From fcd58c134dc532a99dbc19a884b9f3aa9ec70b69 Mon Sep 17 00:00:00 2001 From: XTZGZoReX Date: Mon, 7 Jun 2010 13:57:34 +0200 Subject: * Move VMap3 code to a separate static 'collision' library. --HG-- branch : trunk --- src/server/collision/Maps/TileAssembler.cpp | 494 ++++++++++++++++++++++++++++ 1 file changed, 494 insertions(+) create mode 100644 src/server/collision/Maps/TileAssembler.cpp (limited to 'src/server/collision/Maps/TileAssembler.cpp') diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp new file mode 100644 index 00000000000..d01b54a7564 --- /dev/null +++ b/src/server/collision/Maps/TileAssembler.cpp @@ -0,0 +1,494 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "WorldModel.h" +#include "TileAssembler.h" +#include "MapTree.h" +#include "BIH.h" +#include "VMapDefinitions.h" + +#include +#include +#include +#include + +using G3D::Vector3; +using G3D::AABox; +using G3D::inf; +using std::pair; + +template<> struct BoundsTrait +{ + static void getBounds(const VMAP::ModelSpawn* const &obj, G3D::AABox& out) { out = obj->getBounds(); } +}; + +namespace VMAP +{ + bool readChunk(FILE *rf, char *dest, const char *compare, uint32 len) + { + if (fread(dest, sizeof(char), len, rf) != len) return false; + return memcmp(dest, compare, len) == 0; + } + + Vector3 ModelPosition::transform(const Vector3& pIn) const + { + Vector3 out = pIn * iScale; + out = iRotation * out; + return(out); + } + + //================================================================= + + TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName) + { + iCurrentUniqueNameId = 0; + iFilterMethod = NULL; + iSrcDir = pSrcDirName; + iDestDir = pDestDirName; + //mkdir(iDestDir); + //init(); + } + + TileAssembler::~TileAssembler() + { + //delete iCoordModelMapping; + } + + bool TileAssembler::convertWorld2() + { + std::set spawnedModelFiles; + bool success = readMapSpawns(); + if (!success) + return false; + + // export Map data + for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end() && success; ++map_iter) + { + // build global map tree + std::vector mapSpawns; + UniqueEntryMap::iterator entry; + for (entry = map_iter->second->UniqueEntries.begin(); entry != map_iter->second->UniqueEntries.end(); ++entry) + { + // M2 models don't have a bound set in WDT/ADT placement data, i still think they're not used for LoS at all on retail + if (entry->second.flags & MOD_M2) + { + if (!calculateTransformedBound(entry->second)) + break; + } + else if (entry->second.flags & MOD_WORLDSPAWN) // WMO maps and terrain maps use different origin, so we need to adapt :/ + { + // TODO: remove extractor hack and uncomment below line: + //entry->second.iPos += Vector3(533.33333f*32, 533.33333f*32, 0.f); + entry->second.iBound = entry->second.iBound + Vector3(533.33333f*32, 533.33333f*32, 0.f); + } + mapSpawns.push_back(&(entry->second)); + spawnedModelFiles.insert(entry->second.name); + } + + BIH pTree; + pTree.build(mapSpawns, BoundsTrait::getBounds); + + // ===> possibly move this code to StaticMapTree class + std::map modelNodeIdx; + for (uint32 i=0; i(mapSpawns[i]->ID, i)); + if (!modelNodeIdx.empty()) + printf("min GUID: %u, max GUID: %u\n", modelNodeIdx.begin()->first, modelNodeIdx.rbegin()->first); + + // write map tree file + std::stringstream mapfilename; + mapfilename << iDestDir << "/" << std::setfill('0') << std::setw(3) << map_iter->first << ".vmtree"; + FILE *mapfile = fopen(mapfilename.str().c_str(), "wb"); + if (!mapfile) + { + success = false; + printf("Cannot open %s\n", mapfilename.str().c_str()); + break; + } + + //general info + if (success && fwrite(VMAP_MAGIC, 1, 8, mapfile) != 8) success = false; + uint32 globalTileID = StaticMapTree::packTileID(65, 65); + pair globalRange = map_iter->second->TileEntries.equal_range(globalTileID); + char isTiled = globalRange.first == globalRange.second; // only maps without terrain (tiles) have global WMO + if (success && fwrite(&isTiled, sizeof(char), 1, mapfile) != 1) success = false; + // Nodes + if (success && fwrite("NODE", 4, 1, mapfile) != 1) success = false; + if (success) success = pTree.writeToFile(mapfile); + // global map spawns (WDT), if any (most instances) + if (success && fwrite("GOBJ", 4, 1, mapfile) != 1) success = false; + + for (TileMap::iterator glob=globalRange.first; glob != globalRange.second && success; ++glob) + { + success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second]); + } + + fclose(mapfile); + + // <==== + + // write map tile files, similar to ADT files, only with extra BSP tree node info + TileMap &tileEntries = map_iter->second->TileEntries; + TileMap::iterator tile; + for (tile = tileEntries.begin(); tile != tileEntries.end(); ++tile) + { + const ModelSpawn &spawn = map_iter->second->UniqueEntries[tile->second]; + if (spawn.flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently... + continue; + uint32 nSpawns = tileEntries.count(tile->first); + std::stringstream tilefilename; + tilefilename.fill('0'); + tilefilename << iDestDir << "/" << std::setw(3) << map_iter->first << "_"; + uint32 x, y; + StaticMapTree::unpackTileID(tile->first, x, y); + tilefilename << std::setw(2) << x << "_" << std::setw(2) << y << ".vmtile"; + FILE *tilefile = fopen(tilefilename.str().c_str(), "wb"); + // write number of tile spawns + if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false; + // write tile spawns + for (uint32 s=0; ssecond->UniqueEntries[tile->second]; + success = success && ModelSpawn::writeToFile(tilefile, spawn2); + // MapTree nodes to update when loading tile: + std::map::iterator nIdx = modelNodeIdx.find(spawn2.ID); + if (success && fwrite(&nIdx->second, sizeof(uint32), 1, tilefile) != 1) success = false; + } + fclose(tilefile); + } + // break; //test, extract only first map; TODO: remvoe this line + } + + // export objects + std::cout << "\nConverting Model Files" << std::endl; + for (std::set::iterator mfile = spawnedModelFiles.begin(); mfile != spawnedModelFiles.end(); ++mfile) + { + std::cout << "Converting " << *mfile << std::endl; + if (!convertRawFile(*mfile)) + { + std::cout << "error converting " << *mfile << std::endl; + success = false; + break; + } + } + + //cleanup: + for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end(); ++map_iter) + { + delete map_iter->second; + } + return success; + } + + bool TileAssembler::readMapSpawns() + { + std::string fname = iSrcDir + "/dir_bin"; + FILE *dirf = fopen(fname.c_str(), "rb"); + if (!dirf) + { + printf("Could not read dir_bin file!\n"); + return false; + } + printf("Read coordinate mapping...\n"); + uint32 mapID, tileX, tileY, check=0; + G3D::Vector3 v1, v2; + ModelSpawn spawn; + while (!feof(dirf)) + { + check = 0; + // read mapID, tileX, tileY, Flags, adtID, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name + check += fread(&mapID, sizeof(uint32), 1, dirf); + if (check == 0) // EoF... + break; + check += fread(&tileX, sizeof(uint32), 1, dirf); + check += fread(&tileY, sizeof(uint32), 1, dirf); + if (!ModelSpawn::readFromFile(dirf, spawn)) + break; + + MapSpawns *current; + MapData::iterator map_iter = mapData.find(mapID); + if (map_iter == mapData.end()) + { + printf("spawning Map %d\n", mapID); + mapData[mapID] = current = new MapSpawns(); + } + else current = (*map_iter).second; + current->UniqueEntries.insert(pair(spawn.ID, spawn)); + current->TileEntries.insert(pair(StaticMapTree::packTileID(tileX, tileY), spawn.ID)); + } + bool success = (ferror(dirf) == 0); + fclose(dirf); + return success; + } + + bool TileAssembler::calculateTransformedBound(ModelSpawn &spawn) + { + std::string modelFilename = iSrcDir + "/" + spawn.name; + ModelPosition modelPosition; + modelPosition.iDir = spawn.iRot; + modelPosition.iScale = spawn.iScale; + modelPosition.init(); + + FILE *rf = fopen(modelFilename.c_str(), "rb"); + if (!rf) + { + printf("ERROR: Can't open model file: %s\n", modelFilename.c_str()); + return false; + } + + AABox modelBound; + bool boundEmpty=true; + char ident[8]; + + int readOperation = 1; + + // temporary use defines to simplify read/check code (close file and return at fail) + #define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \ + fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); }readOperation++; + #define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \ + fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); } + + READ_OR_RETURN(&ident, 8); + CMP_OR_RETURN(ident, "VMAP003"); + + // we have to read one int. This is needed during the export and we have to skip it here + uint32 tempNVectors; + READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors)); + + uint32 groups, wmoRootId; + char blockId[5]; + blockId[4] = 0; + int blocksize; + float *vectorarray = 0; + + READ_OR_RETURN(&groups, sizeof(uint32)); + READ_OR_RETURN(&wmoRootId, sizeof(uint32)); + if (groups != 1) printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str()); + + for (uint32 g=0; g0) + { + vectorarray = new float[nvectors*3]; + READ_OR_RETURN(vectorarray, nvectors*sizeof(float)*3); + } + else + { + std::cout << "error: model '" << spawn.name << "' has no geometry!" << std::endl; + return false; + } + + for (uint32 i=0, indexNo=0; indexNo0) + filename.append("/"); + filename.append(pModelFilename); + FILE *rf = fopen(filename.c_str(), "rb"); + + if (!rf) + { + printf("ERROR: Can't open model file in form: %s",pModelFilename.c_str()); + printf("... or form: %s",filename.c_str() ); + return false; + } + + char ident[8]; + + int readOperation = 1; + + // temporary use defines to simplify read/check code (close file and return at fail) + #define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \ + fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); }readOperation++; + #define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \ + fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); } + + READ_OR_RETURN(&ident, 8); + CMP_OR_RETURN(ident, "VMAP003"); + + // we have to read one int. This is needed during the export and we have to skip it here + uint32 tempNVectors; + READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors)); + + uint32 groups; + uint32 RootWMOID; + char blockId[5]; + blockId[4] = 0; + int blocksize; + + READ_OR_RETURN(&groups, sizeof(uint32)); + READ_OR_RETURN(&RootWMOID, sizeof(uint32)); + + std::vector groupsArray; + + for (uint32 g=0; g triangles; + std::vector vertexArray; + + uint32 mogpflags, GroupWMOID; + READ_OR_RETURN(&mogpflags, sizeof(uint32)); + READ_OR_RETURN(&GroupWMOID, sizeof(uint32)); + + float bbox1[3], bbox2[3]; + READ_OR_RETURN(bbox1, sizeof(float)*3); + READ_OR_RETURN(bbox2, sizeof(float)*3); + + uint32 liquidflags; + READ_OR_RETURN(&liquidflags, sizeof(uint32)); + + // will this ever be used? what is it good for anyway?? + uint32 branches; + READ_OR_RETURN(&blockId, 4); + CMP_OR_RETURN(blockId, "GRP "); + READ_OR_RETURN(&blocksize, sizeof(int)); + READ_OR_RETURN(&branches, sizeof(uint32)); + for (uint32 b=0; b0) + { + uint16 *indexarray = new uint16[nindexes]; + READ_OR_RETURN(indexarray, nindexes*sizeof(uint16)); + for (uint32 i=0; i0) + { + float *vectorarray = new float[nvectors*3]; + READ_OR_RETURN(vectorarray, nvectors*sizeof(float)*3); + for (uint32 i=0; iGetHeightStorage(), size*sizeof(float)); + size = hlq.xtiles*hlq.ytiles; + READ_OR_RETURN(liquid->GetFlagsStorage(), size); + } + + groupsArray.push_back(GroupModel(mogpflags, GroupWMOID, AABox(Vector3(bbox1), Vector3(bbox2)))); + groupsArray.back().setMeshData(vertexArray, triangles); + groupsArray.back().setLiquidData(liquid); + + // drop of temporary use defines + #undef READ_OR_RETURN + #undef CMP_OR_RETURN + + } + fclose(rf); + + // write WorldModel + WorldModel model; + model.setRootWmoID(RootWMOID); + if (groupsArray.size()) + { + model.setGroupModels(groupsArray); + success = model.writeFile(iDestDir + "/" + pModelFilename + ".vmo"); + } + + //std::cout << "readRawFile2: '" << pModelFilename << "' tris: " << nElements << " nodes: " << nNodes << std::endl; + return success; + } +} -- cgit v1.2.3 From 1fd70827128177aba3ac1334135fc12422819db0 Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 7 Jun 2010 18:32:20 -0600 Subject: * Reverted to the old G3D library, however collision still will not compile * and is therefore commented out. --HG-- branch : trunk --- externals/PackageList.txt | 2 +- externals/g3dlite/G3D.lib/include/G3D/AABSPTree.h | 1609 --------------- externals/g3dlite/G3D.lib/include/G3D/AABox.h | 281 --- externals/g3dlite/G3D.lib/include/G3D/AnyVal.h | 506 ----- externals/g3dlite/G3D.lib/include/G3D/Array.h | 1180 ----------- .../g3dlite/G3D.lib/include/G3D/AtomicInt32.h | 166 -- .../g3dlite/G3D.lib/include/G3D/BinaryFormat.h | 140 -- .../g3dlite/G3D.lib/include/G3D/BinaryInput.h | 441 ---- .../g3dlite/G3D.lib/include/G3D/BinaryOutput.h | 421 ---- .../g3dlite/G3D.lib/include/G3D/BoundsTrait.h | 20 - externals/g3dlite/G3D.lib/include/G3D/Box.h | 193 -- externals/g3dlite/G3D.lib/include/G3D/Capsule.h | 90 - .../G3D.lib/include/G3D/CollisionDetection.h | 1178 ----------- externals/g3dlite/G3D.lib/include/G3D/Color1.h | 129 -- .../g3dlite/G3D.lib/include/G3D/Color1uint8.h | 107 - externals/g3dlite/G3D.lib/include/G3D/Color3.h | 390 ---- .../g3dlite/G3D.lib/include/G3D/Color3uint8.h | 127 -- externals/g3dlite/G3D.lib/include/G3D/Color4.h | 324 --- .../g3dlite/G3D.lib/include/G3D/Color4uint8.h | 133 -- externals/g3dlite/G3D.lib/include/G3D/Cone.h | 68 - .../g3dlite/G3D.lib/include/G3D/ConvexPolyhedron.h | 179 -- .../g3dlite/G3D.lib/include/G3D/CoordinateFrame.h | 315 --- externals/g3dlite/G3D.lib/include/G3D/Crypto.h | 96 - externals/g3dlite/G3D.lib/include/G3D/Cylinder.h | 92 - externals/g3dlite/G3D.lib/include/G3D/Discovery.h | 589 ------ .../g3dlite/G3D.lib/include/G3D/EqualsTrait.h | 26 - externals/g3dlite/G3D.lib/include/G3D/G3D.h | 150 -- externals/g3dlite/G3D.lib/include/G3D/G3DAll.h | 26 - .../g3dlite/G3D.lib/include/G3D/G3DGameUnits.h | 44 - externals/g3dlite/G3D.lib/include/G3D/GCamera.h | 294 --- externals/g3dlite/G3D.lib/include/G3D/GImage.h | 550 ----- externals/g3dlite/G3D.lib/include/G3D/GLight.h | 72 - externals/g3dlite/G3D.lib/include/G3D/GThread.h | 169 -- externals/g3dlite/G3D.lib/include/G3D/GUniqueID.h | 69 - externals/g3dlite/G3D.lib/include/G3D/HashTrait.h | 63 - externals/g3dlite/G3D.lib/include/G3D/Image1.h | 79 - .../g3dlite/G3D.lib/include/G3D/Image1uint8.h | 80 - externals/g3dlite/G3D.lib/include/G3D/Image3.h | 79 - .../g3dlite/G3D.lib/include/G3D/Image3uint8.h | 85 - externals/g3dlite/G3D.lib/include/G3D/Image4.h | 80 - .../g3dlite/G3D.lib/include/G3D/Image4uint8.h | 85 - .../g3dlite/G3D.lib/include/G3D/ImageFormat.h | 362 ---- externals/g3dlite/G3D.lib/include/G3D/Line.h | 105 - .../g3dlite/G3D.lib/include/G3D/LineSegment.h | 115 -- externals/g3dlite/G3D.lib/include/G3D/Log.h | 109 - externals/g3dlite/G3D.lib/include/G3D/Map2D.h | 665 ------ externals/g3dlite/G3D.lib/include/G3D/Matrix.h | 634 ------ externals/g3dlite/G3D.lib/include/G3D/Matrix2.h | 69 - externals/g3dlite/G3D.lib/include/G3D/Matrix3.h | 323 --- externals/g3dlite/G3D.lib/include/G3D/Matrix4.h | 206 -- externals/g3dlite/G3D.lib/include/G3D/MeshAlg.h | 718 ------- .../g3dlite/G3D.lib/include/G3D/MeshBuilder.h | 82 - externals/g3dlite/G3D.lib/include/G3D/NetAddress.h | 132 -- .../g3dlite/G3D.lib/include/G3D/NetworkDevice.h | 738 ------- .../g3dlite/G3D.lib/include/G3D/PhysicsFrame.h | 74 - externals/g3dlite/G3D.lib/include/G3D/Plane.h | 161 -- .../g3dlite/G3D.lib/include/G3D/PointAABSPTree.h | 1207 ----------- .../g3dlite/G3D.lib/include/G3D/PointHashGrid.h | 894 -------- externals/g3dlite/G3D.lib/include/G3D/Pointer.h | 275 --- .../g3dlite/G3D.lib/include/G3D/PositionTrait.h | 7 - externals/g3dlite/G3D.lib/include/G3D/Quat.h | 725 ------- externals/g3dlite/G3D.lib/include/G3D/Queue.h | 355 ---- externals/g3dlite/G3D.lib/include/G3D/Ray.h | 329 --- externals/g3dlite/G3D.lib/include/G3D/Rect2D.h | 391 ---- .../g3dlite/G3D.lib/include/G3D/ReferenceCount.h | 597 ------ .../g3dlite/G3D.lib/include/G3D/RegistryUtil.h | 97 - externals/g3dlite/G3D.lib/include/G3D/Set.h | 160 -- externals/g3dlite/G3D.lib/include/G3D/Sphere.h | 143 -- externals/g3dlite/G3D.lib/include/G3D/Spline.h | 367 ---- externals/g3dlite/G3D.lib/include/G3D/Stopwatch.h | 108 - externals/g3dlite/G3D.lib/include/G3D/System.h | 390 ---- externals/g3dlite/G3D.lib/include/G3D/Table.h | 770 ------- externals/g3dlite/G3D.lib/include/G3D/TextInput.h | 693 ------- externals/g3dlite/G3D.lib/include/G3D/TextOutput.h | 249 --- externals/g3dlite/G3D.lib/include/G3D/ThreadSet.h | 79 - externals/g3dlite/G3D.lib/include/G3D/Triangle.h | 143 -- .../g3dlite/G3D.lib/include/G3D/UprightFrame.h | 83 - externals/g3dlite/G3D.lib/include/G3D/Vector2.h | 457 ----- .../g3dlite/G3D.lib/include/G3D/Vector2int16.h | 137 -- externals/g3dlite/G3D.lib/include/G3D/Vector3.h | 761 ------- .../g3dlite/G3D.lib/include/G3D/Vector3int16.h | 130 -- .../g3dlite/G3D.lib/include/G3D/Vector3int32.h | 138 -- externals/g3dlite/G3D.lib/include/G3D/Vector4.h | 717 ------- .../g3dlite/G3D.lib/include/G3D/Vector4int8.h | 113 - externals/g3dlite/G3D.lib/include/G3D/WeakCache.h | 90 - externals/g3dlite/G3D.lib/include/G3D/WrapMode.h | 79 - externals/g3dlite/G3D.lib/include/G3D/debug.h | 66 - .../g3dlite/G3D.lib/include/G3D/debugAssert.h | 236 --- .../g3dlite/G3D.lib/include/G3D/debugPrintf.h | 62 - externals/g3dlite/G3D.lib/include/G3D/enumclass.h | 141 -- externals/g3dlite/G3D.lib/include/G3D/fileutils.h | 246 --- externals/g3dlite/G3D.lib/include/G3D/filter.h | 29 - externals/g3dlite/G3D.lib/include/G3D/format.h | 44 - externals/g3dlite/G3D.lib/include/G3D/g3dmath.h | 810 -------- externals/g3dlite/G3D.lib/include/G3D/platform.h | 256 --- externals/g3dlite/G3D.lib/include/G3D/prompt.h | 67 - externals/g3dlite/G3D.lib/include/G3D/serialize.h | 30 - externals/g3dlite/G3D.lib/include/G3D/splinefunc.h | 118 -- .../g3dlite/G3D.lib/include/G3D/stringutils.h | 130 -- externals/g3dlite/G3D.lib/include/G3D/uint128.h | 51 - externals/g3dlite/G3D.lib/include/G3D/vectorMath.h | 235 --- externals/g3dlite/G3D.lib/source/AABox.cpp | 342 ---- externals/g3dlite/G3D.lib/source/AnyVal.cpp | 1381 ------------- externals/g3dlite/G3D.lib/source/BinaryFormat.cpp | 81 - externals/g3dlite/G3D.lib/source/BinaryInput.cpp | 568 ------ externals/g3dlite/G3D.lib/source/BinaryOutput.cpp | 518 ----- externals/g3dlite/G3D.lib/source/Box.cpp | 393 ---- externals/g3dlite/G3D.lib/source/Capsule.cpp | 179 -- .../g3dlite/G3D.lib/source/CollisionDetection.cpp | 2152 -------------------- externals/g3dlite/G3D.lib/source/Color1.cpp | 40 - externals/g3dlite/G3D.lib/source/Color1uint8.cpp | 38 - externals/g3dlite/G3D.lib/source/Color3.cpp | 321 --- externals/g3dlite/G3D.lib/source/Color3uint8.cpp | 45 - externals/g3dlite/G3D.lib/source/Color4.cpp | 140 -- externals/g3dlite/G3D.lib/source/Color4uint8.cpp | 47 - externals/g3dlite/G3D.lib/source/Cone.cpp | 79 - .../g3dlite/G3D.lib/source/ConvexPolyhedron.cpp | 449 ---- .../g3dlite/G3D.lib/source/CoordinateFrame.cpp | 381 ---- externals/g3dlite/G3D.lib/source/Crypto.cpp | 70 - externals/g3dlite/G3D.lib/source/Crypto_md5.cpp | 471 ----- externals/g3dlite/G3D.lib/source/Cylinder.cpp | 176 -- externals/g3dlite/G3D.lib/source/Discovery.cpp | 170 -- externals/g3dlite/G3D.lib/source/GCamera.cpp | 399 ---- externals/g3dlite/G3D.lib/source/GImage.cpp | 1065 ---------- externals/g3dlite/G3D.lib/source/GImage_bayer.cpp | 298 --- externals/g3dlite/G3D.lib/source/GImage_bmp.cpp | 716 ------- externals/g3dlite/G3D.lib/source/GImage_jpeg.cpp | 445 ---- externals/g3dlite/G3D.lib/source/GImage_png.cpp | 245 --- externals/g3dlite/G3D.lib/source/GImage_ppm.cpp | 185 -- externals/g3dlite/G3D.lib/source/GImage_tga.cpp | 179 -- externals/g3dlite/G3D.lib/source/GLight.cpp | 143 -- externals/g3dlite/G3D.lib/source/GThread.cpp | 203 -- externals/g3dlite/G3D.lib/source/GUniqueID.cpp | 78 - externals/g3dlite/G3D.lib/source/Image1.cpp | 224 -- externals/g3dlite/G3D.lib/source/Image1uint8.cpp | 212 -- externals/g3dlite/G3D.lib/source/Image3.cpp | 224 -- externals/g3dlite/G3D.lib/source/Image3uint8.cpp | 225 -- externals/g3dlite/G3D.lib/source/Image4.cpp | 226 -- externals/g3dlite/G3D.lib/source/Image4uint8.cpp | 222 -- externals/g3dlite/G3D.lib/source/ImageFormat.cpp | 440 ---- .../g3dlite/G3D.lib/source/ImageFormat_convert.cpp | 1305 ------------ externals/g3dlite/G3D.lib/source/Line.cpp | 89 - externals/g3dlite/G3D.lib/source/LineSegment.cpp | 236 --- externals/g3dlite/G3D.lib/source/Log.cpp | 157 -- externals/g3dlite/G3D.lib/source/Matrix.cpp | 1801 ---------------- externals/g3dlite/G3D.lib/source/Matrix3.cpp | 1725 ---------------- externals/g3dlite/G3D.lib/source/Matrix4.cpp | 433 ---- externals/g3dlite/G3D.lib/source/MeshAlg.cpp | 733 ------- .../g3dlite/G3D.lib/source/MeshAlgAdjacency.cpp | 729 ------- externals/g3dlite/G3D.lib/source/MeshAlgWeld.cpp | 213 -- externals/g3dlite/G3D.lib/source/MeshAlgWeld2.cpp | 377 ---- externals/g3dlite/G3D.lib/source/MeshBuilder.cpp | 113 - externals/g3dlite/G3D.lib/source/NetAddress.cpp | 164 -- externals/g3dlite/G3D.lib/source/NetworkDevice.cpp | 1362 ------------- externals/g3dlite/G3D.lib/source/PhysicsFrame.cpp | 77 - externals/g3dlite/G3D.lib/source/Plane.cpp | 149 -- externals/g3dlite/G3D.lib/source/Quat.cpp | 583 ------ externals/g3dlite/G3D.lib/source/Ray.cpp | 112 - externals/g3dlite/G3D.lib/source/RegistryUtil.cpp | 290 --- externals/g3dlite/G3D.lib/source/Sphere.cpp | 196 -- externals/g3dlite/G3D.lib/source/SplineBase.cpp | 162 -- externals/g3dlite/G3D.lib/source/Stopwatch.cpp | 96 - externals/g3dlite/G3D.lib/source/System.cpp | 1864 ----------------- externals/g3dlite/G3D.lib/source/TextInput.cpp | 988 --------- externals/g3dlite/G3D.lib/source/TextOutput.cpp | 452 ---- externals/g3dlite/G3D.lib/source/ThreadSet.cpp | 147 -- externals/g3dlite/G3D.lib/source/Triangle.cpp | 135 -- externals/g3dlite/G3D.lib/source/UprightFrame.cpp | 132 -- externals/g3dlite/G3D.lib/source/Vector2.cpp | 211 -- externals/g3dlite/G3D.lib/source/Vector2int16.cpp | 47 - externals/g3dlite/G3D.lib/source/Vector3.cpp | 493 ----- externals/g3dlite/G3D.lib/source/Vector3int16.cpp | 49 - externals/g3dlite/G3D.lib/source/Vector3int32.cpp | 57 - externals/g3dlite/G3D.lib/source/Vector4.cpp | 475 ----- externals/g3dlite/G3D.lib/source/Vector4int8.cpp | 58 - externals/g3dlite/G3D.lib/source/WinMain.cpp | 155 -- externals/g3dlite/G3D.lib/source/debugAssert.cpp | 392 ---- externals/g3dlite/G3D.lib/source/fileutils.cpp | 1092 ---------- externals/g3dlite/G3D.lib/source/filter.cpp | 32 - externals/g3dlite/G3D.lib/source/format.cpp | 164 -- externals/g3dlite/G3D.lib/source/g3dmath.cpp | 70 - externals/g3dlite/G3D.lib/source/license.cpp | 70 - externals/g3dlite/G3D.lib/source/prompt.cpp | 716 ------- externals/g3dlite/G3D.lib/source/stringutils.cpp | 231 --- externals/g3dlite/G3D.lib/source/uint128.cpp | 155 -- externals/g3dlite/G3D/AABox.h | 272 +++ externals/g3dlite/G3D/Any.h | 570 ++++++ externals/g3dlite/G3D/AnyVal.h | 512 +++++ externals/g3dlite/G3D/AreaMemoryManager.h | 93 + externals/g3dlite/G3D/Array.h | 1274 ++++++++++++ externals/g3dlite/G3D/AtomicInt32.h | 164 ++ externals/g3dlite/G3D/BinaryFormat.h | 140 ++ externals/g3dlite/G3D/BinaryInput.h | 441 ++++ externals/g3dlite/G3D/BinaryOutput.h | 421 ++++ externals/g3dlite/G3D/BoundsTrait.h | 20 + externals/g3dlite/G3D/Box.h | 195 ++ externals/g3dlite/G3D/Box2D.h | 121 ++ externals/g3dlite/G3D/BumpMapPreprocess.h | 61 + externals/g3dlite/G3D/Capsule.h | 90 + externals/g3dlite/G3D/CollisionDetection.h | 1205 +++++++++++ externals/g3dlite/G3D/Color1.h | 144 ++ externals/g3dlite/G3D/Color1uint8.h | 91 + externals/g3dlite/G3D/Color3.h | 432 ++++ externals/g3dlite/G3D/Color3uint8.h | 110 + externals/g3dlite/G3D/Color4.h | 338 +++ externals/g3dlite/G3D/Color4uint8.h | 115 ++ externals/g3dlite/G3D/Cone.h | 68 + externals/g3dlite/G3D/ConvexPolyhedron.h | 180 ++ externals/g3dlite/G3D/CoordinateFrame.h | 331 +++ externals/g3dlite/G3D/Crypto.h | 96 + externals/g3dlite/G3D/Cylinder.h | 92 + externals/g3dlite/G3D/EqualsTrait.h | 26 + externals/g3dlite/G3D/G3D.h | 162 ++ externals/g3dlite/G3D/G3DAll.h | 26 + externals/g3dlite/G3D/G3DGameUnits.h | 42 + externals/g3dlite/G3D/GCamera.h | 337 +++ externals/g3dlite/G3D/GImage.h | 607 ++++++ externals/g3dlite/G3D/GLight.h | 106 + externals/g3dlite/G3D/GMutex.h | 123 ++ externals/g3dlite/G3D/GThread.h | 121 ++ externals/g3dlite/G3D/GUniqueID.h | 69 + externals/g3dlite/G3D/HashTrait.h | 92 + externals/g3dlite/G3D/Image1.h | 81 + externals/g3dlite/G3D/Image1uint8.h | 80 + externals/g3dlite/G3D/Image3.h | 81 + externals/g3dlite/G3D/Image3uint8.h | 85 + externals/g3dlite/G3D/Image4.h | 86 + externals/g3dlite/G3D/Image4uint8.h | 85 + externals/g3dlite/G3D/ImageFormat.h | 419 ++++ externals/g3dlite/G3D/Intersect.h | 55 + externals/g3dlite/G3D/KDTree.h | 1667 +++++++++++++++ externals/g3dlite/G3D/Line.h | 105 + externals/g3dlite/G3D/LineSegment.h | 115 ++ externals/g3dlite/G3D/Log.h | 109 + externals/g3dlite/G3D/Map2D.h | 667 ++++++ externals/g3dlite/G3D/Matrix.h | 634 ++++++ externals/g3dlite/G3D/Matrix2.h | 69 + externals/g3dlite/G3D/Matrix3.h | 366 ++++ externals/g3dlite/G3D/Matrix4.h | 249 +++ externals/g3dlite/G3D/MemoryManager.h | 93 + externals/g3dlite/G3D/MeshAlg.h | 683 +++++++ externals/g3dlite/G3D/MeshBuilder.h | 82 + externals/g3dlite/G3D/NetAddress.h | 132 ++ externals/g3dlite/G3D/NetworkDevice.h | 738 +++++++ externals/g3dlite/G3D/ParseError.h | 59 + externals/g3dlite/G3D/PhysicsFrame.h | 74 + externals/g3dlite/G3D/Plane.h | 161 ++ externals/g3dlite/G3D/PointHashGrid.h | 917 +++++++++ externals/g3dlite/G3D/PointKDTree.h | 1185 +++++++++++ externals/g3dlite/G3D/Pointer.h | 292 +++ externals/g3dlite/G3D/PositionTrait.h | 7 + externals/g3dlite/G3D/PrecomputedRandom.h | 110 + externals/g3dlite/G3D/Quat.h | 725 +++++++ externals/g3dlite/G3D/Quat.inl | 36 + externals/g3dlite/G3D/Queue.h | 364 ++++ externals/g3dlite/G3D/Random.h | 139 ++ externals/g3dlite/G3D/Ray.h | 371 ++++ externals/g3dlite/G3D/Rect2D.h | 417 ++++ externals/g3dlite/G3D/ReferenceCount.h | 570 ++++++ externals/g3dlite/G3D/RegistryUtil.h | 97 + externals/g3dlite/G3D/Set.h | 186 ++ externals/g3dlite/G3D/SmallArray.h | 155 ++ externals/g3dlite/G3D/Sphere.h | 148 ++ externals/g3dlite/G3D/Spline.h | 367 ++++ externals/g3dlite/G3D/Stopwatch.h | 144 ++ externals/g3dlite/G3D/System.h | 507 +++++ externals/g3dlite/G3D/Table.h | 924 +++++++++ externals/g3dlite/G3D/TextInput.h | 801 ++++++++ externals/g3dlite/G3D/TextOutput.h | 249 +++ externals/g3dlite/G3D/ThreadSet.h | 87 + externals/g3dlite/G3D/Triangle.h | 160 ++ externals/g3dlite/G3D/UprightFrame.h | 83 + externals/g3dlite/G3D/Vector2.h | 454 +++++ externals/g3dlite/G3D/Vector2.inl | 18 + externals/g3dlite/G3D/Vector2int16.h | 127 ++ externals/g3dlite/G3D/Vector3.h | 798 ++++++++ externals/g3dlite/G3D/Vector3.inl | 249 +++ externals/g3dlite/G3D/Vector3int16.h | 127 ++ externals/g3dlite/G3D/Vector3int32.h | 128 ++ externals/g3dlite/G3D/Vector4.h | 716 +++++++ externals/g3dlite/G3D/Vector4.inl | 191 ++ externals/g3dlite/G3D/Vector4int8.h | 113 + externals/g3dlite/G3D/WeakCache.h | 122 ++ externals/g3dlite/G3D/Welder.h | 82 + externals/g3dlite/G3D/WrapMode.h | 93 + externals/g3dlite/G3D/constants.h | 129 ++ externals/g3dlite/G3D/debug.h | 66 + externals/g3dlite/G3D/debugAssert.h | 233 +++ externals/g3dlite/G3D/debugPrintf.h | 62 + externals/g3dlite/G3D/enumclass.h | 147 ++ externals/g3dlite/G3D/fileutils.h | 254 +++ externals/g3dlite/G3D/filter.h | 29 + externals/g3dlite/G3D/format.h | 44 + externals/g3dlite/G3D/g3dfnmatch.h | 83 + externals/g3dlite/G3D/g3dmath.h | 845 ++++++++ externals/g3dlite/G3D/g3dmath.inl | 288 +++ externals/g3dlite/G3D/platform.h | 331 +++ externals/g3dlite/G3D/prompt.h | 67 + externals/g3dlite/G3D/serialize.h | 30 + externals/g3dlite/G3D/splinefunc.h | 118 ++ externals/g3dlite/G3D/stringutils.h | 140 ++ externals/g3dlite/G3D/uint128.h | 51 + externals/g3dlite/G3D/units.h | 126 ++ externals/g3dlite/G3D/vectorMath.h | 235 +++ externals/g3dlite/doc-files/changelog.dox | 1872 ----------------- externals/g3dlite/doc-files/contributors.dox | 85 - externals/g3dlite/doc-files/license.dox | 120 -- externals/g3dlite/win/VC90/g3dlite.vcproj | 463 ----- externals/g3dlite/win/g3dlite.sln | 25 - externals/g3dlite/zip.lib/include/zip/ioapi.h | 75 - externals/g3dlite/zip.lib/include/zip/unzip.h | 354 ---- externals/g3dlite/zip.lib/include/zip/zip.h | 235 --- externals/g3dlite/zip.lib/source/crypt.h | 132 -- externals/g3dlite/zip.lib/source/ioapi.c | 177 -- externals/g3dlite/zip.lib/source/iowin32.c | 272 --- externals/g3dlite/zip.lib/source/iowin32.h | 23 - externals/g3dlite/zip.lib/source/unzip.c | 1604 --------------- externals/g3dlite/zip.lib/source/zip.c | 1221 ----------- src/server/collision/BoundingIntervalHierarchy.h | 8 +- src/server/collision/CMakeLists.txt | 5 +- src/server/collision/Management/VMapManager2.h | 4 +- src/server/collision/Maps/TileAssembler.cpp | 2 +- 322 files changed, 31809 insertions(+), 68149 deletions(-) delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/AABSPTree.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/AABox.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/AnyVal.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Array.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/AtomicInt32.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/BinaryFormat.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/BinaryInput.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/BinaryOutput.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/BoundsTrait.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Box.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Capsule.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/CollisionDetection.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Color1.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Color1uint8.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Color3.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Color3uint8.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Color4.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Color4uint8.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Cone.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/ConvexPolyhedron.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/CoordinateFrame.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Crypto.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Cylinder.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Discovery.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/EqualsTrait.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/G3D.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/G3DAll.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/G3DGameUnits.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/GCamera.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/GImage.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/GLight.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/GThread.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/GUniqueID.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/HashTrait.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Image1.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Image1uint8.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Image3.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Image3uint8.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Image4.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Image4uint8.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/ImageFormat.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Line.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/LineSegment.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Log.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Map2D.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Matrix.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Matrix2.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Matrix3.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Matrix4.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/MeshAlg.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/MeshBuilder.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/NetAddress.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/NetworkDevice.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/PhysicsFrame.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Plane.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/PointAABSPTree.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/PointHashGrid.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Pointer.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/PositionTrait.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Quat.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Queue.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Ray.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Rect2D.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/ReferenceCount.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/RegistryUtil.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Set.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Sphere.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Spline.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Stopwatch.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/System.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Table.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/TextInput.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/TextOutput.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/ThreadSet.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Triangle.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/UprightFrame.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Vector2.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Vector2int16.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Vector3.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Vector3int16.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Vector3int32.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Vector4.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/Vector4int8.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/WeakCache.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/WrapMode.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/debug.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/debugAssert.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/debugPrintf.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/enumclass.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/fileutils.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/filter.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/format.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/g3dmath.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/platform.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/prompt.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/serialize.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/splinefunc.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/stringutils.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/uint128.h delete mode 100644 externals/g3dlite/G3D.lib/include/G3D/vectorMath.h delete mode 100644 externals/g3dlite/G3D.lib/source/AABox.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/AnyVal.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/BinaryFormat.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/BinaryInput.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/BinaryOutput.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Box.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Capsule.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/CollisionDetection.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Color1.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Color1uint8.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Color3.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Color3uint8.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Color4.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Color4uint8.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Cone.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/ConvexPolyhedron.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/CoordinateFrame.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Crypto.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Crypto_md5.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Cylinder.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Discovery.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/GCamera.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/GImage.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/GImage_bayer.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/GImage_bmp.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/GImage_jpeg.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/GImage_png.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/GImage_ppm.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/GImage_tga.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/GLight.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/GThread.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/GUniqueID.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Image1.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Image1uint8.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Image3.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Image3uint8.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Image4.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Image4uint8.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/ImageFormat.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/ImageFormat_convert.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Line.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/LineSegment.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Log.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Matrix.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Matrix3.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Matrix4.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/MeshAlg.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/MeshAlgAdjacency.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/MeshAlgWeld.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/MeshAlgWeld2.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/MeshBuilder.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/NetAddress.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/NetworkDevice.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/PhysicsFrame.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Plane.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Quat.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Ray.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/RegistryUtil.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Sphere.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/SplineBase.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Stopwatch.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/System.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/TextInput.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/TextOutput.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/ThreadSet.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Triangle.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/UprightFrame.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Vector2.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Vector2int16.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Vector3.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Vector3int16.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Vector3int32.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Vector4.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/Vector4int8.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/WinMain.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/debugAssert.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/fileutils.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/filter.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/format.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/g3dmath.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/license.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/prompt.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/stringutils.cpp delete mode 100644 externals/g3dlite/G3D.lib/source/uint128.cpp create mode 100644 externals/g3dlite/G3D/AABox.h create mode 100644 externals/g3dlite/G3D/Any.h create mode 100644 externals/g3dlite/G3D/AnyVal.h create mode 100644 externals/g3dlite/G3D/AreaMemoryManager.h create mode 100644 externals/g3dlite/G3D/Array.h create mode 100644 externals/g3dlite/G3D/AtomicInt32.h create mode 100644 externals/g3dlite/G3D/BinaryFormat.h create mode 100644 externals/g3dlite/G3D/BinaryInput.h create mode 100644 externals/g3dlite/G3D/BinaryOutput.h create mode 100644 externals/g3dlite/G3D/BoundsTrait.h create mode 100644 externals/g3dlite/G3D/Box.h create mode 100644 externals/g3dlite/G3D/Box2D.h create mode 100644 externals/g3dlite/G3D/BumpMapPreprocess.h create mode 100644 externals/g3dlite/G3D/Capsule.h create mode 100644 externals/g3dlite/G3D/CollisionDetection.h create mode 100644 externals/g3dlite/G3D/Color1.h create mode 100644 externals/g3dlite/G3D/Color1uint8.h create mode 100644 externals/g3dlite/G3D/Color3.h create mode 100644 externals/g3dlite/G3D/Color3uint8.h create mode 100644 externals/g3dlite/G3D/Color4.h create mode 100644 externals/g3dlite/G3D/Color4uint8.h create mode 100644 externals/g3dlite/G3D/Cone.h create mode 100644 externals/g3dlite/G3D/ConvexPolyhedron.h create mode 100644 externals/g3dlite/G3D/CoordinateFrame.h create mode 100644 externals/g3dlite/G3D/Crypto.h create mode 100644 externals/g3dlite/G3D/Cylinder.h create mode 100644 externals/g3dlite/G3D/EqualsTrait.h create mode 100644 externals/g3dlite/G3D/G3D.h create mode 100644 externals/g3dlite/G3D/G3DAll.h create mode 100644 externals/g3dlite/G3D/G3DGameUnits.h create mode 100644 externals/g3dlite/G3D/GCamera.h create mode 100644 externals/g3dlite/G3D/GImage.h create mode 100644 externals/g3dlite/G3D/GLight.h create mode 100644 externals/g3dlite/G3D/GMutex.h create mode 100644 externals/g3dlite/G3D/GThread.h create mode 100644 externals/g3dlite/G3D/GUniqueID.h create mode 100644 externals/g3dlite/G3D/HashTrait.h create mode 100644 externals/g3dlite/G3D/Image1.h create mode 100644 externals/g3dlite/G3D/Image1uint8.h create mode 100644 externals/g3dlite/G3D/Image3.h create mode 100644 externals/g3dlite/G3D/Image3uint8.h create mode 100644 externals/g3dlite/G3D/Image4.h create mode 100644 externals/g3dlite/G3D/Image4uint8.h create mode 100644 externals/g3dlite/G3D/ImageFormat.h create mode 100644 externals/g3dlite/G3D/Intersect.h create mode 100644 externals/g3dlite/G3D/KDTree.h create mode 100644 externals/g3dlite/G3D/Line.h create mode 100644 externals/g3dlite/G3D/LineSegment.h create mode 100644 externals/g3dlite/G3D/Log.h create mode 100644 externals/g3dlite/G3D/Map2D.h create mode 100644 externals/g3dlite/G3D/Matrix.h create mode 100644 externals/g3dlite/G3D/Matrix2.h create mode 100644 externals/g3dlite/G3D/Matrix3.h create mode 100644 externals/g3dlite/G3D/Matrix4.h create mode 100644 externals/g3dlite/G3D/MemoryManager.h create mode 100644 externals/g3dlite/G3D/MeshAlg.h create mode 100644 externals/g3dlite/G3D/MeshBuilder.h create mode 100644 externals/g3dlite/G3D/NetAddress.h create mode 100644 externals/g3dlite/G3D/NetworkDevice.h create mode 100644 externals/g3dlite/G3D/ParseError.h create mode 100644 externals/g3dlite/G3D/PhysicsFrame.h create mode 100644 externals/g3dlite/G3D/Plane.h create mode 100644 externals/g3dlite/G3D/PointHashGrid.h create mode 100644 externals/g3dlite/G3D/PointKDTree.h create mode 100644 externals/g3dlite/G3D/Pointer.h create mode 100644 externals/g3dlite/G3D/PositionTrait.h create mode 100644 externals/g3dlite/G3D/PrecomputedRandom.h create mode 100644 externals/g3dlite/G3D/Quat.h create mode 100644 externals/g3dlite/G3D/Quat.inl create mode 100644 externals/g3dlite/G3D/Queue.h create mode 100644 externals/g3dlite/G3D/Random.h create mode 100644 externals/g3dlite/G3D/Ray.h create mode 100644 externals/g3dlite/G3D/Rect2D.h create mode 100644 externals/g3dlite/G3D/ReferenceCount.h create mode 100644 externals/g3dlite/G3D/RegistryUtil.h create mode 100644 externals/g3dlite/G3D/Set.h create mode 100644 externals/g3dlite/G3D/SmallArray.h create mode 100644 externals/g3dlite/G3D/Sphere.h create mode 100644 externals/g3dlite/G3D/Spline.h create mode 100644 externals/g3dlite/G3D/Stopwatch.h create mode 100644 externals/g3dlite/G3D/System.h create mode 100644 externals/g3dlite/G3D/Table.h create mode 100644 externals/g3dlite/G3D/TextInput.h create mode 100644 externals/g3dlite/G3D/TextOutput.h create mode 100644 externals/g3dlite/G3D/ThreadSet.h create mode 100644 externals/g3dlite/G3D/Triangle.h create mode 100644 externals/g3dlite/G3D/UprightFrame.h create mode 100644 externals/g3dlite/G3D/Vector2.h create mode 100644 externals/g3dlite/G3D/Vector2.inl create mode 100644 externals/g3dlite/G3D/Vector2int16.h create mode 100644 externals/g3dlite/G3D/Vector3.h create mode 100644 externals/g3dlite/G3D/Vector3.inl create mode 100644 externals/g3dlite/G3D/Vector3int16.h create mode 100644 externals/g3dlite/G3D/Vector3int32.h create mode 100644 externals/g3dlite/G3D/Vector4.h create mode 100644 externals/g3dlite/G3D/Vector4.inl create mode 100644 externals/g3dlite/G3D/Vector4int8.h create mode 100644 externals/g3dlite/G3D/WeakCache.h create mode 100644 externals/g3dlite/G3D/Welder.h create mode 100644 externals/g3dlite/G3D/WrapMode.h create mode 100644 externals/g3dlite/G3D/constants.h create mode 100644 externals/g3dlite/G3D/debug.h create mode 100644 externals/g3dlite/G3D/debugAssert.h create mode 100644 externals/g3dlite/G3D/debugPrintf.h create mode 100644 externals/g3dlite/G3D/enumclass.h create mode 100644 externals/g3dlite/G3D/fileutils.h create mode 100644 externals/g3dlite/G3D/filter.h create mode 100644 externals/g3dlite/G3D/format.h create mode 100644 externals/g3dlite/G3D/g3dfnmatch.h create mode 100644 externals/g3dlite/G3D/g3dmath.h create mode 100644 externals/g3dlite/G3D/g3dmath.inl create mode 100644 externals/g3dlite/G3D/platform.h create mode 100644 externals/g3dlite/G3D/prompt.h create mode 100644 externals/g3dlite/G3D/serialize.h create mode 100644 externals/g3dlite/G3D/splinefunc.h create mode 100644 externals/g3dlite/G3D/stringutils.h create mode 100644 externals/g3dlite/G3D/uint128.h create mode 100644 externals/g3dlite/G3D/units.h create mode 100644 externals/g3dlite/G3D/vectorMath.h delete mode 100644 externals/g3dlite/doc-files/changelog.dox delete mode 100644 externals/g3dlite/doc-files/contributors.dox delete mode 100644 externals/g3dlite/doc-files/license.dox delete mode 100644 externals/g3dlite/win/VC90/g3dlite.vcproj delete mode 100644 externals/g3dlite/win/g3dlite.sln delete mode 100644 externals/g3dlite/zip.lib/include/zip/ioapi.h delete mode 100644 externals/g3dlite/zip.lib/include/zip/unzip.h delete mode 100644 externals/g3dlite/zip.lib/include/zip/zip.h delete mode 100644 externals/g3dlite/zip.lib/source/crypt.h delete mode 100644 externals/g3dlite/zip.lib/source/ioapi.c delete mode 100644 externals/g3dlite/zip.lib/source/iowin32.c delete mode 100644 externals/g3dlite/zip.lib/source/iowin32.h delete mode 100644 externals/g3dlite/zip.lib/source/unzip.c delete mode 100644 externals/g3dlite/zip.lib/source/zip.c (limited to 'src/server/collision/Maps/TileAssembler.cpp') diff --git a/externals/PackageList.txt b/externals/PackageList.txt index 52341a01cd4..168d0428983 100644 --- a/externals/PackageList.txt +++ b/externals/PackageList.txt @@ -6,7 +6,7 @@ ACE (ADAPTIVE Communication Environment) bzip2 (a freely available, patent free, high-quality data compressor) http://www.bzip.org/ -G3D (a commercial-grade C++ 3D engine available as Open Source (BSD License) +G3D 6.09 (a commercial-grade C++ 3D engine available as Open Source (BSD License) http://g3d.sourceforge.net/ jemalloc (a general-purpose scalable concurrent malloc-implementation) diff --git a/externals/g3dlite/G3D.lib/include/G3D/AABSPTree.h b/externals/g3dlite/G3D.lib/include/G3D/AABSPTree.h deleted file mode 100644 index 1178fad93c3..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/AABSPTree.h +++ /dev/null @@ -1,1609 +0,0 @@ -/** - @file AABSPTree.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2004-01-11 - @edited 2008-11-19 - - Copyright 2000-2008, Morgan McGuire. - All rights reserved. - - */ - -#ifndef G3D_KDTREE_H -#define G3D_KDTREE_H - -#include "G3D/platform.h" -#include "G3D/Array.h" -#include "G3D/Table.h" -#include "G3D/Vector2.h" -#include "G3D/Vector3.h" -#include "G3D/Vector4.h" -#include "G3D/AABox.h" -#include "G3D/Sphere.h" -#include "G3D/Box.h" -#include "G3D/Triangle.h" -#include "G3D/Ray.h" -#include "G3D/GCamera.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/CollisionDetection.h" -#include "G3D/GCamera.h" -#include "G3D/BoundsTrait.h" -#include - -// If defined, in debug mode the tree is checked for consistency -// as a way of detecting corruption due to implementation bugs -// #define VERIFY_TREE - -template<> struct BoundsTrait { - static void getBounds(const G3D::Vector2& v, G3D::AABox& out) { out = G3D::AABox(G3D::Vector3(v, 0)); } -}; - -template<> struct BoundsTrait { - static void getBounds(const G3D::Vector3& v, G3D::AABox& out) { out = G3D::AABox(v); } -}; - -template<> struct BoundsTrait { - static void getBounds(const G3D::Vector4& v, G3D::AABox& out) { out = G3D::AABox(v.xyz()); } -}; - -template<> struct BoundsTrait { - static void getBounds(const G3D::AABox& v, G3D::AABox& out) { out = v; } -}; - -template<> struct BoundsTrait { - static void getBounds(const G3D::Sphere& s, G3D::AABox& out) { s.getBounds(out); } -}; - -template<> struct BoundsTrait { - static void getBounds(const G3D::Box& b, G3D::AABox& out) { b.getBounds(out); } -}; - -template<> struct BoundsTrait { - static void getBounds(const G3D::Vector2*& v, G3D::AABox& out) { out = G3D::AABox(G3D::Vector3(*v, 0)); } -}; - -template<> struct BoundsTrait { - static void getBounds(const G3D::Vector3*& v, G3D::AABox& out) { out = G3D::AABox(*v); } -}; - -template<> struct BoundsTrait { - static void getBounds(const G3D::Vector4*& v, G3D::AABox& out) { out = G3D::AABox(v->xyz()); } -}; - -template<> struct BoundsTrait { - static void getBounds(const G3D::AABox*& v, G3D::AABox& out) { out = *v; } -}; - -template<> struct BoundsTrait { - static void getBounds(const G3D::Sphere*& s, G3D::AABox& out) { s->getBounds(out); } -}; - -template<> struct BoundsTrait { - static void getBounds(const G3D::Box*& b, G3D::AABox& out) { b->getBounds(out); } -}; - - -template<> struct BoundsTrait { - static void getBounds(const G3D::Triangle*& t, G3D::AABox& out) { t->getBounds(out); } -}; - -namespace G3D { - namespace _internal { - - /** - Wraps a pointer value so that it can be treated as the instance itself; - convenient for inserting pointers into a Table but using the - object equality instead of pointer equality. - */ - template - class Indirector { - public: - Type* handle; - - inline Indirector(Type* h) : handle(h) {} - - inline Indirector() : handle(NULL) {} - - /** Returns true iff the values referenced by the handles are equivalent. */ - inline bool operator==(const Indirector& m) const { - return *handle == *(m.handle); - } - - inline bool operator==(const Type& m) const { - return *handle == m; - } - - inline size_t hashCode() const { - return handle->hashCode(); - } - }; - } // namespace internal -} // namespace G3D - -template struct HashTrait > { - static size_t hashCode(const G3D::_internal::Indirector& key) { return key.hashCode(); } -}; - -namespace G3D { - -/** - A set that supports spatial queries using a KD tree (axis-aligned - BSP tree) for speed. - - KDTree allows you to quickly find objects in 3D that lie within - a box or along a ray. For large sets of objects it is much faster - than testing each object for a collision. - - KDTree is as powerful as but more general than a Quad Tree, Oct - Tree, or regular KD tree that cycles through axes, but less general than an unconstrained BSP tree - (which is much slower to create). - - Internally, objects - are arranged into a tree according to their - axis-aligned bounds. This increases the cost of insertion to - O(log n) but allows fast overlap queries. - - Template Parameters -
The template parameter T must be one for which - the following functions are all overloaded: - -
-  T::T(); (public constructor of no arguments)
-  template <> struct HashTrait { static size_t hashCode(int key); };
-  template<> struct BoundsTrait { static void getBounds(const T& obj, G3D::AABox& out); };
- 
- - G3D provides these for common classes like G3D::Vector3 and G3D::Sphere. - If you use a custom class, or a pointer to a custom class, you will need - to define those functions. - - Moving %Set Members -
It is important that objects do not move without updating the - KDTree. If the axis-aligned bounds of an object are about - to change, KDTree::remove it before they change and - KDTree::insert it again afterward. For objects - where the hashCode and == operator are invariant with respect - to the 3D position, - you can use the KDTree::update method as a shortcut to - insert/remove an object in one step after it has moved. - - - Note: Do not mutate any value once it has been inserted into KDTree. Values - are copied interally. All KDTree iterators convert to pointers to constant - values to reinforce this. - - If you want to mutate the objects you intend to store in a KDTree - simply insert pointers to your objects instead of the objects - themselves, and ensure that the above operations are defined. (And - actually, because values are copied, if your values are large you may - want to insert pointers anyway, to save space and make the balance - operation faster.) - - Dimensions - Although designed as a 3D-data structure, you can use the KDTree - for data distributed along 2 or 1 axes by simply returning bounds - that are always zero along one or more dimensions. - -*/ -template< class T, - class BoundsFunc = BoundsTrait, - class HashFunc = HashTrait, - class EqualsFunc = EqualsTrait > -class KDTree { -protected: -#define TreeType KDTree - - /** Wrapper for a value that includes a cache of its bounds. - Except for the test value used in a set-query operation, there - is only ever one instance of the handle associated with any - value and the memberTable and Nodes maintain pointers to that - heap-allocated value. - */ - class Handle { - public: - /** The bounds of each object are constrained to AABox::large */ - AABox bounds; - - /** Center of bounds. We cache this value to avoid recomputing it - during the median sort, and because MSVC 6 std::sort goes into - an infinite loop if we compute the midpoint on the fly (possibly - a floating point roundoff issue, where B& point, - int beginIndex, - int endIndex) { - - Vector3 lo = Vector3::inf(); - Vector3 hi = -lo; - - debugAssertM(beginIndex <= endIndex, "No points"); - for (int p = beginIndex; p <= endIndex; ++p) { - // This code is written with the vector min and max expanded - // because otherwise it compiles incorrectly with -O3 on - // gcc 3.4 - - const Vector3& pLo = point[p]->bounds.low(); - const Vector3& pHi = point[p]->bounds.high(); - for (int a = 0; a < 3; ++a) { - lo[a] = G3D::min(lo[a], pLo[a]); - hi[a] = G3D::max(hi[a], pHi[a]); - } - } - - return AABox(lo, hi); - } - - /** Compares centers */ - class CenterComparator { - public: - Vector3::Axis sortAxis; - - CenterComparator(Vector3::Axis a) : sortAxis(a) {} - - inline int operator()(Handle* A, const Handle* B) const { - float a = A->center[sortAxis]; - float b = B->center[sortAxis]; - - if (a < b) { - return 1; - } else if (a > b) { - return -1; - } else { - return 0; - } - } - }; - - - /** Compares bounds for strict >, <, or overlap*/ - class BoundsComparator { - public: - Vector3::Axis sortAxis; - - BoundsComparator(Vector3::Axis a) : sortAxis(a) {} - - inline int operator()(Handle* A, const Handle* B) const { - const AABox& a = A->bounds; - const AABox& b = B->bounds; - - if (a.high()[sortAxis] < b.low()[sortAxis]) { - return 1; - } else if (a.low()[sortAxis] > b.high()[sortAxis]) { - return -1; - } else { - return 0; - } - } - }; - - - /** Compares bounds to the sort location */ - class Comparator { - public: - Vector3::Axis sortAxis; - float sortLocation; - - Comparator(Vector3::Axis a, float l) : sortAxis(a), sortLocation(l) {} - - inline int operator()(Handle* ignore, const Handle* handle) const { - const AABox& box = handle->bounds; - debugAssert(ignore == NULL); - - if (box.high()[sortAxis] < sortLocation) { - // Box is strictly below the sort location - return -1; - } else if (box.low()[sortAxis] > sortLocation) { - // Box is strictly above the sort location - return 1; - } else { - // Box overlaps the sort location - return 0; - } - } - }; - - // Using System::malloc with this class provided no speed improvement. - class Node { - public: - - /** Spatial bounds on all values at this node and its children, based purely on - the parent's splitting planes. May be infinite. */ - AABox splitBounds; - - Vector3::Axis splitAxis; - - /** Location along the specified axis */ - float splitLocation; - - /** child[0] contains all values strictly - smaller than splitLocation along splitAxis. - - child[1] contains all values strictly - larger. - - Both may be NULL if there are not enough - values to bother recursing. - */ - Node* child[2]; - - /** Array of values at this node (i.e., values - straddling the split plane + all values if - this is a leaf node). - - This is an array of pointers because that minimizes - data movement during tree building, which accounts - for about 15% of the time cost of tree building. - */ - Array valueArray; - - /** For each object in the value array, a copy of its bounds. - Packing these into an array at the node level - instead putting them in the valueArray improves - cache coherence, which is about a 3x performance - increase when performing intersection computations. - */ - Array boundsArray; - - /** Creates node with NULL children */ - Node() { - splitAxis = Vector3::X_AXIS; - splitLocation = 0; - splitBounds = AABox(-Vector3::inf(), Vector3::inf()); - for (int i = 0; i < 2; ++i) { - child[i] = NULL; - } - } - - /** - Doesn't clone children. - */ - Node(const Node& other) : valueArray(other.valueArray), boundsArray(other.boundsArray) { - splitAxis = other.splitAxis; - splitLocation = other.splitLocation; - splitBounds = other.splitBounds; - for (int i = 0; i < 2; ++i) { - child[i] = NULL; - } - } - - /** Copies the specified subarray of pt into point, NULLs the children. - Assumes a second pass will set splitBounds. */ - Node(const Array& pt) : valueArray(pt) { - splitAxis = Vector3::X_AXIS; - splitLocation = 0; - for (int i = 0; i < 2; ++i) { - child[i] = NULL; - } - - boundsArray.resize(valueArray.size()); - for (int i = 0; i < valueArray.size(); ++i) { - boundsArray[i] = valueArray[i]->bounds; - } - } - - /** Deletes the children (but not the values) */ - ~Node() { - for (int i = 0; i < 2; ++i) { - delete child[i]; - } - } - - /** Returns true if this node is a leaf (no children) */ - inline bool isLeaf() const { - return (child[0] == NULL) && (child[1] == NULL); - } - - - /** - Recursively appends all handles and children's handles - to the array. - */ - void getHandles(Array& handleArray) const { - handleArray.append(valueArray); - for (int i = 0; i < 2; ++i) { - if (child[i] != NULL) { - child[i]->getHandles(handleArray); - } - } - } - - void verifyNode(const Vector3& lo, const Vector3& hi) { - // debugPrintf("Verifying: split %d @ %f [%f, %f, %f], [%f, %f, %f]\n", - // splitAxis, splitLocation, lo.x, lo.y, lo.z, hi.x, hi.y, hi.z); - - debugAssertM(lo == splitBounds.low(), - format("lo = %s, splitBounds.lo = %s", - lo.toString().c_str(), splitBounds.low().toString().c_str())); - debugAssert(hi == splitBounds.high()); - - for (int i = 0; i < valueArray.length(); ++i) { - const AABox& b = valueArray[i]->bounds; - debugAssert(b == boundsArray[i]); - - for(int axis = 0; axis < 3; ++axis) { - debugAssert(b.low()[axis] <= b.high()[axis]); - debugAssert(b.low()[axis] >= lo[axis]); - debugAssert(b.high()[axis] <= hi[axis]); - } - } - - if (child[0] || child[1]) { - debugAssert(lo[splitAxis] < splitLocation); - debugAssert(hi[splitAxis] > splitLocation); - } - - Vector3 newLo = lo; - newLo[splitAxis] = splitLocation; - Vector3 newHi = hi; - newHi[splitAxis] = splitLocation; - - if (child[0] != NULL) { - child[0]->verifyNode(lo, newHi); - } - - if (child[1] != NULL) { - child[1]->verifyNode(newLo, hi); - } - } - - - /** - Stores the locations of the splitting planes (the structure but not the content) - so that the tree can be quickly rebuilt from a previous configuration without - calling balance. - */ - static void serializeStructure(const Node* n, BinaryOutput& bo) { - if (n == NULL) { - bo.writeUInt8(0); - } else { - bo.writeUInt8(1); - n->splitBounds.serialize(bo); - serialize(n->splitAxis, bo); - bo.writeFloat32(n->splitLocation); - for (int c = 0; c < 2; ++c) { - serializeStructure(n->child[c], bo); - } - } - } - - /** Clears the member table */ - static Node* deserializeStructure(BinaryInput& bi) { - if (bi.readUInt8() == 0) { - return NULL; - } else { - Node* n = new Node(); - n->splitBounds.deserialize(bi); - deserialize(n->splitAxis, bi); - n->splitLocation = bi.readFloat32(); - for (int c = 0; c < 2; ++c) { - n->child[c] = deserializeStructure(bi); - } - return n; - } - } - - /** Returns the deepest node that completely contains bounds. */ - Node* findDeepestContainingNode(const AABox& bounds) { - - // See which side of the splitting plane the bounds are on - if (bounds.high()[splitAxis] < splitLocation) { - // Bounds are on the low side. Recurse into the child - // if it exists. - if (child[0] != NULL) { - return child[0]->findDeepestContainingNode(bounds); - } - } else if (bounds.low()[splitAxis] > splitLocation) { - // Bounds are on the high side, recurse into the child - // if it exists. - if (child[1] != NULL) { - return child[1]->findDeepestContainingNode(bounds); - } - } - - // There was no containing child, so this node is the - // deepest containing node. - return this; - } - - - /** Appends all members that intersect the box. - If useSphere is true, members that pass the box test - face a second test against the sphere. */ - void getIntersectingMembers( - const AABox& box, - const Sphere& sphere, - Array& members, - bool useSphere) const { - - // Test all values at this node - for (int v = 0; v < boundsArray.size(); ++v) { - const AABox& bounds = boundsArray[v]; - if (bounds.intersects(box) && - (! useSphere || bounds.intersects(sphere))) { - members.append(valueArray[v]->value); - } - } - - // If the left child overlaps the box, recurse into it - if ((child[0] != NULL) && (box.low()[splitAxis] < splitLocation)) { - child[0]->getIntersectingMembers(box, sphere, members, useSphere); - } - - // If the right child overlaps the box, recurse into it - if ((child[1] != NULL) && (box.high()[splitAxis] > splitLocation)) { - child[1]->getIntersectingMembers(box, sphere, members, useSphere); - } - } - - /** - Recurse through the tree, assigning splitBounds fields. - */ - void assignSplitBounds(const AABox& myBounds) { - splitBounds = myBounds; - - AABox childBounds[2]; - myBounds.split(splitAxis, splitLocation, childBounds[0], childBounds[1]); - -# if defined(G3D_DEBUG) && defined(VERIFY_TREE) - // Verify the split - for (int v = 0; v < boundsArray.size(); ++v) { - const AABox& bounds = boundsArray[v]; - debugAssert(myBounds.contains(bounds)); - } -# endif - - for (int c = 0; c < 2; ++c) { - if (child[c]) { - child[c]->assignSplitBounds(childBounds[c]); - } - } - } - - /** Returns true if the ray intersects this node */ - bool intersects(const Ray& ray, float distance) const { - // See if the ray will ever hit this node or its children - Vector3 location; - bool alreadyInsideBounds = false; - bool rayWillHitBounds = - CollisionDetection::collisionLocationForMovingPointFixedAABox( - ray.origin, ray.direction, splitBounds, location, alreadyInsideBounds); - - bool canHitThisNode = (alreadyInsideBounds || - (rayWillHitBounds && ((location - ray.origin).squaredLength() < square(distance)))); - - return canHitThisNode; - } - - template - void intersectRay( - const Ray& ray, - RayCallback& intersectCallback, - float& distance, - bool intersectCallbackIsFast) const { - - if (! intersects(ray, distance)) { - // The ray doesn't hit this node, so it can't hit the children of the node. - return; - } - - // Test for intersection against every object at this node. - for (int v = 0; v < valueArray.size(); ++v) { - bool canHitThisObject = true; - - if (! intersectCallbackIsFast) { - // See if - Vector3 location; - const AABox& bounds = boundsArray[v]; - bool alreadyInsideBounds = false; - bool rayWillHitBounds = - CollisionDetection::collisionLocationForMovingPointFixedAABox( - ray.origin, ray.direction, bounds, location, alreadyInsideBounds); - - canHitThisObject = (alreadyInsideBounds || - (rayWillHitBounds && ((location - ray.origin).squaredLength() < square(distance)))); - } - - if (canHitThisObject) { - // It is possible that this ray hits this object. Look for the intersection using the - // callback. - const T& value = valueArray[v]->value; - intersectCallback(ray, value, distance); - } - } - - // There are three cases to consider next: - // - // 1. the ray can start on one side of the splitting plane and never enter the other, - // 2. the ray can start on one side and enter the other, and - // 3. the ray can travel exactly down the splitting plane - - enum {NONE = -1}; - int firstChild = NONE; - int secondChild = NONE; - - if (ray.origin[splitAxis] < splitLocation) { - - // The ray starts on the small side - firstChild = 0; - - if (ray.direction[splitAxis] > 0) { - // The ray will eventually reach the other side - secondChild = 1; - } - - } else if (ray.origin[splitAxis] > splitLocation) { - - // The ray starts on the large side - firstChild = 1; - - if (ray.direction[splitAxis] < 0) { - secondChild = 0; - } - } else { - // The ray starts on the splitting plane - if (ray.direction[splitAxis] < 0) { - // ...and goes to the small side - firstChild = 0; - } else if (ray.direction[splitAxis] > 0) { - // ...and goes to the large side - firstChild = 1; - } - } - - // Test on the side closer to the ray origin. - if ((firstChild != NONE) && child[firstChild]) { - child[firstChild]->intersectRay(ray, intersectCallback, distance, intersectCallbackIsFast); - } - - if (ray.direction[splitAxis] != 0) { - // See if there was an intersection before hitting the splitting plane. - // If so, there is no need to look on the far side and recursion terminates. - float distanceToSplittingPlane = (splitLocation - ray.origin[splitAxis]) / ray.direction[splitAxis]; - if (distanceToSplittingPlane > distance) { - // We aren't going to hit anything else before hitting the splitting plane, - // so don't bother looking on the far side of the splitting plane at the other - // child. - return; - } - } - - // Test on the side farther from the ray origin. - if ((secondChild != NONE) && child[secondChild]) { - child[secondChild]->intersectRay(ray, intersectCallback, distance, intersectCallbackIsFast); - } - - } - }; - - - /** - Recursively subdivides the subarray. - - Clears the source array as soon as it is no longer needed. - - Call assignSplitBounds() on the root node after making a tree. - */ - Node* makeNode( - Array& source, - int valuesPerNode, - int numMeanSplits, - Array& temp) { - - Node* node = NULL; - - if (source.size() <= valuesPerNode) { - // Make a new leaf node - node = new Node(source); - - // Set the pointers in the memberTable - for (int i = 0; i < source.size(); ++i) { - memberTable.set(Member(source[i]), node); - } - source.clear(); - - } else { - // Make a new internal node - node = new Node(); - - const AABox& bounds = computeBounds(source, 0, source.size() - 1); - const Vector3& extent = bounds.high() - bounds.low(); - - Vector3::Axis splitAxis = extent.primaryAxis(); - - float splitLocation; - - // Arrays for holding the children - Array lt, gt; - - if (numMeanSplits <= 0) { - - source.medianPartition(lt, node->valueArray, gt, temp, CenterComparator(splitAxis)); - - // Choose the split location to be the center of whatever fell in the center - splitLocation = node->valueArray[0]->center[splitAxis]; - - // Some of the elements in the lt or gt array might really overlap the split location. - // Move them as needed. - for (int i = 0; i < lt.size(); ++i) { - const AABox& bounds = lt[i]->bounds; - if ((bounds.low()[splitAxis] <= splitLocation) && (bounds.high()[splitAxis] >= splitLocation)) { - node->valueArray.append(lt[i]); - // Remove this element and process the new one that - // is swapped in in its place. - lt.fastRemove(i); --i; - } - } - - for (int i = 0; i < gt.size(); ++i) { - const AABox& bounds = gt[i]->bounds; - if ((bounds.low()[splitAxis] <= splitLocation) && (bounds.high()[splitAxis] >= splitLocation)) { - node->valueArray.append(gt[i]); - // Remove this element and process the new one that - // is swapped in in its place. - gt.fastRemove(i); --i; - } - } - - if ((node->valueArray.size() > (source.size() / 2)) && - (source.size() > 6)) { - // This was a bad partition; we ended up putting the splitting plane right in the middle of most of the - // objects. We could try to split on a different axis, or use a different partition (e.g., the extents mean, - // or geometric mean). This implementation falls back on the extents mean, since that case is already handled - // below. - numMeanSplits = 1; - } - } - - // Note: numMeanSplits may have been increased by the code in the previous case above in order to - // force a re-partition. - - if (numMeanSplits > 0) { - // Split along the mean - splitLocation = - bounds.high()[splitAxis] * 0.5f + - bounds.low()[splitAxis] * 0.5f; - - debugAssertM(isFinite(splitLocation), - "Internal error: split location must be finite."); - - source.partition(NULL, lt, node->valueArray, gt, Comparator(splitAxis, splitLocation)); - - // The Comparator ensures that elements are strictly on the correct side of the split - } - - -# if defined(G3D_DEBUG) && defined(VERIFY_TREE) - debugAssert(lt.size() + node->valueArray.size() + gt.size() == source.size()); - // Verify that all objects ended up on the correct side of the split. - // (i.e., make sure that the Array partition was correct) - for (int i = 0; i < lt.size(); ++i) { - const AABox& bounds = lt[i]->bounds; - debugAssert(bounds.high()[splitAxis] < splitLocation); - } - - for (int i = 0; i < gt.size(); ++i) { - const AABox& bounds = gt[i]->bounds; - debugAssert(bounds.low()[splitAxis] > splitLocation); - } - - for (int i = 0; i < node->valueArray.size(); ++i) { - const AABox& bounds = node->valueArray[i]->bounds; - debugAssert(bounds.high()[splitAxis] >= splitLocation); - debugAssert(bounds.low()[splitAxis] <= splitLocation); - } -# endif - - // The source array is no longer needed - source.clear(); - - node->splitAxis = splitAxis; - node->splitLocation = splitLocation; - - // Update the bounds array and member table - node->boundsArray.resize(node->valueArray.size()); - for (int i = 0; i < node->valueArray.size(); ++i) { - Handle* v = node->valueArray[i]; - node->boundsArray[i] = v->bounds; - memberTable.set(Member(v), node); - } - - if (lt.size() > 0) { - node->child[0] = makeNode(lt, valuesPerNode, numMeanSplits - 1, temp); - } - - if (gt.size() > 0) { - node->child[1] = makeNode(gt, valuesPerNode, numMeanSplits - 1, temp); - } - - } - - return node; - } - - /** - Recursively clone the passed in node tree, setting - pointers for members in the memberTable as appropriate. - called by the assignment operator. - */ - Node* cloneTree(Node* src) { - Node* dst = new Node(*src); - - // Make back pointers - for (int i = 0; i < dst->valueArray.size(); ++i) { - memberTable.set(Member(dst->valueArray[i]), dst); - } - - // Clone children - for (int i = 0; i < 2; ++i) { - if (src->child[i] != NULL) { - dst->child[i] = cloneTree(src->child[i]); - } - } - - return dst; - } - - /** - Wrapper for a Handle; used to create a memberTable that acts like Table but - stores only Handle* internally to avoid memory copies. - */ - typedef _internal::Indirector Member; - - typedef Table MemberTable; - - /** Maps members to the node containing them */ - MemberTable memberTable; - - Node* root; - -public: - - /** To construct a balanced tree, insert the elements and then call - KDTree::balance(). */ - KDTree() : root(NULL) {} - - - KDTree(const KDTree& src) : root(NULL) { - *this = src; - } - - - KDTree& operator=(const KDTree& src) { - delete root; - // Clone tree takes care of filling out the memberTable. - root = cloneTree(src.root); - return *this; - } - - - ~KDTree() { - clear(); - } - - /** - Throws out all elements of the set. - */ - void clear() { - typedef typename Table<_internal::Indirector, Node*>::Iterator It; - - // Delete all handles stored in the member table - It cur = memberTable.begin(); - It end = memberTable.end(); - while (cur != end) { - delete cur->key.handle; - cur->key.handle = NULL; - ++cur; - } - memberTable.clear(); - - // Delete the tree structure itself - delete root; - root = NULL; - } - - int size() const { - return memberTable.size(); - } - - /** - Inserts an object into the set if it is not - already present. O(log n) time. Does not - cause the tree to be balanced. - */ - void insert(const T& value) { - if (contains(value)) { - // Already in the set - return; - } - - Handle* h = new Handle(value); - - if (root == NULL) { - // This is the first node; create a root node - root = new Node(); - } - - Node* node = root->findDeepestContainingNode(h->bounds); - - // Insert into the node - node->valueArray.append(h); - node->boundsArray.append(h->bounds); - - // Insert into the node table - Member m(h); - memberTable.set(m, node); - } - - /** Inserts each elements in the array in turn. If the tree - begins empty (no structure and no elements), this is faster - than inserting each element in turn. You still need to balance - the tree at the end.*/ - void insert(const Array& valueArray) { - if (root == NULL) { - // Optimized case for an empty tree; don't bother - // searching or reallocating the root node's valueArray - // as we incrementally insert. - root = new Node(); - root->valueArray.resize(valueArray.size()); - root->boundsArray.resize(root->valueArray.size()); - for (int i = 0; i < valueArray.size(); ++i) { - // Insert in opposite order so that we have the exact same - // data structure as if we inserted each (i.e., order is reversed - // from array). - Handle* h = new Handle(valueArray[i]); - int j = valueArray.size() - i - 1; - root->valueArray[j] = h; - root->boundsArray[j] = h->bounds; - memberTable.set(Member(h), root); - } - - } else { - // Insert at appropriate tree depth. - for (int i = 0; i < valueArray.size(); ++i) { - insert(valueArray[i]); - } - } - } - - - /** - Returns true if this object is in the set, otherwise - returns false. O(1) time. - */ - bool contains(const T& value) { - // Temporarily create a handle and member - Handle h(value); - return memberTable.containsKey(Member(&h)); - } - - - /** - Removes an object from the set in O(1) time. - It is an error to remove members that are not already - present. May unbalance the tree. - - Removing an element never causes a node (split plane) to be removed... - nodes are only changed when the tree is rebalanced. This behavior - is desirable because it allows the split planes to be serialized, - and then deserialized into an empty tree which can be repopulated. - */ - void remove(const T& value) { - debugAssertM(contains(value), - "Tried to remove an element from a " - "KDTree that was not present"); - - // Get the list of elements at the node - Handle h(value); - Member m(&h); - - Array& list = memberTable[m]->valueArray; - - Handle* ptr = NULL; - - // Find the element and remove it - for (int i = list.length() - 1; i >= 0; --i) { - if (list[i]->value == value) { - // This was the element. Grab the pointer so that - // we can delete it below - ptr = list[i]; - - // Remove the handle from the node - list.fastRemove(i); - - // Remove the corresponding bounds - memberTable[m]->boundsArray.fastRemove(i); - break; - } - } - - // Remove the member - memberTable.remove(m); - - // Delete the handle data structure - delete ptr; - ptr = NULL; - } - - - /** - If the element is in the set, it is removed. - The element is then inserted. - - This is useful when the == and hashCode methods - on T are independent of the bounds. In - that case, you may call update(v) to insert an - element for the first time and call update(v) - again every time it moves to keep the tree - up to date. - */ - void update(const T& value) { - if (contains(value)) { - remove(value); - } - insert(value); - } - - - /** - Rebalances the tree (slow). Call when objects - have moved substantially from their original positions - (which unbalances the tree and causes the spatial - queries to be slow). - - @param valuesPerNode Maximum number of elements to put at - a node. - - @param numMeanSplits numMeanSplits = 0 gives a - fully axis aligned BSP-tree, where the balance operation attempts to balance - the tree so that every splitting plane has an equal number of left - and right children (i.e. it is a median split along that axis). - This tends to maximize average performance. - - You can override this behavior by - setting a number of mean (average) splits. numMeanSplits = MAX_INT - creates a full oct-tree, which tends to optimize peak performance at the expense of - average performance. It tends to have better clustering behavior when - members are not uniformly distributed. - */ - void balance(int valuesPerNode = 5, int numMeanSplits = 3) { - if (root == NULL) { - // Tree is empty - return; - } - - // Get all handles and delete the old tree structure - Node* oldRoot = root; - for (int c = 0; c < 2; ++c) { - if (root->child[c] != NULL) { - root->child[c]->getHandles(root->valueArray); - - // Delete the child; this will delete all structure below it - delete root->child[c]; - root->child[c] = NULL; - } - } - - Array temp; - // Make a new root. Work with a copy of the value array because - // makeNode clears the source array as it progresses - Array copy(oldRoot->valueArray); - root = makeNode(copy, valuesPerNode, numMeanSplits, temp); - - // Throw away the old root node - delete oldRoot; - oldRoot = NULL; - - // Walk the tree, assigning splitBounds. We start with unbounded - // space. This will override the current member table. - const AABox& LARGE = AABox::large(); - root->assignSplitBounds(LARGE); - -# ifdef _DEBUG - { - // Ensure that the balanced tree is still correct - root->verifyNode(LARGE.low(), LARGE.high()); - } -# endif - } - -protected: - - /** - @param parentMask The mask that this node returned from culledBy. - */ - static void getIntersectingMembers( - const Array& plane, - Array& members, - Node* node, - uint32 parentMask) { - - int dummy; - - if (parentMask == 0) { - // None of these planes can cull anything - for (int v = node->valueArray.size() - 1; v >= 0; --v) { - members.append(node->valueArray[v]->value); - } - - // Iterate through child nodes - for (int c = 0; c < 2; ++c) { - if (node->child[c]) { - getIntersectingMembers(plane, members, node->child[c], 0); - } - } - } else { - - // Test values at this node against remaining planes - for (int v = node->boundsArray.size() - 1; v >= 0; --v) { - if (! node->boundsArray[v].culledBy(plane, dummy, parentMask)) { - members.append(node->valueArray[v]->value); - } - } - - uint32 childMask = 0xFFFFFF; - - // Iterate through child nodes - for (int c = 0; c < 2; ++c) { - if (node->child[c] && - ! node->child[c]->splitBounds.culledBy(plane, dummy, parentMask, childMask)) { - // This node was not culled - getIntersectingMembers(plane, members, node->child[c], childMask); - } - } - } - } - -public: - - /** - Returns all members inside the set of planes. - @param members The results are appended to this array. - */ - void getIntersectingMembers(const Array& plane, Array& members) const { - if (root == NULL) { - return; - } - - getIntersectingMembers(plane, members, root, 0xFFFFFF); - } - - /** - Typically used to find all visible - objects inside the view frustum (see also GCamera::getClipPlanes)... i.e. all objects - not culled by frustum. - - Example: -
-        Array  visible;
-        tree.getIntersectingMembers(camera.frustum(), visible);
-        // ... Draw all objects in the visible array.
-      
- @param members The results are appended to this array. - */ - void getIntersectingMembers(const GCamera::Frustum& frustum, Array& members) const { - Array plane; - - for (int i = 0; i < frustum.faceArray.size(); ++i) { - plane.append(frustum.faceArray[i].plane); - } - - getIntersectingMembers(plane, members); - } - - /** - C++ STL style iterator variable. See beginBoxIntersection(). - The iterator overloads the -> (dereference) operator, so this - acts like a pointer to the current member. - */ - // This iterator turns Node::getIntersectingMembers into a - // coroutine. It first translates that method from recursive to - // stack based, then captures the system state (analogous to a Scheme - // continuation) after each element is appended to the member array, - // and allowing the computation to be restarted. - class BoxIntersectionIterator { - private: - friend class TreeType; - - /** True if this is the "end" iterator instance */ - bool isEnd; - - /** The box that we're testing against. */ - AABox box; - - /** Node that we're currently looking at. Undefined if isEnd - is true. */ - Node* node; - - /** Nodes waiting to be processed */ - // We could use backpointers within the tree and careful - // state management to avoid ever storing the stack-- but - // it is much easier this way and only inefficient if the - // caller uses post increment (which they shouldn't!). - Array stack; - - /** The next index of current->valueArray to return. - Undefined when isEnd is true.*/ - int nextValueArrayIndex; - - BoxIntersectionIterator() : isEnd(true) {} - - BoxIntersectionIterator(const AABox& b, const Node* root) : - isEnd(root == NULL), box(b), - node(const_cast(root)), nextValueArrayIndex(-1) { - - // We intentionally start at the "-1" index of the current - // node so we can use the preincrement operator to move - // ourselves to element 0 instead of repeating all of the - // code from the preincrement method. Note that this might - // cause us to become the "end" instance. - ++(*this); - } - - public: - - inline bool operator!=(const BoxIntersectionIterator& other) const { - return ! (*this == other); - } - - bool operator==(const BoxIntersectionIterator& other) const { - if (isEnd) { - return other.isEnd; - } else if (other.isEnd) { - return false; - } else { - // Two non-end iterators; see if they match. This is kind of - // silly; users shouldn't call == on iterators in general unless - // one of them is the end iterator. - if ((box != other.box) || (node != other.node) || - (nextValueArrayIndex != other.nextValueArrayIndex) || - (stack.length() != other.stack.length())) { - return false; - } - - // See if the stacks are the same - for (int i = 0; i < stack.length(); ++i) { - if (stack[i] != other.stack[i]) { - return false; - } - } - - // We failed to find a difference; they must be the same - return true; - } - } - - /** - Pre increment. - */ - BoxIntersectionIterator& operator++() { - ++nextValueArrayIndex; - - bool foundIntersection = false; - while (! isEnd && ! foundIntersection) { - - // Search for the next node if we've exhausted this one - while ((! isEnd) && (nextValueArrayIndex >= node->valueArray.length())) { - // If we entered this loop, then the iterator has exhausted the elements at - // node (possibly because it just switched to a child node with no members). - // This loop continues until it finds a node with members or reaches - // the end of the whole intersection search. - - // If the right child overlaps the box, push it onto the stack for - // processing. - if ((node->child[1] != NULL) && - (box.high()[node->splitAxis] > node->splitLocation)) { - stack.push(node->child[1]); - } - - // If the left child overlaps the box, push it onto the stack for - // processing. - if ((node->child[0] != NULL) && - (box.low()[node->splitAxis] < node->splitLocation)) { - stack.push(node->child[0]); - } - - if (stack.length() > 0) { - // Go on to the next node (which may be either one of the ones we - // just pushed, or one from farther back the tree). - node = stack.pop(); - nextValueArrayIndex = 0; - } else { - // That was the last node; we're done iterating - isEnd = true; - } - } - - // Search for the next intersection at this node until we run out of children - while (! isEnd && ! foundIntersection && (nextValueArrayIndex < node->valueArray.length())) { - if (box.intersects(node->boundsArray[nextValueArrayIndex])) { - foundIntersection = true; - } else { - ++nextValueArrayIndex; - // If we exhaust this node, we'll loop around the master loop - // to find a new node. - } - } - } - - return *this; - } - - private: - /** - Post increment (much slower than preincrement!). Intentionally overloaded to preclude accidentally slow code. - */ - BoxIntersectionIterator operator++(int); - /*{ - BoxIntersectionIterator old = *this; - ++this; - return old; - }*/ - - public: - - /** Overloaded dereference operator so the iterator can masquerade as a pointer - to a member */ - const T& operator*() const { - alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); - return node->valueArray[nextValueArrayIndex]->value; - } - - /** Overloaded dereference operator so the iterator can masquerade as a pointer - to a member */ - T const * operator->() const { - alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); - return &(stack.last()->valueArray[nextValueArrayIndex]->value); - } - - /** Overloaded cast operator so the iterator can masquerade as a pointer - to a member */ - operator T*() const { - alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); - return &(stack.last()->valueArray[nextValueArrayIndex]->value); - } - }; - - - /** - Iterates through the members that intersect the box - */ - BoxIntersectionIterator beginBoxIntersection(const AABox& box) const { - return BoxIntersectionIterator(box, root); - } - - BoxIntersectionIterator endBoxIntersection() const { - // The "end" iterator instance - return BoxIntersectionIterator(); - } - - /** - Appends all members whose bounds intersect the box. - See also KDTree::beginBoxIntersection. - */ - void getIntersectingMembers(const AABox& box, Array& members) const { - if (root == NULL) { - return; - } - root->getIntersectingMembers(box, Sphere(Vector3::zero(), 0), members, false); - } - - - /** - Invoke a callback for every member along a ray until the closest intersection is found. - - @param callback either a function or an instance of a class with an overloaded operator() of the form: - - void callback(const Ray& ray, const T& object, float& distance). If the ray hits the object - before travelling distance distance, updates distance with the new distance to - the intersection, otherwise leaves it unmodified. A common example is: - -
-            class Entity {
-            public:
-
-                void intersect(const Ray& ray, float& maxDist, Vector3& outLocation, Vector3& outNormal) {
-                    float d = maxDist;
-
-                    // ... search for intersection distance d
-
-                    if ((d > 0) && (d < maxDist)) {
-                        // Intersection occured
-                        maxDist = d;
-                        outLocation = ...;
-                        outNormal = ...;
-                    }
-                }
-            };
-
-            // Finds the surface normal and location of the first intersection with the scene
-            class Intersection {
-            public:
-                Entity*     closestEntity;
-                Vector3     hitLocation;
-                Vector3     hitNormal;
-
-                void operator()(const Ray& ray, const Entity* entity, float& distance) {
-                    entity->intersect(ray, distance, hitLocation, hitNormal);
-                }
-            };
-
-            KDTree scene;
-
-            Intersection intersection;
-            float distance = inf();
-            scene.intersectRay(camera.worldRay(x, y), intersection, distance);
-          
- - - @param distance When the method is invoked, this is the maximum distance that the tree should search for an intersection. - On return, this is set to the distance to the first intersection encountered. - - @param intersectCallbackIsFast If false, each object's bounds are tested before the intersectCallback is invoked. - If the intersect callback runs at the same speed or faster than AABox-ray intersection, set this to true. - */ - template - void intersectRay( - const Ray& ray, - RayCallback& intersectCallback, - float& distance, - bool intersectCallbackIsFast = false) const { - - root->intersectRay(ray, intersectCallback, distance, intersectCallbackIsFast); - - } - - - /** - @brief Finds all members whose bounding boxes intersect the sphere. The actual - elements may not intersect the sphere. - - @param members The results are appended to this array. - */ - void getIntersectingMembers(const Sphere& sphere, Array& members) const { - if (root == NULL) { - return; - } - - AABox box; - sphere.getBounds(box); - root->getIntersectingMembers(box, sphere, members, true); - - } - - /** - Stores the locations of the splitting planes (the structure but not the content) - so that the tree can be quickly rebuilt from a previous configuration without - calling balance. - */ - void serializeStructure(BinaryOutput& bo) const { - Node::serializeStructure(root, bo); - } - - /** Clears the member table */ - void deserializeStructure(BinaryInput& bi) { - clear(); - root = Node::deserializeStructure(bi); - } - - /** - Returns an array of all members of the set. See also KDTree::begin. - */ - void getMembers(Array& members) const { - Array temp; - memberTable.getKeys(temp); - for (int i = 0; i < temp.size(); ++i) { - members.append(*(temp.handle)); - } - } - - - /** - C++ STL style iterator variable. See begin(). - Overloads the -> (dereference) operator, so this acts like a pointer - to the current member. - */ - class Iterator { - private: - friend class TreeType; - - // Note: this is a Table iterator, we are currently defining - // Set iterator - typename Table::Iterator it; - - Iterator(const typename Table::Iterator& it) : it(it) {} - - public: - - inline bool operator!=(const Iterator& other) const { - return !(*this == other); - } - - bool operator==(const Iterator& other) const { - return it == other.it; - } - - /** - Pre increment. - */ - Iterator& operator++() { - ++it; - return *this; - } - - private: - /** - Post increment (slower than preincrement). Intentionally unimplemented to prevent slow code. - */ - Iterator operator++(int);/* { - Iterator old = *this; - ++(*this); - return old; - }*/ - public: - - const T& operator*() const { - return it->key.handle->value; - } - - T* operator->() const { - return &(it->key.handle->value); - } - - operator T*() const { - return &(it->key.handle->value); - } - }; - - - /** - C++ STL style iterator method. Returns the first member. - Use preincrement (++entry) to get to the next element (iteration - order is arbitrary). - Do not modify the set while iterating. - */ - Iterator begin() const { - return Iterator(memberTable.begin()); - } - - - /** - C++ STL style iterator method. Returns one after the last iterator - element. - */ - Iterator end() const { - return Iterator(memberTable.end()); - } -#undef TreeType -}; - -/** @deprecated For backwards compatibility */ -#define AABSPTree KDTree - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/AABox.h b/externals/g3dlite/G3D.lib/include/G3D/AABox.h deleted file mode 100644 index 76c5d6d5195..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/AABox.h +++ /dev/null @@ -1,281 +0,0 @@ -/** - @file AABox.h - - Axis-aligned box class - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2004-01-10 - @edited 2006-02-10 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_AABOX_H -#define G3D_AABOX_H - -#include "G3D/platform.h" -#include "G3D/Vector3.h" -#include "G3D/debug.h" -#include "G3D/Array.h" -#include "G3D/Plane.h" - -namespace G3D { - -/** - An axis-aligned box. - */ -class AABox { -private: - - /** Optional argument placeholder */ - static int dummy; - - Vector3 lo; - Vector3 hi; - -public: - - /** Does not initialize the fields */ - inline AABox() {} - - /** - Constructs a zero-area AABox at v. - */ - inline explicit AABox(const Vector3& v) { - lo = hi = v; - } - - /** Assumes that low is less than or equal to high along each dimension. - To have this automatically enforced, use - AABox(low.min(high), low.max(high)); - */ - inline AABox(const Vector3& low, const Vector3& high) { - set(low, high); - } - - /** Assumes that low is less than or equal to high along each dimension. - */ - inline void set(const Vector3& low, const Vector3& high) { - debugAssert( - (low.x <= high.x) && - (low.y <= high.y) && - (low.z <= high.z)); - lo = low; - hi = high; - } - - /** - Grows to include the bounds of a - */ - inline void merge(const AABox& a) { - lo = lo.min(a.lo); - hi = hi.max(a.hi); - } - - inline void merge(const Vector3& a) { - lo = lo.min(a); - hi = hi.max(a); - } - - void serialize(class BinaryOutput& b) const; - - void deserialize(class BinaryInput& b); - - inline const Vector3& low() const { - return lo; - } - - inline const Vector3& high() const { - return hi; - } - - /** - The largest possible finite box. - */ - static inline const AABox& maxFinite() { - static const AABox b = AABox(Vector3::minFinite(), - Vector3::maxFinite()); - return b; - } - - /** A large finite box. This is smaller than FLT_MAX - because it leaves room to add boxes together. */ - static inline const AABox& large() { - static const AABox b = AABox(Vector3::minFinite() * 0.5f, - Vector3::maxFinite() * 0.5f); - return b; - } - - static inline const AABox& inf() { - static const AABox b = AABox(-Vector3::inf(), Vector3::inf()); - return b; - } - - static inline const AABox& zero() { - static const AABox b = AABox(Vector3::zero(), Vector3::zero()); - return b; - } - - /** - Returns the centroid of the box. - */ - inline Vector3 center() const { - return (lo + hi) * 0.5; - } - - Vector3 corner(int index) const; - - /** - Distance from corner(0) to the next corner along axis a. - */ - inline float extent(int a) const { - debugAssert(a < 3); - return hi[a] - lo[a]; - } - - - inline Vector3 extent() const { - return hi - lo; - } - - - /** - Splits the box into two AABoxes along the specified axis. low contains - the part that was closer to negative infinity along axis, high contains - the other part. Either may have zero volume. - */ - void split(const Vector3::Axis& axis, float location, AABox& low, AABox& high) const; - - /** - Conservative culling test for up to 32 planes. - Returns true if there exists a plane[p] for - which the entire object is in the negative half space - (opposite the plane normal). - - testMask and childMask - are used for optimizing bounding volume hierarchies. - The version of this method that produces childMask - is slower than the version without; it should only - be used for parent nodes. - - @param cullingPlaneIndex The index of the first plane for which - the entire object is in the negative half-space. The function - exits early when one plane is found. -1 when the function - returns false (i.e. when no plane culls the whole object). - - @param testMask If bit p is 0, the - bounding volume automatically passes the culling test for - plane[p] (i.e. it is known that the volume - is entirely within the positive half space). The function - must return false if testMask is 0 and test all planes - when testMask is -1 (0xFFFFFFFF). - - @param childMask Test mask for the children of this volume. - - */ - bool culledBy( - const Array& plane, - int32& cullingPlaneIndex, - const uint32 testMask, - uint32& childMask) const; - - /** - Conservative culling test that does not produce a mask for children. - */ - bool culledBy( - const Array& plane, - int32& cullingPlaneIndex = dummy, - const uint32 testMask = 0xFFFFFFFF) const; - - /** less than or equal to containment */ - inline bool contains(const AABox& other) const { - return - (other.hi.x <= hi.x) && - (other.hi.y <= hi.y) && - (other.hi.z <= hi.z) && - (other.lo.x >= lo.x) && - (other.lo.y >= lo.y) && - (other.lo.z >= lo.z); - } - - inline bool contains( - const Vector3& point) const { - return - (point.x >= lo.x) && - (point.y >= lo.y) && - (point.z >= lo.z) && - (point.x <= hi.x) && - (point.y <= hi.y) && - (point.z <= hi.z); - } - - inline float area() const { - Vector3 diag = hi - lo; - return 2.0f * (diag.x * diag.y + diag.y * diag.z + diag.x * diag.z); - } - - inline float volume() const { - Vector3 diag = hi - lo; - return diag.x * diag.y * diag.z; - } - - Vector3 randomInteriorPoint() const; - - Vector3 randomSurfacePoint() const; - - /** Returns true if there is any overlap */ - bool intersects(const AABox& other) const; - - /** Returns true if there is any overlap. - @cite Jim Arvo's algorithm from Graphics Gems II*/ - bool intersects(const class Sphere& other) const; - - /** Return the intersection of the two boxes */ - AABox intersect(const AABox& other) const { - Vector3 H = hi.min(other.hi); - Vector3 L = lo.max(other.lo).min(H); - return AABox(L, H); - } - - inline size_t hashCode() const { - return lo.hashCode() + hi.hashCode(); - } - - inline bool operator==(const AABox& b) const { - return (lo == b.lo) && (hi == b.hi); - } - - inline bool operator!=(const AABox& b) const { - return !((lo == b.lo) && (hi == b.hi)); - } - - inline AABox operator+(const Vector3& v) const { - AABox out; - out.lo = lo + v; - out.hi = hi + v; - return out; - } - - inline AABox operator-(const Vector3& v) const { - AABox out; - out.lo = lo - v; - out.hi = hi - v; - return out; - } - - void getBounds(AABox& out) const { - out = *this; - } -}; - -} - -template <> struct HashTrait { - static size_t hashCode(const G3D::AABox& key) { return key.hashCode(); } -}; - - - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/AnyVal.h b/externals/g3dlite/G3D.lib/include/G3D/AnyVal.h deleted file mode 100644 index 8254dd73c93..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/AnyVal.h +++ /dev/null @@ -1,506 +0,0 @@ -/** - @file AnyVal.h - @author Morgan McGuire - @created 2006-06-11 - @edited 2008-07-14 - */ - -#ifndef G3D_ANYVAL_H -#define G3D_ANYVAL_H - -#include "G3D/platform.h" -#include -#include "G3D/Array.h" -#include "G3D/TextInput.h" - -namespace G3D { -// Forward declarations for G3D types -class Vector2; -class Vector3; -class Vector4; -class Color1; -class Color3; -class Color4; -class Quat; -class Matrix2; -class Matrix3; -class Matrix4; -class CoordinateFrame; -class TextInput; -class TextOutput; -class BinaryInput; -class BinaryOutput; -class Rect2D; -class AABox; - -/** - A generic value, useful for defining property trees that can - be loaded from and saved to disk. The values are intentionally - restricted to a small set. - - When written to files, the syntax is as follows. Note that you can - nest arrays and tables in order to create full tree (i.e., XML-like) - structures as configuration files: - - - - - - - - - - - - - - - - - - - - - - - -
NULLNil
doubleThe number in printf double format
booltrue or false
std::stringThe string in double-quotes (")
Rect2DR(x0,y0,x1,y1)
Color1C1(value)
Color3C3(r,g,b)
Color4C4(r,g,b,a)
Vector2V2(x,y)
Vector3V3(x,y,z)
Vector4V4(x,y,z,w)
QuatV(x,y,z,w)
AABoxAAB(low Vector3, high Vector3)
Matrix2M2(r0c0, r0c1, -
   
r1c0, r1c1)
Matrix3M3(r0c0, r0c1, r0c2, -
   
r1c0, r1c1, r1c2, -
   
r2c0, r2c1, r2c2)
Matrix4M4(r0c0, r0c1, r0c2, r0c3, -
   
r1c0, r1c1, r1c2, r1c3, -
   
r2c0, r2c1, r2c2, r2c3, -
   
r3c0, r3c1, r3c2, r3c3)
CoordinateFrameCF(r0c0, r0c1, r0c2, r0c3, -
   
r1c0, r1c1, r1c2, r1c3, -
   
r2c0, r2c1, r2c2, r2c3)
CoordinateFrameCF(V3(x, y, z), yaw deg, pitch deg, optional roll deg)
Array[element0, element1, ... , elementn-1]
Table{symbol0 = value0 -
 symbol1 = value1 -
 ... -
 symboln-1 = valuen-1}
- - See also boost::any for a more general purpose but slightly harder to use - "any" for C++. - - The semantics of operator[] and the get() methods are slightly different; - operator[] acts more like a scripting language that automatically extends - arrays and tables instead of generating errors. get() has more strict semantics, - like a C++ class. - - AnyVal uses copy-on-mutate, so that AnyVal a = b semantically copies b (like int a = b would), although in practice - it delays the copy until one is mutated so that it is still fast to "copy" large arrays and tables. - - Reading example: -
-    AnyVal property = AnyVal::fromFile("c:/tmp/test.txt"));
-
-    Vector3 vel = property["angular velocity"]
-
-    Using defaults to handle errors:
-       If there was no "enabled" value, this will return the default instead of failing
-    bool enabled = property["enabled"].boolean(true);
-
- 
- - Writing to a file: -
-    AnyVal dict(AnyVal::TABLE);
-
-    dict["enabled"] = AnyVal(true);
-    dict["weight"] = 100;
-    dict["angular velocity"] = Vector3(1, -3, 4.5);
-
-    TextOutput t("c:/tmp/test.txt");
-    dict.serialize(t);
-    t.commit();
-  
- - Example of a data file: -
-   {
-      heights = [1, 17, 32]
-      model = 
-        {
-           color = C3(1, 1, 1)
-           filename = "foo.md2"
-        }
-      position = V3(23, 14, 0)
-      name = "Elmer"
-   }
-  
- -

- What's the difference from boost::any? -
I think that AnyVal will be easier for novice C++ users. It addresses the problem that - even though G3D::TextInput makes reading configuration files extremely simple, many people - still don't use it. So AnyVal makes it ridiculously simple to read and write a tree of G3D - types to a file. - - AnyVal: -

-{
-AnyVal tree(TextInput("config.txt"));
-
-bool enabled = tree.get("enabled", false);
-Vector3 direction = tree.get("direction", Vector3::zero());
-...
-}
-
- -boost: -
-{
-bool enabled = false;
-Vector3 direction;
-Table tree;
-
- ...write lots of file parsing code...
-
-   if (tree.containsKey("enabled")) {
-      const boost::any& val = tree["enabled"];
-      try {
-        enabled = any_cast(val);
-      } catch(const boost::bad_any_cast &) {
-      }
-    }
-
-   if (tree.containsKey("direction")) {
-      const boost::any& val = tree["direction"];
-      try {
-        direction = any_cast(val);
-      } catch(const boost::bad_any_cast &) {
-      }
-    }
-   ...
-}
-
- */ -class AnyVal { -public: - - /** Array and table values are all Any.*/ - enum Type { - NIL, - NUMBER, - BOOLEAN, - STRING, - VECTOR2, - VECTOR3, - VECTOR4, - MATRIX2, - MATRIX3, - MATRIX4, - QUAT, - COORDINATEFRAME, - COORDINATEFRAME2D, - CFRAME = COORDINATEFRAME, - CFRAME2D = COORDINATEFRAME2D, - COLOR1, - COLOR3, - COLOR4, - RECT2D, - AABOX2D = RECT2D, - AABOX, - ARRAY, - TABLE}; - - /** Base class for all AnyVal exceptions.*/ - class Exception { - public: - virtual ~Exception() {} - }; - - /** Thrown when an inappropriate operation is performed (e.g., operator[] on a number) */ - class WrongType : public Exception { - public: - Type expected; - Type actual; - WrongType() : expected(NIL), actual(NIL) {} - WrongType(Type e, Type a) : expected(e), actual(a) {} - }; - - /** Thrown by operator[] when a key is not present. */ - class KeyNotFound : public Exception { - public: - std::string key; - KeyNotFound() {} - KeyNotFound(const std::string& k) : key(k) {} - }; - - class IndexOutOfBounds : public Exception { - public: - int index; - int size; - IndexOutOfBounds() : index(0), size(0) {} - IndexOutOfBounds(int i, int s) : index(i), size(s) {} - }; - - /** Thrown when deserialize() when the input is incorrectly formatted. */ - class CorruptText : public Exception { - public: - std::string message; - - /** Token where the problem occurred.*/ - G3D::Token token; - - CorruptText() {} - CorruptText(const std::string& s, const G3D::Token& t) : message(s), token(t) {} - }; - -private: - - Type m_type; - void* m_value; - - /** For table and array types, *m_value is shared between multiple - instances. Mutation is allowed only if the reference count is - exactly 1, otherwise the mutating instance must copy the - value. This is not used for other types. - */ - int* m_referenceCount; - - /** Decrements the reference count (if there is one). If the - reference count is zero or does not exist. Calls delete on @a - m_value and sets it to NULL. - */ - void deleteValue(); - - /** Returns a copy of the value. */ - void* copyValue() const; - - /** Assumes isSharedType. Ensures that this has a unique reference */ - void makeMutable(); - - /** True if this is a shared value between multiple instances. */ - inline bool isShared() const { - return m_referenceCount && (*m_referenceCount > 1); - } - - /** True when m_value is a double pointer */ - inline bool isSharedType() const { - return (m_type == TABLE) || (m_type == ARRAY); - } - -public: - - AnyVal(); - - /** Deserialize */ - explicit AnyVal(G3D::TextInput& t); - - static AnyVal fromFile(const std::string& filename); - - void load(const std::string& filename); - - void save(const std::string& filename) const; - - ///** Deserialize */ - //explicit AnyVal(G3D::BinaryInput& t); - - /** Construct a number */ - AnyVal(double); - AnyVal(int); - - // Explicit to avoid ambiguity with the 'double' constructor - // when an integer type is constructed - AnyVal(bool); - AnyVal(const G3D::Vector2&); - AnyVal(const G3D::Vector3&); - AnyVal(const G3D::Vector4&); - - AnyVal(const G3D::Color1&); - AnyVal(const G3D::Color3&); - AnyVal(const G3D::Color4&); - - AnyVal(const std::string&); - AnyVal(const char*); - - AnyVal(const G3D::Quat&); - - AnyVal(const G3D::Rect2D&); - AnyVal(const G3D::AABox&); - - AnyVal(const G3D::CoordinateFrame&); - AnyVal(const G3D::Matrix2&); - AnyVal(const G3D::Matrix3&); - AnyVal(const G3D::Matrix4&); - - AnyVal(const AnyVal&); - - AnyVal(Type arrayOrTable); - - AnyVal& operator=(const AnyVal&); - - /** Frees the underlying storage */ - ~AnyVal(); - - Type type() const; - - bool isNil() const { - return type() == NIL; - } - - void serialize(G3D::TextOutput& t) const; - //void serialize(G3D::BinaryOutput& t) const; - void deserialize(G3D::TextInput& t); - //void deserialize(G3D::BinaryInput& t); - - /** Array dereference. If the index is out of bounds, IndexOutOfBounds is thrown */ - const AnyVal& operator[](int) const; - - /** Extend this array by one element. */ - void append(const AnyVal&); - - /** If the index is out of bounds, the array is resized. If the index is negative, - IndexOutOfBounds is thrown.*/ - AnyVal& operator[](int); - - /** If @a i is out of bounds or this is not an ARRAY, defaultVal is returned.*/ - const AnyVal& get(int i, const AnyVal& defaultVal) const; - - /** If out of bounds, IndexOutOfBounds is thrown. */ - const AnyVal& get(int i) const; - - /** Returns defaultVal if this is not a TABLE or the key is not found. */ - const AnyVal& get(const std::string& key, const AnyVal& defaultVal) const; - - /** Throws KeyNotFound exception if the key is not present.*/ - const AnyVal& get(const std::string& key) const; - - /** Table reference */ - const AnyVal& operator[](const std::string&) const; - - /** Table reference. If the element does not exist, it is created. */ - AnyVal& operator[](const std::string&); - - /** Table reference */ - const AnyVal& operator[](const char*) const; - - /** Table reference. If the element does not exist, it is created. */ - AnyVal& operator[](const char*); - - /** If this value is not a number throws a WrongType exception. */ - double number() const; - - /** If this value is not a number, returns defaultVal. */ - double number(double defaultVal) const; - - operator double () const { - return number(); - } - - operator float () const { - return (float)number(); - } - - bool boolean() const; - bool boolean(bool b) const; - - operator bool() const { - return boolean(); - } - - const std::string& string() const; - const std::string& string(const std::string& defaultVal) const; - - operator const std::string& () const { - return string(); - } - - const G3D::Rect2D& rect2D() const; - const G3D::Rect2D& rect2D(const G3D::Rect2D& defaultVal) const; - - operator const Rect2D& () const { - return rect2D(); - } - - const G3D::AABox& aabox() const; - const G3D::AABox& aabox(const G3D::AABox& defaultVal) const; - - operator const AABox& () const { - return aabox(); - } - - const G3D::Vector2& vector2() const; - const G3D::Vector2& vector2(const G3D::Vector2& defaultVal) const; - - operator const Vector2& () const { - return vector2(); - } - - const G3D::Vector3& vector3() const; - const G3D::Vector3& vector3(const G3D::Vector3& defaultVal) const; - - operator const Vector3& () { - return vector3(); - } - - const G3D::Vector4& vector4() const; - const G3D::Vector4& vector4(const G3D::Vector4& defaultVal) const; - - operator const Vector4& () const { - return vector4(); - } - - const G3D::Color1& color1() const; - const G3D::Color1& color1(const G3D::Color1& defaultVal) const; - - const G3D::Color3& color3() const; - const G3D::Color3& color3(const G3D::Color3& defaultVal) const; - - operator const Color3& () const { - return color3(); - } - - const G3D::Color4& color4() const; - const G3D::Color4& color4(const G3D::Color4& defaultVal) const; - - operator const Color4& () const { - return color4(); - } - - const G3D::CoordinateFrame& coordinateFrame() const; - const G3D::CoordinateFrame& coordinateFrame(const G3D::CoordinateFrame& defaultVal) const; - - operator const CoordinateFrame& () const { - return coordinateFrame(); - } - - const G3D::Matrix2& matrix2() const; - const G3D::Matrix2& matrix2(const G3D::Matrix2& defaultVal) const; - - operator const Matrix2& () const { - return matrix2(); - } - - const G3D::Matrix3& matrix3() const; - const G3D::Matrix3& matrix3(const G3D::Matrix3& defaultVal) const; - - operator const Matrix3& () const { - return matrix3(); - } - - const G3D::Matrix4& matrix4() const; - const G3D::Matrix4& matrix4(const G3D::Matrix4& defaultVal) const; - - operator const Matrix4& () const { - return matrix4(); - } - - const G3D::Quat& quat() const; - const G3D::Quat& quat(const G3D::Quat& defaultVal) const; - - operator const Quat& () const { - return quat(); - } - - std::string toString() const; - - /** Number of elements for an array or table.*/ - int size() const; - - /** For a table, returns the keys. */ - void getKeys(G3D::Array&) const; -}; - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Array.h b/externals/g3dlite/G3D.lib/include/G3D/Array.h deleted file mode 100644 index ae4eea8ab40..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Array.h +++ /dev/null @@ -1,1180 +0,0 @@ -/** - @file Array.h - - @maintainer Morgan McGuire, graphics3d.com - @cite Portions written by Aaron Orenstein, a@orenstein.name - - @created 2001-03-11 - @edited 2008-07-09 - - Copyright 2000-2008, Morgan McGuire, morgan@cs.williams.edu - All rights reserved. - */ - -#ifndef G3D_ARRAY_H -#define G3D_ARRAY_H - -#include "G3D/platform.h" -#include "G3D/debug.h" -#include "G3D/System.h" -#ifdef G3D_DEBUG -// For formatting error messages -# include "G3D/format.h" -#endif -#include -#include - -#ifdef _MSC_VER -# include - -# pragma warning (push) - // debug information too long -# pragma warning( disable : 4312) -# pragma warning( disable : 4786) -#endif - - -namespace G3D { - -/** - Constant for passing to Array::resize - */ -const bool DONT_SHRINK_UNDERLYING_ARRAY = false; - -/** Constant for Array::sort */ -const int SORT_INCREASING = 1; -/** Constant for Array::sort */ -const int SORT_DECREASING = -1; - -/** - Dynamic 1D array. - - Objects must have a default constructor (constructor that - takes no arguments) in order to be used with this template. - You will get the error "no appropriate default constructor found" - if they do not. - - Do not use with objects that overload placement operator new, - since the speed of Array is partly due to pooled allocation. - - If SSE is defined Arrays allocate the first element aligned to - 16 bytes. - - - Array is highly optimized compared to std::vector. - Array operations are less expensive than on std::vector and for large - amounts of data, Array consumes only 1.5x the total size of the - data, while std::vector consumes 2.0x. The default - array takes up zero heap space. The first resize (or append) - operation grows it to a reasonable internal size so it is efficient - to append to small arrays. Memory is allocated using - System::alignedMalloc, which produces pointers aligned to 16-byte - boundaries for use with SSE instructions and uses pooled storage for - fast allocation. When Array needs to copy - data internally on a resize operation it correctly invokes copy - constructors of the elements (the MSVC6 implementation of - std::vector uses realloc, which can create memory leaks for classes - containing references and pointers). Array provides a guaranteed - safe way to access the underlying data as a flat C array -- - Array::getCArray. Although (T*)std::vector::begin() can be used for - this purpose, it is not guaranteed to succeed on all platforms. - - To serialize an array, see G3D::serialize. - - The template parameter MIN_ELEMENTS indicates the smallest number of - elements that will be allocated. The default of 10 is designed to avoid - the overhead of repeatedly allocating the array as it grows from 1, to 2, and so on. - If you are creating a lot of small Arrays, however, you may want to set this smaller - to reduce the memory cost. Once the array has been allocated, it will never - deallocate the underlying array unless MIN_ELEMENTS is set to 0, MIN_BYTES is 0, and the array - is empty. - - Do not subclass an Array. - */ -template -class Array { -private: - /** 0...num-1 are initialized elements, num...numAllocated-1 are not */ - T* data; - - int num; - int numAllocated; - - void init(int n, int a) { - debugAssert(n <= a); - debugAssert(n >= 0); - this->num = 0; - this->numAllocated = 0; - data = NULL; - if (a > 0) { - resize(n); - } else { - data = NULL; - } - } - - void _copy(const Array &other) { - init(other.num, other.num); - for (int i = 0; i < num; i++) { - data[i] = other.data[i]; - } - } - - /** - Returns true iff address points to an element of this array. - Used by append. - */ - inline bool inArray(const T* address) { - return (address >= data) && (address < data + num); - } - - - /** Only compiled if you use the sort procedure. */ - static bool __cdecl compareGT(const T& a, const T& b) { - return a > b; - } - - - /** - Allocates a new array of size numAllocated (not a parameter to the method) - and then copies at most oldNum elements from the old array to it. Destructors are - called for oldNum elements of the old array. - */ - void realloc(int oldNum) { - T* oldData = data; - - // The allocation is separate from the constructor invocation because we don't want - // to pay for the cost of constructors until the newly allocated - // elements are actually revealed to the application. They - // will be constructed in the resize() method. - - data = (T*)System::alignedMalloc(sizeof(T) * numAllocated, 16); - - // Call the copy constructors - {const int N = G3D::min(oldNum, numAllocated); - const T* end = data + N; - T* oldPtr = oldData; - for (T* ptr = data; ptr < end; ++ptr, ++oldPtr) { - - // Use placement new to invoke the constructor at the location - // that we determined. Use the copy constructor to make the assignment. - const T* constructed = new (ptr) T(*oldPtr); - - (void)constructed; - debugAssertM(constructed == ptr, - "new returned a different address than the one provided by Array."); - }} - - // Call destructors on the old array (if there is no destructor, this will compile away) - {const T* end = oldData + oldNum; - for (T* ptr = oldData; ptr < end; ++ptr) { - ptr->~T(); - }} - - - System::alignedFree(oldData); - } - -public: - - /** - G3D C++ STL style iterator variable. Call begin() to get - the first iterator, pre-increment (++i) the iterator to get to - the next value. Use dereference (*i) to access the element. - */ - typedef T* Iterator; - /** G3D C++ STL style const iterator in same style as Iterator. */ - typedef const T* ConstIterator; - - /** stl porting compatibility helper */ - typedef Iterator iterator; - /** stl porting compatibility helper */ - typedef ConstIterator const_iterator; - /** stl porting compatibility helper */ - typedef T value_type; - /** stl porting compatibility helper */ - typedef int size_type; - /** stl porting compatibility helper */ - typedef int difference_type; - - /** - C++ STL style iterator method. Returns the first iterator element. - Do not change the size of the array while iterating. - */ - Iterator begin() { - return data; - } - - ConstIterator begin() const { - return data; - } - /** - C++ STL style iterator method. Returns one after the last iterator - element. - */ - ConstIterator end() const { - return data + num; - } - - Iterator end() { - return data + num; - } - - /** - The array returned is only valid until the next append() or resize call, or - the Array is deallocated. - */ - T* getCArray() { - return data; - } - - /** - The array returned is only valid until the next append() or resize call, or - the Array is deallocated. - */ - const T* getCArray() const { - return data; - } - - /** Creates a zero length array (no heap allocation occurs until resize). */ - Array() { - init(0, 0); - } - - /** - Creates an array of size. - */ - Array(int size) { - init(size, size); - } - - /** - Copy constructor - */ - Array(const Array& other) { - _copy(other); - } - - /** - Destructor does not delete() the objects if T is a pointer type - (e.g. T = int*) instead, it deletes the pointers themselves and - leaves the objects. Call deleteAll if you want to dealocate - the objects referenced. Do not call deleteAll if T is not a pointer - type (e.g. do call Array::deleteAll, do not call Array::deleteAll). - */ - ~Array() { - // Invoke the destructors on the elements - for (int i = 0; i < num; i++) { - (data + i)->~T(); - } - - System::alignedFree(data); - // Set to 0 in case this Array is global and gets referenced during app exit - data = NULL; - num = 0; - numAllocated = 0; - } - - - /** - Removes all elements. Use resize(0, false) or fastClear if you want to - remove all elements without deallocating the underlying array - so that future append() calls will be faster. - */ - void clear(bool shrink = true) { - resize(0, shrink); - } - - /** resize(0, false) - @deprecated*/ - void fastClear() { - clear(false); - } - - /** - Assignment operator. - */ - Array& operator=(const Array& other) { - resize(other.num); - for (int i = 0; i < num; ++i) { - data[i] = other[i]; - } - return *this; - } - - Array& operator=(const std::vector& other) { - resize((int)other.size()); - for (int i = 0; i < num; ++i) { - data[i] = other[i]; - } - return *this; - } - - /** - Number of elements in the array. - */ - inline int size() const { - return num; - } - - /** - Number of elements in the array. (Same as size; this is just - here for convenience). - */ - inline int length() const { - return size(); - } - - /** - Swaps element index with the last element in the array then - shrinks the array by one. - */ - void fastRemove(int index, bool shrinkIfNecessary = false) { - debugAssert(index >= 0); - debugAssert(index < num); - data[index] = data[num - 1]; - resize(size() - 1, shrinkIfNecessary); - } - - /** Resizes without shrinking the underlying array. Same as resize(n, false). - @deprecated*/ - void fastResize(int n) { - resize(n, false); - } - - - /** - Inserts at the specified index and shifts all other elements up by one. - */ - void insert(int n, const T& value) { - // Add space for the extra element - resize(num + 1, false); - - for (int i = num - 1; i > n; --i) { - data[i] = data[i - 1]; - } - data[n] = value; - } - - /** @param shrinkIfNecessary if false, memory will never be - reallocated when the array shrinks. This makes resizing much - faster but can waste memory. */ - void resize(int n, bool shrinkIfNecessary = true) { - int oldNum = num; - num = n; - - // Call the destructors on newly hidden elements if there are any - for (int i = num; i < oldNum; ++i) { - (data + i)->~T(); - } - - // Once allocated, always maintain MIN_ELEMENTS elements or 32 bytes, whichever is higher. - static const int minSize = G3D::max(MIN_ELEMENTS, (int)(MIN_BYTES / sizeof(T))); - - if ((MIN_ELEMENTS == 0) && (MIN_BYTES == 0) && (n == 0) && shrinkIfNecessary) { - // Deallocate the array completely - numAllocated = 0; - System::alignedFree(data); - data = NULL; - return; - } - - if (num > numAllocated) { - // Grow the underlying array - - if (numAllocated == 0) { - // First allocation; grow to exactly the size requested to avoid wasting space. - numAllocated = n; - debugAssert(oldNum == 0); - realloc(oldNum); - } else { - - if (num < minSize) { - // Grow to at least the minimum size - numAllocated = minSize; - - } else { - - // Increase the underlying size of the array. Grow aggressively - // up to 64k, less aggressively up to 400k, and then grow relatively - // slowly (1.5x per resize) to avoid excessive space consumption. - // - // These numbers are tweaked according to performance tests. - - float growFactor = 3.0; - - size_t oldSizeBytes = numAllocated * sizeof(T); - if (oldSizeBytes > 400000) { - // Avoid bloat - growFactor = 1.5; - } else if (oldSizeBytes > 64000) { - // This is what std:: uses at all times - growFactor = 2.0; - } - - numAllocated = (num - numAllocated) + (int)(numAllocated * growFactor); - - if (numAllocated < minSize) { - numAllocated = minSize; - } - } - - realloc(oldNum); - } - - } else if ((num <= numAllocated / 3) && shrinkIfNecessary && (num > minSize)) { - // Shrink the underlying array - - // Only copy over old elements that still remain after resizing - // (destructors were called for others if we're shrinking) - realloc(iMin(num, oldNum)); - - } - - // Call the constructors on newly revealed elements. - // Do not use parens because we don't want the intializer - // invoked for POD types. - for (int i = oldNum; i < num; ++i) { - new (data + i) T; - } - } - - /** - Add an element to the end of the array. Will not shrink the underlying array - under any circumstances. It is safe to append an element that is already - in the array. - */ - inline void append(const T& value) { - - if (num < numAllocated) { - // This is a simple situation; just stick it in the next free slot using - // the copy constructor. - new (data + num) T(value); - ++num; - } else if (inArray(&value)) { - // The value was in the original array; resizing - // is dangerous because it may move the value - // we have a reference to. - T tmp = value; - append(tmp); - } else { - // Here we run the empty initializer where we don't have to, but - // this simplifies the computation. - resize(num + 1, DONT_SHRINK_UNDERLYING_ARRAY); - data[num - 1] = value; - } - } - - - inline void append(const T& v1, const T& v2) { - if (inArray(&v1) || inArray(&v2)) { - // Copy into temporaries so that the references won't break when - // the array resizes. - T t1 = v1; - T t2 = v2; - append(t1, t2); - } else if (num + 1 < numAllocated) { - // This is a simple situation; just stick it in the next free slot using - // the copy constructor. - new (data + num) T(v1); - new (data + num + 1) T(v2); - num += 2; - } else { - // Resize the array. Note that neither value is already in the array. - resize(num + 2, DONT_SHRINK_UNDERLYING_ARRAY); - data[num - 2] = v1; - data[num - 1] = v2; - } - } - - - inline void append(const T& v1, const T& v2, const T& v3) { - if (inArray(&v1) || inArray(&v2) || inArray(&v3)) { - T t1 = v1; - T t2 = v2; - T t3 = v3; - append(t1, t2, t3); - } else if (num + 2 < numAllocated) { - // This is a simple situation; just stick it in the next free slot using - // the copy constructor. - new (data + num) T(v1); - new (data + num + 1) T(v2); - new (data + num + 2) T(v3); - num += 3; - } else { - resize(num + 3, DONT_SHRINK_UNDERLYING_ARRAY); - data[num - 3] = v1; - data[num - 2] = v2; - data[num - 1] = v3; - } - } - - - inline void append(const T& v1, const T& v2, const T& v3, const T& v4) { - if (inArray(&v1) || inArray(&v2) || inArray(&v3) || inArray(&v4)) { - T t1 = v1; - T t2 = v2; - T t3 = v3; - T t4 = v4; - append(t1, t2, t3, t4); - } else if (num + 3 < numAllocated) { - // This is a simple situation; just stick it in the next free slot using - // the copy constructor. - new (data + num) T(v1); - new (data + num + 1) T(v2); - new (data + num + 2) T(v3); - new (data + num + 3) T(v4); - num += 4; - } else { - resize(num + 4, DONT_SHRINK_UNDERLYING_ARRAY); - data[num - 4] = v1; - data[num - 3] = v2; - data[num - 2] = v3; - data[num - 1] = v4; - } - } - - /** - Returns true if the given element is in the array. - */ - bool contains(const T& e) const { - for (int i = 0; i < size(); ++i) { - if ((*this)[i] == e) { - return true; - } - } - - return false; - } - - /** - Append the elements of array. Cannot be called with this array - as an argument. - */ - void append(const Array& array) { - debugAssert(this != &array); - int oldNum = num; - int arrayLength = array.length(); - - resize(num + arrayLength, false); - - for (int i = 0; i < arrayLength; i++) { - data[oldNum + i] = array.data[i]; - } - } - - /** - Pushes a new element onto the end and returns its address. - This is the same as A.resize(A.size() + 1, false); A.last() - */ - inline T& next() { - resize(num + 1, false); - return last(); - } - - /** - Pushes an element onto the end (appends) - */ - inline void push(const T& value) { - append(value); - } - - inline void push(const Array& array) { - append(array); - } - - /** Alias to provide std::vector compatibility */ - inline void push_back(const T& v) { - push(v); - } - - /** "The member function removes the last element of the controlled sequence, which must be non-empty." - For compatibility with std::vector. */ - inline void pop_back() { - pop(); - } - - /** - "The member function returns the storage currently allocated to hold the controlled - sequence, a value at least as large as size()" - For compatibility with std::vector. - */ - int capacity() const { - return numAllocated; - } - - /** - "The member function returns a reference to the first element of the controlled sequence, - which must be non-empty." - For compatibility with std::vector. - */ - T& front() { - return (*this)[0]; - } - - /** - "The member function returns a reference to the first element of the controlled sequence, - which must be non-empty." - For compatibility with std::vector. - */ - const T& front() const { - return (*this)[0]; - } - - /** - Removes the last element and returns it. By default, shrinks the underlying array. - */ - inline T pop(bool shrinkUnderlyingArrayIfNecessary = true) { - debugAssert(num > 0); - T temp = data[num - 1]; - resize(num - 1, shrinkUnderlyingArrayIfNecessary); - return temp; - } - - /** Pops the last element and discards it without returning anything. Faster than pop. - By default, does not shrink the underlying array.*/ - inline void popDiscard(bool shrinkUnderlyingArrayIfNecessary = false) { - debugAssert(num > 0); - resize(num - 1, shrinkUnderlyingArrayIfNecessary); - } - - - /** - "The member function swaps the controlled sequences between *this and str." - Note that this is slower than the optimal std implementation. - - For compatibility with std::vector. - */ - void swap(Array& str) { - Array temp = str; - str = *this; - *this = temp; - } - - - /** - Performs bounds checks in debug mode - */ - inline T& operator[](int n) { - debugAssertM((n >= 0) && (n < num), format("Array index out of bounds. n = %d, size() = %d", n, num)); - debugAssert(data!=NULL); - return data[n]; - } - - inline T& operator[](unsigned int n) { - debugAssertM(n < (unsigned int)num, format("Array index out of bounds. n = %d, size() = %d", n, num)); - return data[n]; - } - - /** - Performs bounds checks in debug mode - */ - inline const T& operator[](int n) const { - debugAssert((n >= 0) && (n < num)); - debugAssert(data!=NULL); - return data[n]; - } - - inline const T& operator[](unsigned int n) const { - debugAssert((n < (unsigned int)num)); - debugAssert(data!=NULL); - return data[n]; - } - - inline T& randomElement() { - debugAssert(num > 0); - debugAssert(data!=NULL); - return data[iRandom(0, num - 1)]; - } - - inline const T& randomElement() const { - debugAssert(num > 0); - debugAssert(data!=NULL); - return data[iRandom(0, num - 1)]; - } - - /** - Returns the last element, performing a check in - debug mode that there is at least one element. - */ - inline const T& last() const { - debugAssert(num > 0); - debugAssert(data!=NULL); - return data[num - 1]; - } - - /** Returns element lastIndex() */ - inline T& last() { - debugAssert(num > 0); - debugAssert(data!=NULL); - return data[num - 1]; - } - - /** Returns size() - 1 */ - inline int lastIndex() const { - debugAssertM(num > 0, "Array is empty"); - return num - 1; - } - - inline int firstIndex() const { - debugAssertM(num > 0, "Array is empty"); - return 0; - } - - /** Returns element firstIndex(), performing a check in debug mode to ensure that there is at least one */ - inline T& first() { - debugAssertM(num > 0, "Array is empty"); - return data[0]; - } - - inline const T& first() const { - debugAssertM(num > 0, "Array is empty"); - return data[0]; - } - - /** Returns iFloor(size() / 2), throws an assertion in debug mode if the array is empty */ - inline int middleIndex() const { - debugAssertM(num > 0, "Array is empty"); - return num >> 1; - } - - /** Returns element middleIndex() */ - inline const T& middle() const { - debugAssertM(num > 0, "Array is empty"); - return data[num >> 1]; - } - - /** Returns element middleIndex() */ - inline T& middle() { - debugAssertM(num > 0, "Array is empty"); - return data[num >> 1]; - } - - /** - Calls delete on all objects[0...size-1] - and sets the size to zero. - */ - void deleteAll() { - for (int i = 0; i < num; i++) { - delete data[i]; - } - resize(0); - } - - /** - Returns the index of (the first occurance of) an index or -1 if - not found. - */ - int findIndex(const T& value) const { - for (int i = 0; i < num; ++i) { - if (data[i] == value) { - return i; - } - } - return -1; - } - - /** - Finds an element and returns the iterator to it. If the element - isn't found then returns end(). - */ - Iterator find(const T& value) { - for (int i = 0; i < num; ++i) { - if (data[i] == value) { - return data + i; - } - } - return end(); - } - - ConstIterator find(const T& value) const { - for (int i = 0; i < num; ++i) { - if (data[i] == value) { - return data + i; - } - } - return end(); - } - - /** - Removes count elements from the array - referenced either by index or Iterator. - */ - void remove(Iterator element, int count = 1) { - debugAssert((element >= begin()) && (element < end())); - debugAssert((count > 0) && (element + count) <= end()); - Iterator last = end() - count; - - while(element < last) { - element[0] = element[count]; - ++element; - } - - resize(num - count); - } - - void remove(int index, int count = 1) { - debugAssert((index >= 0) && (index < num)); - debugAssert((count > 0) && (index + count <= num)); - - remove(begin() + index, count); - } - - /** - Reverse the elements of the array in place. - */ - void reverse() { - T temp; - - int n2 = num / 2; - for (int i = 0; i < n2; ++i) { - temp = data[num - 1 - i]; - data[num - 1 - i] = data[i]; - data[i] = temp; - } - } - - /** - Sort using a specific less-than function, e.g.: - -
-    bool __cdecl myLT(const MyClass& elem1, const MyClass& elem2) {
-        return elem1.x < elem2.x;
-    }
-    
- - Note that for pointer arrays, the const must come - after the class name, e.g., Array uses: - -
-    bool __cdecl myLT(MyClass*const& elem1, MyClass*const& elem2) {
-        return elem1->x < elem2->x;
-    }
-    
- */ - void sort(bool (__cdecl *lessThan)(const T& elem1, const T& elem2)) { - std::sort(data, data + num, lessThan); - } - - - /** - Sorts the array in increasing order using the > or < operator. To - invoke this method on Array, T must override those operator. - You can overide these operators as follows: - - bool T::operator>(const T& other) const { - return ...; - } - bool T::operator<(const T& other) const { - return ...; - } - - */ - void sort(int direction = SORT_INCREASING) { - if (direction == SORT_INCREASING) { - std::sort(data, data + num); - } else { - std::sort(data, data + num, compareGT); - } - } - - /** - Sorts elements beginIndex through and including endIndex. - */ - void sortSubArray(int beginIndex, int endIndex, int direction = SORT_INCREASING) { - if (direction == SORT_INCREASING) { - std::sort(data + beginIndex, data + endIndex + 1); - } else { - std::sort(data + beginIndex, data + endIndex + 1, compareGT); - } - } - - void sortSubArray(int beginIndex, int endIndex, bool (__cdecl *lessThan)(const T& elem1, const T& elem2)) { - std::sort(data + beginIndex, data + endIndex + 1, lessThan); - } - - /** - The StrictWeakOrdering can be either a class that overloads the function call operator() or - a function pointer of the form bool (__cdecl *lessThan)(const T& elem1, const T& elem2) - */ - template - void sortSubArray(int beginIndex, int endIndex, StrictWeakOrdering& lessThan) { - std::sort(data + beginIndex, data + endIndex + 1, lessThan); - } - - /** Uses < and == to evaluate operator(); this is the default comparator for Array::partition. */ - class DefaultComparator { - public: - inline int operator()(const T& A, const T& B) const { - if (A < B) { - return 1; - } else if (A == B) { - return 0; - } else { - return -1; - } - } - }; - - /** The output arrays are resized with fastClear() so that if they are already of the same size - as this array no memory is allocated during partitioning. - - @param comparator A function, or class instance with an overloaded operator() that compares - two elements of type T and returns 0 if they are equal, -1 if the second is smaller, - and 1 if the first is smaller (i.e., following the conventions of std::string::compare). For example: - -
-        int compare(int A, int B) {
-            if (A < B) {
-                return 1;
-            } else if (A == B) {
-                return 0;
-            } else {
-                return -1;
-            }
-        }
-        
- */ - template - void partition( - const T& partitionElement, - Array& ltArray, - Array& eqArray, - Array& gtArray, - const Comparator& comparator) const { - - // Make sure all arrays are independent - debugAssert(<Array != this); - debugAssert(&eqArray != this); - debugAssert(>Array != this); - debugAssert(<Array != &eqArray); - debugAssert(<Array != >Array); - debugAssert(&eqArray != >Array); - - // Clear the arrays - ltArray.fastClear(); - eqArray.fastClear(); - gtArray.fastClear(); - - // Form a table of buckets for lt, eq, and gt - Array* bucket[3] = {<Array, &eqArray, >Array}; - - for (int i = 0; i < num; ++i) { - int c = comparator(partitionElement, data[i]); - debugAssertM(c >= -1 && c <= 1, "Comparator returned an illegal value."); - - // Insert into the correct bucket, 0, 1, or 2 - bucket[c + 1]->append(data[i]); - } - } - - /** - Uses < and == on elements to perform a partition. See partition(). - */ - void partition( - const T& partitionElement, - Array& ltArray, - Array& eqArray, - Array& gtArray) const { - - partition(partitionElement, ltArray, eqArray, gtArray, typename Array::DefaultComparator()); - } - - /** - Paritions the array into those below the median, those above the median, and those elements - equal to the median in expected O(n) time using quickselect. If the array has an even - number of different elements, the median for partition purposes is the largest value - less than the median. - - @param tempArray used for working scratch space - @param comparator see parition() for a discussion.*/ - template - void medianPartition( - Array& ltMedian, - Array& eqMedian, - Array& gtMedian, - Array& tempArray, - const Comparator& comparator) const { - - ltMedian.fastClear(); - eqMedian.fastClear(); - gtMedian.fastClear(); - - // Handle trivial cases first - switch (size()) { - case 0: - // Array is empty; no parition is possible - return; - - case 1: - // One element - eqMedian.append(first()); - return; - - case 2: - { - // Two element array; median is the smaller - int c = comparator(first(), last()); - - switch (c) { - case -1: - // first was bigger - eqMedian.append(last()); - gtMedian.append(first()); - break; - - case 0: - // Both equal to the median - eqMedian.append(first(), last()); - break; - - case 1: - // Last was bigger - eqMedian.append(first()); - gtMedian.append(last()); - break; - } - } - return; - } - - // All other cases use a recursive randomized median - - // Number of values less than all in the current arrays - int ltBoost = 0; - - // Number of values greater than all in the current arrays - int gtBoost = 0; - - // For even length arrays, force the gt array to be one larger than the - // lt array: - // [1 2 3] size = 3, choose half = (s + 1) /2 - // - int lowerHalfSize, upperHalfSize; - if (isEven(size())) { - lowerHalfSize = size() / 2; - upperHalfSize = lowerHalfSize + 1; - } else { - lowerHalfSize = upperHalfSize = (size() + 1) / 2; - } - const T* xPtr = NULL; - - // Maintain pointers to the arrays; we'll switch these around during sorting - // to avoid copies. - const Array* source = this; - Array* lt = <Median; - Array* eq = &eqMedian; - Array* gt = >Median; - Array* extra = &tempArray; - - while (true) { - // Choose a random element -- choose the middle element; this is theoretically - // suboptimal, but for loosly sorted array is actually the best strategy - - xPtr = &(source->middle()); - if (source->size() == 1) { - // Done; there's only one element left - break; - } - const T& x = *xPtr; - - // Note: partition (fast) clears the arrays for us - source->partition(x, *lt, *eq, *gt, comparator); - - int L = lt->size() + ltBoost + eq->size(); - int U = gt->size() + gtBoost + eq->size(); - if ((L >= lowerHalfSize) && - (U >= upperHalfSize)) { - - // x must be the partition median - break; - - } else if (L < lowerHalfSize) { - - // x must be smaller than the median. Recurse into the 'gt' array. - ltBoost += lt->size() + eq->size(); - - // The new gt array will be the old source array, unless - // that was the this pointer (i.e., unless we are on the - // first iteration) - Array* newGt = (source == this) ? extra : const_cast*>(source); - - // Now set up the gt array as the new source - source = gt; - gt = newGt; - - } else { - - // x must be bigger than the median. Recurse into the 'lt' array. - gtBoost += gt->size() + eq->size(); - - // The new lt array will be the old source array, unless - // that was the this pointer (i.e., unless we are on the - // first iteration) - Array* newLt = (source == this) ? extra : const_cast*>(source); - - // Now set up the lt array as the new source - source = lt; - lt = newLt; - } - } - - // Now that we know the median, make a copy of it (since we're about to destroy the array that it - // points into). - T median = *xPtr; - xPtr = NULL; - - // Partition the original array (note that this fast clears for us) - partition(median, ltMedian, eqMedian, gtMedian, comparator); - } - - /** - Computes a median partition using the default comparator and a dynamically allocated temporary - working array. If the median is not in the array, it is chosen to be the largest value smaller - than the true median. - */ - void medianPartition( - Array& ltMedian, - Array& eqMedian, - Array& gtMedian) const { - - Array temp; - medianPartition(ltMedian, eqMedian, gtMedian, temp, DefaultComparator()); - } - - - /** Redistributes the elements so that the new order is statistically independent - of the original order. O(n) time.*/ - void randomize() { - T temp; - - for (int i = size() - 1; i >= 0; --i) { - int x = iRandom(0, i); - - temp = data[i]; - data[i] = data[x]; - data[x] = temp; - } - } - - -}; - - -/** Array::contains for C-arrays */ -template bool contains(const T* array, int len, const T& e) { - for (int i = len - 1; i >= 0; --i) { - if (array[i] == e) { - return true; - } - } - return false; -} - -} // namespace - -#ifdef _MSC_VER -# pragma warning (pop) -#endif - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/AtomicInt32.h b/externals/g3dlite/G3D.lib/include/G3D/AtomicInt32.h deleted file mode 100644 index 9d58e02efe5..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/AtomicInt32.h +++ /dev/null @@ -1,166 +0,0 @@ -/** - @file AtomicInt32.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2005-09-01 - @edited 2006-06-21 - */ -#ifndef G3D_ATOMICINT32_H -#define G3D_ATOMICINT32_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" - -#if defined(G3D_OSX) - #include -#endif - -namespace G3D { - -/** - An integer that may safely be used on different threads without - external locking. - - On Win32, Linux, FreeBSD, and Mac OS X this is implemented without locks. - - BETA API This is unsupported and may change - */ -class AtomicInt32 { -private: -# if defined(G3D_WIN32) - volatile long m_value; -# elif defined(G3D_OSX) - int32_t m_value; -# else - volatile int32 m_value; -# endif - - -public: - - /** Initial value is undefined. */ - AtomicInt32() {} - - /** Atomic set */ - explicit AtomicInt32(const int32 x) { - m_value = x; - } - - /** Atomic set */ - AtomicInt32(const AtomicInt32& x) { - m_value = x.m_value; - } - - /** Atomic set */ - const AtomicInt32& operator=(const int32 x) { - m_value = x; - return *this; - } - - /** Atomic set */ - void operator=(const AtomicInt32& x) { - m_value = x.m_value; - } - - /** Returns the current value */ - int32 value() const { - return m_value; - } - - /** Returns the old value, before the add. */ - int32 add(const int32 x) { -# if defined(G3D_WIN32) - - return InterlockedExchangeAdd(&m_value, x); - -# elif defined(G3D_LINUX) || defined(G3D_FREEBSD) - - int32 old; - asm volatile ("lock; xaddl %0,%1" - : "=r"(old), "=m"(m_value) /* outputs */ - : "0"(x), "m"(m_value) /* inputs */ - : "memory", "cc"); - return old; - -# elif defined(G3D_OSX) - - int32 old = m_value; - OSAtomicAdd32(x, &m_value); - return old; - -# endif - } - - /** Returns old value. */ - int32 sub(const int32 x) { - return add(-x); - } - - void increment() { -# if defined(G3D_WIN32) - // Note: returns the newly incremented value - InterlockedIncrement(&m_value); -# elif defined(G3D_LINUX) || defined(G3D_FREEBSD) - add(1); -# elif defined(G3D_OSX) - // Note: returns the newly incremented value - OSAtomicIncrement32(&m_value); -# endif - } - - /** Returns zero if the result is zero after decrement, non-zero otherwise.*/ - int32 decrement() { -# if defined(G3D_WIN32) - // Note: returns the newly decremented value - return InterlockedDecrement(&m_value); -# elif defined(G3D_LINUX) || defined(G3D_FREEBSD) - unsigned char nz; - - asm volatile ("lock; decl %1;\n\t" - "setnz %%al" - : "=a" (nz) - : "m" (m_value) - : "memory", "cc"); - return nz; -# elif defined(G3D_OSX) - // Note: returns the newly decremented value - return OSAtomicDecrement32(&m_value); -# endif - } - - - /** Atomic test-and-set: if *this == comperand then *this := exchange else do nothing. - In both cases, returns the old value of *this. - - Performs an atomic comparison of this with the Comperand value. - If this is equal to the Comperand value, the Exchange value is stored in this. - Otherwise, no operation is performed. - - Under VC6 the sign bit may be lost. - - */ - int32 compareAndSet(const int32 comperand, const int32 exchange) { -# if defined(G3D_WIN32) - return InterlockedCompareExchange(&m_value, exchange, comperand); -# elif defined(G3D_LINUX) || defined(G3D_FREEBSD) - int32 ret; - asm volatile ("lock; cmpxchgl %1, %2" - : "=a" (ret) - : "r" (exchange), "m" (m_value), "0"(comperand) - : "memory", "cc"); - return ret; -# elif defined(G3D_OSX) - int32 old = m_value; - - OSAtomicCompareAndSwap32(comperand, exchange, &m_value); - - return old; -# endif - } - -}; - -} // namespace - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/BinaryFormat.h b/externals/g3dlite/G3D.lib/include/G3D/BinaryFormat.h deleted file mode 100644 index 53f0c144bf6..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/BinaryFormat.h +++ /dev/null @@ -1,140 +0,0 @@ -/** - @file BinaryFormat.h - @maintainer Morgan McGuire, matrix@graphics3d.com - - @author 2005-06-03 - @edited 2005-06-03 - - Copyright 2000-2005, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_BINARYFORMAT_H -#define G3D_BINARYFORMAT_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" - -namespace G3D { - -class Vector2; -class Vector2int16; -class Vector3; -class Vector3int16; -class Vector4; -class Vector4int16; -class Color3; -class Color3uint8; -class Color4; -class Color4uint8; - -/** - Some values like float16 and int128 have no current CPU data structure that implements them but are useful - for file formats and for GPUs. - - CHUNK_BINFMT data follows the protocol. - */ -// Must be packed int 16 bits for the chunk reader -// We can't name these just "INT8" etc. because some libraries #define names like that -enum BinaryFormat { - FIRST_BINFMT = 1000, - - BOOL8_BINFMT, - UINT8_BINFMT, INT8_BINFMT, UINT16_BINFMT, INT16_BINFMT, UINT32_BINFMT, INT32_BINFMT, UINT64_BINFMT, INT64_BINFMT, UINT128_BINFMT, INT128_BINFMT, - FLOAT16_BINFMT, FLOAT32_BINFMT, FLOAT64_BINFMT, - VECTOR2_BINFMT, VECTOR2INT16_BINFMT, - VECTOR3_BINFMT, VECTOR3INT16_BINFMT, - VECTOR4_BINFMT, VECTOR4INT16_BINFMT, - COLOR3_BINFMT, COLOR3UINT8_BINFMT, COLOR3INT16_BINFMT, - COLOR4_BINFMT, COLOR4UINT8_BINFMT, COLOR4INT16_BINFMT, - STRING_BINFMT, STRINGEVEN_BINFMT, STRING8_BINFMT, STRING16_BINFMT, STRING32_BINFMT, - - CHUNK_BINFMT, - - CUSTOM_BINFMT, - - LAST_BINFMT -}; - -} - -/** A macro that maps G3D types to format constants. - (e.g. binaryFormatOf(Vector3) == VECTOR3_BINFMT). -*/ -// This implementation is designed to meet the following constraints: -// 1. Work around the many MSVC++ partial template bugs -// 2. Work for primitive types (e.g. int) -#define binaryFormatOf(T) (G3D::_internal::_BinaryFormat::x()) - -namespace G3D { -namespace _internal { - - -template class _BinaryFormat { -public: - static BinaryFormat x() { - return CUSTOM_BINFMT; - } -}; -}} - - -/** - Macro to declare the underlying format (as will be returned by glFormatOf) - of a type. For example, - -
-    DECLARE_BINARYFORMATOF(Vector4, VECTOR4_BINFMT)
-  
- - Use this so you can make vertex arrays of your own classes and not just - the standard ones. - */ -#define DECLARE_BINARYFORMATOF(CType, EnumType) \ -namespace G3D { \ - namespace _internal { \ - template<> class _BinaryFormat { \ - public: \ - static BinaryFormat x() { \ - return EnumType; \ - } \ - }; \ - } \ -} - -DECLARE_BINARYFORMATOF( bool, BOOL8_BINFMT ) - -DECLARE_BINARYFORMATOF( uint8, UINT8_BINFMT ) -DECLARE_BINARYFORMATOF( int8, INT8_BINFMT ) -DECLARE_BINARYFORMATOF( uint16, UINT16_BINFMT ) -DECLARE_BINARYFORMATOF( int16, INT16_BINFMT ) -DECLARE_BINARYFORMATOF( uint32, UINT32_BINFMT ) -DECLARE_BINARYFORMATOF( int32, INT32_BINFMT ) -DECLARE_BINARYFORMATOF( uint64, UINT64_BINFMT ) -DECLARE_BINARYFORMATOF( int64, INT64_BINFMT ) - -DECLARE_BINARYFORMATOF( float32, FLOAT32_BINFMT ) -DECLARE_BINARYFORMATOF( float64, FLOAT64_BINFMT ) - -DECLARE_BINARYFORMATOF( Vector2, VECTOR2_BINFMT ) -DECLARE_BINARYFORMATOF( Vector2int16, VECTOR2INT16_BINFMT ) -DECLARE_BINARYFORMATOF( Vector3, VECTOR3_BINFMT ) -DECLARE_BINARYFORMATOF( Vector3int16, VECTOR3INT16_BINFMT ) -DECLARE_BINARYFORMATOF( Vector4, VECTOR4_BINFMT ) -DECLARE_BINARYFORMATOF( Vector4int16, VECTOR4INT16_BINFMT ) - -DECLARE_BINARYFORMATOF( Color3, COLOR3_BINFMT ) -DECLARE_BINARYFORMATOF( Color3uint8, COLOR3UINT8_BINFMT ) -DECLARE_BINARYFORMATOF( Color4, COLOR4_BINFMT ) -DECLARE_BINARYFORMATOF( Color4uint8, COLOR4UINT8_BINFMT ) - -namespace G3D { - -/** Returns -1 if the format is custom, otherwise the byte size - of a single element in this format.*/ -int32 byteSize(BinaryFormat f); - - -} //G3D - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/BinaryInput.h b/externals/g3dlite/G3D.lib/include/G3D/BinaryInput.h deleted file mode 100644 index c0ab9052402..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/BinaryInput.h +++ /dev/null @@ -1,441 +0,0 @@ -/** - @file BinaryInput.h - - @maintainer Morgan McGuire, graphics3d.com - - @created 2001-08-09 - @edited 2006-07-19 - - Copyright 2000-2007, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_BINARYINPUT_H -#define G3D_BINARYINPUT_H - -#ifdef _MSC_VER -// Disable conditional expression is constant, which occurs incorrectly on inlined functions -# pragma warning(push) -# pragma warning( disable : 4127 ) -#endif - -#include -#include -#include -#include -#include -#include -#include "G3D/platform.h" -#include "G3D/Array.h" -#include "G3D/Color4.h" -#include "G3D/Color3.h" -#include "G3D/Vector4.h" -#include "G3D/Vector3.h" -#include "G3D/Vector2.h" -#include "G3D/g3dmath.h" -#include "G3D/debug.h" -#include "G3D/System.h" - - -namespace G3D { - -#if defined(G3D_WIN32) || defined(G3D_LINUX) - // Allow writing of integers to non-word aligned locations. - // This is legal on x86, but not on other platforms. - #define G3D_ALLOW_UNALIGNED_WRITES -#endif - -/** - Sequential or random access byte-order independent binary file access. - Files compressed with zlib and beginning with an unsigned 32-bit int - size are transparently decompressed when the compressed = true flag is - specified to the constructor. - - For every readX method there are also versions that operate on a whole - Array, std::vector, or C-array. e.g. readFloat32(Array& array, n) - These methods resize the array or std::vector to the appropriate size - before reading. For a C-array, they require the pointer to reference - a memory block at least large enough to hold n elements. - - Most classes define serialize/deserialize methods that use BinaryInput, - BinaryOutput, TextInput, and TextOutput. There are text serializer - functions for primitive types (e.g. int, std::string, float, double) but not - binary serializers-- you must call the BinaryInput::readInt32 or - other appropriate function. This is because it would be very hard to - debug the error sequence: serialize(1.0, bo); ... float f; deserialize(f, bi); - in which a double is serialized and then deserialized as a float. - */ -class BinaryInput { -private: - - // The initial buffer will be no larger than this, but - // may grow if a large memory read occurs. 50 MB - enum {INITIAL_BUFFER_LENGTH = 50000000}; - - /** - is the file big or little endian - */ - G3DEndian m_fileEndian; - std::string m_filename; - - bool m_swapBytes; - - /** Next position to read from in bitString during readBits. */ - int m_bitPos; - - /** Bits currently being read by readBits. - Contains at most 8 (low) bits. Note that - beginBits/readBits actually consumes one extra byte, which - will be restored by writeBits.*/ - uint32 m_bitString; - - /** 1 when between beginBits and endBits, 0 otherwise. */ - int m_beginEndBits; - - /** When operating on huge files, we cannot load the whole file into memory. - This is the file position to which buffer[0] corresponds. - */ - int64 m_alreadyRead; - - /** - Length of the entire file, in bytes. - For the length of the buffer, see bufferLength - */ - int64 m_length; - - /** Length of the array referenced by buffer. May go past the end of the file!*/ - int64 m_bufferLength; - uint8* m_buffer; - - /** - Next byte in file, relative to buffer. - */ - int64 m_pos; - - /** - When true, the buffer is freed in the destructor. - */ - bool m_freeBuffer; - - /** Ensures that we are able to read at least minLength from startPosition (relative - to start of file). */ - void loadIntoMemory(int64 startPosition, int64 minLength = 0); - - /** Verifies that at least this number of bytes can be read.*/ - inline void prepareToRead(int64 nbytes) { - debugAssertM(m_length > 0, m_filename + " not found or corrupt."); - debugAssertM(m_pos + nbytes + m_alreadyRead <= m_length, "Read past end of file."); - - if (m_pos + nbytes > m_bufferLength) { - loadIntoMemory(m_pos + m_alreadyRead, nbytes); - } - } - - // Not implemented on purpose, don't use - BinaryInput(const BinaryInput&); - BinaryInput& operator=(const BinaryInput&); - bool operator==(const BinaryInput&); - - /** Buffer is compressed; replace it with a decompressed version */ - void decompress(); -public: - - /** false, constant to use with the copyMemory option */ - static const bool NO_COPY; - - /** - If the file cannot be opened, a zero length buffer is presented. - Automatically opens files that are inside zipfiles. - - @param compressed Set to true if and only if the file was - compressed using BinaryOutput's zlib compression. This has - nothing to do with whether the input is in a zipfile. - */ - BinaryInput( - const std::string& filename, - G3DEndian fileEndian, - bool compressed = false); - - /** - Creates input stream from an in memory source. - Unless you specify copyMemory = false, the data is copied - from the pointer, so you may deallocate it as soon as the - object is constructed. It is an error to specify copyMemory = false - and compressed = true. - - To decompress part of a file, you can follow the following paradigm: - -
-        BinaryInput master(...);
-
-        // read from master to point where compressed data exists.
-
-        BinaryInput subset(master.getCArray() + master.getPosition(), 
-                           master.length() - master.getPosition(),
-                           master.endian(), true, true);
-
-        // Now read from subset (it is ok for master to go out of scope)
-     
- */ - BinaryInput( - const uint8* data, - int64 dataLen, - G3DEndian dataEndian, - bool compressed = false, - bool copyMemory = true); - - virtual ~BinaryInput(); - - /** Change the endian-ness of the file. This only changes the - interpretation of the file for future read calls; the - underlying data is unmodified.*/ - void setEndian(G3DEndian endian); - - G3DEndian endian() const { - return m_fileEndian; - } - - std::string getFilename() const { - return m_filename; - } - - /** - Returns a pointer to the internal memory buffer. - May throw an exception for huge files. - */ - const uint8* getCArray() const { - if (m_alreadyRead > 0) { - throw "Cannot getCArray for a huge file"; - } - return m_buffer; - } - - /** - Performs bounds checks in debug mode. [] are relative to - the start of the file, not the current position. - Seeks to the new position before reading (and leaves - that as the current position) - */ - inline uint8 operator[](int64 n) { - setPosition(n); - return readUInt8(); - } - - /** - Returns the length of the file in bytes. - */ - inline int64 getLength() const { - return m_length; - } - - inline int64 size() const { - return getLength(); - } - - /** - Returns the current byte position in the file, - where 0 is the beginning and getLength() - 1 is the end. - */ - inline int64 getPosition() const { - return m_pos + m_alreadyRead; - } - - /** - Sets the position. Cannot set past length. - May throw a char* when seeking backwards more than 10 MB on a huge file. - */ - inline void setPosition(int64 p) { - debugAssertM(p <= m_length, "Read past end of file"); - m_pos = p - m_alreadyRead; - if ((m_pos < 0) || (m_pos > m_bufferLength)) { - loadIntoMemory(m_pos + m_alreadyRead); - } - } - - /** - Goes back to the beginning of the file. - */ - inline void reset() { - setPosition(0); - } - - inline int8 readInt8() { - prepareToRead(1); - return m_buffer[m_pos++]; - } - - inline bool readBool8() { - return (readInt8() != 0); - } - - inline uint8 readUInt8() { - prepareToRead(1); - return ((uint8*)m_buffer)[m_pos++]; - } - - uint16 inline readUInt16() { - prepareToRead(2); - - m_pos += 2; - if (m_swapBytes) { - uint8 out[2]; - out[0] = m_buffer[m_pos - 1]; - out[1] = m_buffer[m_pos - 2]; - return *(uint16*)out; - } else { - #ifdef G3D_ALLOW_UNALIGNED_WRITES - return *(uint16*)(&m_buffer[m_pos - 2]); - #else - uint8 out[2]; - out[0] = m_buffer[m_pos - 2]; - out[1] = m_buffer[m_pos - 1]; - return *(uint16*)out; - #endif - } - - } - - inline int16 readInt16() { - uint16 a = readUInt16(); - return *(int16*)&a; - } - - inline uint32 readUInt32() { - prepareToRead(4); - - m_pos += 4; - if (m_swapBytes) { - uint8 out[4]; - out[0] = m_buffer[m_pos - 1]; - out[1] = m_buffer[m_pos - 2]; - out[2] = m_buffer[m_pos - 3]; - out[3] = m_buffer[m_pos - 4]; - return *(uint32*)out; - } else { - #ifdef G3D_ALLOW_UNALIGNED_WRITES - return *(uint32*)(&m_buffer[m_pos - 4]); - #else - uint8 out[4]; - out[0] = m_buffer[m_pos - 4]; - out[1] = m_buffer[m_pos - 3]; - out[2] = m_buffer[m_pos - 2]; - out[3] = m_buffer[m_pos - 1]; - return *(uint32*)out; - #endif - } - } - - - inline int32 readInt32() { - uint32 a = readUInt32(); - return *(int32*)&a; - } - - uint64 readUInt64(); - - inline int64 readInt64() { - uint64 a = readUInt64(); - return *(int64*)&a; - } - - inline float32 readFloat32() { - union { - uint32 a; - float32 b; - }; - a = readUInt32(); - return b; - } - - inline float64 readFloat64() { - union { - uint64 a; - float64 b; - }; - a = readUInt64(); - return b; - } - - void readBytes(void* bytes, int64 n); - - /** - Reads an n character string. The string is not - required to end in NULL in the file but will - always be a proper std::string when returned. - */ - std::string readString(int64 n); - - /** - Reads until NULL or the end of the file is encountered. - */ - std::string readString(); - - /** - Reads until NULL or the end of the file is encountered. - If the string has odd length (including NULL), reads - another byte. - */ - std::string readStringEven(); - - - std::string readString32(); - - Vector4 readVector4(); - Vector3 readVector3(); - Vector2 readVector2(); - - Color4 readColor4(); - Color3 readColor3(); - - /** - Skips ahead n bytes. - */ - inline void skip(int64 n) { - setPosition(m_pos + m_alreadyRead + n); - } - - /** - Returns true if the position is not at the end of the file - */ - inline bool hasMore() const { - return m_pos + m_alreadyRead < m_length; - } - - /** Prepares for bit reading via readBits. Only readBits can be - called between beginBits and endBits without corrupting the - data stream. */ - void beginBits(); - - /** Can only be called between beginBits and endBits */ - uint32 readBits(int numBits); - - /** Ends bit-reading. */ - void endBits(); - -# define DECLARE_READER(ucase, lcase)\ - void read##ucase(lcase* out, int64 n);\ - void read##ucase(std::vector& out, int64 n);\ - void read##ucase(Array& out, int64 n); - - DECLARE_READER(Bool8, bool) - DECLARE_READER(UInt8, uint8) - DECLARE_READER(Int8, int8) - DECLARE_READER(UInt16, uint16) - DECLARE_READER(Int16, int16) - DECLARE_READER(UInt32, uint32) - DECLARE_READER(Int32, int32) - DECLARE_READER(UInt64, uint64) - DECLARE_READER(Int64, int64) - DECLARE_READER(Float32, float32) - DECLARE_READER(Float64, float64) -# undef DECLARE_READER -}; - - -} - -#ifdef _MSC_VER -# pragma warning(pop) -#endif - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/BinaryOutput.h b/externals/g3dlite/G3D.lib/include/G3D/BinaryOutput.h deleted file mode 100644 index d81ec56a67b..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/BinaryOutput.h +++ /dev/null @@ -1,421 +0,0 @@ -/** - @file BinaryOutput.h - - @maintainer Morgan McGuire, graphics3d.com - - @created 2001-08-09 - @edited 2008-01-24 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_BINARYOUTPUT_H -#define G3D_BINARYOUTPUT_H - -#include "G3D/platform.h" -#include -#include -#include -#include -#include -#include "G3D/Color4.h" -#include "G3D/Color3.h" -#include "G3D/Vector4.h" -#include "G3D/Vector3.h" -#include "G3D/Vector2.h" -#include "G3D/g3dmath.h" -#include "G3D/debug.h" -#include "G3D/BinaryInput.h" -#include "G3D/System.h" - -#ifdef _MSC_VER -# pragma warning (push) -// Conditional is constant (wrong in inline) -# pragma warning (disable : 4127) -#endif -namespace G3D { - -/** - Sequential or random access byte-order independent binary file access. - - The compress() call can be used to compress with zlib. - - Any method call can trigger an out of memory error (thrown as char*) - when writing to "" instead of a file. - - Compressed writing and seeking backwards is not supported for huge files - (i.e., BinaryOutput may have to dump the contents to disk if they - exceed available RAM). - */ -class BinaryOutput { -private: - std::string m_filename; - - bool m_committed; - - /** 0 outside of beginBits...endBits, 1 inside */ - int m_beginEndBits; - - /** The current string of bits being built up by beginBits...endBits. - This string is treated semantically, as if the lowest bit was - on the left and the highest was on the right.*/ - int8 m_bitString; - - /** Position (from the lowest bit) currently used in bitString.*/ - int m_bitPos; - - // True if the file endianess does not match the machine endian - bool m_swapBytes; - - G3DEndian m_fileEndian; - - uint8* m_buffer; - - /** Size of the elements used */ - int m_bufferLen; - - /** Underlying size of memory allocaded */ - int m_maxBufferLen; - - /** Next byte in file */ - int m_pos; - - /** is this initialized? */ - bool m_init; - - /** Number of bytes already written to the file.*/ - size_t m_alreadyWritten; - - bool m_ok; - - void reserveBytesWhenOutOfMemory(size_t bytes); - - void reallocBuffer(size_t bytes, size_t oldBufferLen); - - /** - Make sure at least bytes can be written, resizing if - necessary. - */ - inline void reserveBytes(int bytes) { - debugAssert(bytes > 0); - size_t oldBufferLen = (size_t)m_bufferLen; - - m_bufferLen = iMax(m_bufferLen, (m_pos + bytes)); - if (m_bufferLen > m_maxBufferLen) { - reallocBuffer(bytes, oldBufferLen); - } - } - - // Not implemented on purpose, don't use - BinaryOutput(const BinaryOutput&); - BinaryOutput& operator=(const BinaryOutput&); - bool operator==(const BinaryOutput&); - -public: - - /** - You must call setEndian() if you use this (memory) constructor. - */ - BinaryOutput(); - - /** - Doesn't actually open the file; commit() does that. - Use "" as the filename if you're going to commit - to memory. - */ - BinaryOutput( - const std::string& filename, - G3DEndian fileEndian); - - ~BinaryOutput(); - - /** Compresses the data in the buffer in place, - preceeding it with a little-endian uint32 indicating - the uncompressed size. - - Call immediately before commit(). - - Cannot be used for huge files (ones where the data - was already written to disk)-- will throw char*. - */ - void compress(); - - /** True if no errors have been encountered.*/ - bool ok() const; - - /** - Returns a pointer to the internal memory buffer. - */ - inline const uint8* getCArray() const { - return m_buffer; - } - - void setEndian(G3DEndian fileEndian); - - G3DEndian endian() const { - return m_fileEndian; - } - - std::string getFilename() const { - return m_filename; - } - - /** - Write the bytes to disk. It is ok to call this - multiple times; it will just overwrite the previous file. - - Parent directories are created as needed if they do - not exist. - - Not called from the destructor; you must call - it yourself. - - @param flush If true (default) the file is ready for reading when the method returns, otherwise - the method returns immediately and writes the file in the background. - */ - void commit(bool flush = true); - - /** - Write the bytes to memory (which must be of - at least size() bytes). - */ - void commit(uint8*); - - /** - A memory BinaryOutput may be reset so that it can be written to again - without allocating new memory. The underlying array will not be deallocated, - but the reset structure will act like a newly intialized one. - */ - void reset(); - - - inline int length() const { - return (int)m_bufferLen + (int)m_alreadyWritten; - } - - inline int size() const { - return length(); - } - - /** - Sets the length of the file to n, padding - with 0's past the current end. Does not - change the position of the next byte to be - written unless n < size(). - - Throws char* when resetting a huge file to be shorter - than its current length. - */ - inline void setLength(int n) { - n = n - (int)m_alreadyWritten; - - if (n < 0) { - throw "Cannot resize huge files to be shorter."; - } - - if (n < m_bufferLen) { - m_pos = n; - } - if (n > m_bufferLen) { - reserveBytes(n - m_bufferLen); - } - } - - /** - Returns the current byte position in the file, - where 0 is the beginning and getLength() - 1 is the end. - */ - inline int64 position() const { - return (int64)m_pos + (int64)m_alreadyWritten; - } - - - /** - Sets the position. Can set past length, in which case - the file is padded with zeros up to one byte before the - next to be written. - - May throw a char* exception when seeking backwards on a huge file. - */ - inline void setPosition(int64 p) { - p = p - (int64)m_alreadyWritten; - - if (p > m_bufferLen) { - setLength((int)(p + (int64)m_alreadyWritten)); - } - - if (p < 0) { - throw "Cannot seek more than 10 MB backwards on huge files."; - } - - m_pos = (int)p; - } - - - void writeBytes( - const void* b, - int count) { - - reserveBytes(count); - debugAssert(m_pos >= 0); - debugAssert(m_bufferLen >= count); - System::memcpy(m_buffer + m_pos, b, count); - m_pos += count; - } - - /** - Writes a signed 8-bit integer to the current position. - */ - inline void writeInt8(int8 i) { - reserveBytes(1); - m_buffer[m_pos] = *(uint8*)&i; - m_pos++; - } - - inline void writeBool8(bool b) { - writeInt8(b ? 1 : 0); - } - - inline void writeUInt8(uint8 i) { - reserveBytes(1); - m_buffer[m_pos] = i; - m_pos++; - } - - void writeUInt16(uint16 u); - - inline void writeInt16(int16 i) { - writeUInt16(*(uint16*)&i); - } - - void writeUInt32(uint32 u); - - inline void writeInt32(int32 i) { - debugAssert(m_beginEndBits == 0); - writeUInt32(*(uint32*)&i); - } - - void writeUInt64(uint64 u); - - inline void writeInt64(int64 i) { - writeUInt64(*(uint64*)&i); - } - - inline void writeFloat32(float32 f) { - debugAssert(m_beginEndBits == 0); - union { - float32 a; - uint32 b; - }; - a = f; - writeUInt32(b); - } - - inline void writeFloat64(float64 f) { - union { - float64 a; - uint64 b; - }; - a = f; - writeUInt64(b); - } - - /** - Write a string with NULL termination. - */ - inline void writeString(const std::string& s) { - writeString(s.c_str()); - } - - void writeString(const char* s); - - /** - Write a string, ensuring that the total length - including NULL is even. - */ - void writeStringEven(const std::string& s) { - writeStringEven(s.c_str()); - } - - void writeStringEven(const char* s); - - - void writeString32(const char* s); - - /** - Write a string with a 32-bit length field in front - of it. - */ - void writeString32(const std::string& s) { - writeString32(s.c_str()); - } - - void writeVector4(const Vector4& v); - - void writeVector3(const Vector3& v); - - void writeVector2(const Vector2& v); - - void writeColor4(const Color4& v); - - void writeColor3(const Color3& v); - - /** - Skips ahead n bytes. - */ - inline void skip(int n) { - if (m_pos + n > m_bufferLen) { - setLength((int)m_pos + (int)m_alreadyWritten + n); - } - m_pos += n; - } - - /** Call before a series of BinaryOutput::writeBits calls. Only writeBits - can be called between beginBits and endBits without corrupting the stream.*/ - void beginBits(); - - /** Write numBits from bitString to the output stream. Bits are numbered from - low to high. - - Can only be - called between beginBits and endBits. Bits written are semantically - little-endian, regardless of the actual endian-ness of the system. That is, - writeBits(0xABCD, 16) writes 0xCD to the first byte and - 0xAB to the second byte. However, if used with BinaryInput::readBits, the ordering - is transparent to the caller. - */ - void writeBits(uint32 bitString, int numBits); - - /** Call after a series of BinaryOutput::writeBits calls. This will - finish out with zeros the last byte into which bits were written.*/ - void endBits(); - - -# define DECLARE_WRITER(ucase, lcase)\ - void write##ucase(const lcase* out, int n);\ - void write##ucase(const std::vector& out, int n);\ - void write##ucase(const Array& out, int n); - - DECLARE_WRITER(Bool8, bool) - DECLARE_WRITER(UInt8, uint8) - DECLARE_WRITER(Int8, int8) - DECLARE_WRITER(UInt16, uint16) - DECLARE_WRITER(Int16, int16) - DECLARE_WRITER(UInt32, uint32) - DECLARE_WRITER(Int32, int32) - DECLARE_WRITER(UInt64, uint64) - DECLARE_WRITER(Int64, int64) - DECLARE_WRITER(Float32, float32) - DECLARE_WRITER(Float64, float64) -# undef DECLARE_WRITER - -}; - -} - -#ifdef _MSC_VER -# pragma warning (pop) -#endif - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/BoundsTrait.h b/externals/g3dlite/G3D.lib/include/G3D/BoundsTrait.h deleted file mode 100644 index 31525dab73b..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/BoundsTrait.h +++ /dev/null @@ -1,20 +0,0 @@ -/** - @file BoundsTrait.h - - @maintainer Morgan McGuire, morgan@cs.williams.edu - @created 2008-10-01 - @edited 2008-10-01 - Copyright 2000-2008, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_BOUNDSTRAIT_H -#define G3D_BOUNDSTRAIT_H - -#include "G3D/platform.h" - -template -struct BoundsTrait{}; - -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/Box.h b/externals/g3dlite/G3D.lib/include/G3D/Box.h deleted file mode 100644 index 83e06a2f069..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Box.h +++ /dev/null @@ -1,193 +0,0 @@ -/** - @file Box.h - - Box class - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @cite Portions based on Dave Eberly's Magic Software Library at
http://www.magic-software.com - @created 2001-06-02 - @edited 2007-06-05 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_BOX_H -#define G3D_BOX_H - -#include "G3D/platform.h" -#include "G3D/Vector3.h" -#include "G3D/Array.h" -#include "G3D/Plane.h" - -namespace G3D { - -class CoordinateFrame; - -/** - An arbitrary 3D box, useful as a bounding box. - - - To construct a box from a coordinate frame, center and extent, use the idiom: - - Box box = cframe.toObjectSpace(Box(center - extent/2, center + extent/2)); - */ -class Box { -private: - - static int32 dummy; - - friend class CoordinateFrame; - - /** -
-       3    2       7    6
-    
-       0    1       4    5
-
-       front    back (seen through front)
-      
- */ - Vector3 _corner[8]; - - /** - Unit axes. - */ - Vector3 _axis[3]; - - Vector3 _center; - - /** - Extent along each axis. - */ - Vector3 _extent; - - float _area; - float _volume; - - void init( - const Vector3& min, - const Vector3& max); - -public: - - /** - Does not initialize the fields. - */ - Box(); - - /** - Constructs a box from two opposite corners. - */ - Box( - const Vector3& min, - const Vector3& max); - - static Box inf(); - - Box(class BinaryInput& b); - - Box(const class AABox& b); - - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); - - /** - Returns the object to world transformation for - this box. localFrame().worldToObject(...) takes - objects into the space where the box axes are - (1,0,0), (0,1,0), (0,0,1). Note that there - is no scaling in this transformation. - */ - CoordinateFrame localFrame() const; - - void getLocalFrame(CoordinateFrame& frame) const; - - /** - Returns the centroid of the box. - */ - inline Vector3 center() const { - return _center; - } - - - inline Vector3 corner(int i) const { - debugAssert(i < 8); - return _corner[i]; - } - - /** - Unit length. - */ - inline Vector3 axis(int a) const { - debugAssert(a < 3); - return _axis[a]; - } - - /** - Distance from corner(0) to the next corner - along the box's local axis a. - */ - inline float extent(int a) const { - debugAssert(a < 3); - return (float)_extent[a]; - } - - inline Vector3 extent() const { - return _extent; - } - - /** - Returns the four corners of a face (0 <= f < 6). - The corners are returned to form a counter clockwise quad facing outwards. - */ - void getFaceCorners( - int f, - Vector3& v0, - Vector3& v1, - Vector3& v2, - Vector3& v3) const; - - - /** - See AABox::culledBy - */ - bool culledBy( - const Array& plane, - int32& cullingPlaneIndex, - const uint32 testMask, - uint32& childMask) const; - - /** - Conservative culling test that does not produce a mask for children. - */ - bool culledBy( - const Array& plane, - int32& cullingPlaneIndex = dummy, - const uint32 testMask = -1) const; - - bool contains( - const Vector3& point) const; - - float area() const; - - float volume() const; - - void getRandomSurfacePoint(Vector3& P, Vector3& N = Vector3::dummy) const; - - /** - Uniformly distributed on the interior (includes surface) - */ - Vector3 randomInteriorPoint() const; - - void getBounds(class AABox&) const; - - bool isFinite() const { - return G3D::isFinite(_volume); - } -}; - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Capsule.h b/externals/g3dlite/G3D.lib/include/G3D/Capsule.h deleted file mode 100644 index 237dcdab69d..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Capsule.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - @file Capsule.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-02-07 - @edited 2005-08-20 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_CAPSULE_H -#define G3D_CAPSULE_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Vector3.h" - -namespace G3D { - -class Line; -class AABox; -/** - A shape formed by extruding a sphere along a line segment. - */ -class Capsule { -private: - Vector3 p1; - Vector3 p2; - - float _radius; -public: - - - /** Uninitialized */ - Capsule(); - Capsule(class BinaryInput& b); - Capsule(const Vector3& _p1, const Vector3& _p2, float _r); - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); - - /** The line down the center of the capsule */ - Line axis() const; - - inline float radius() const { - return _radius; - } - - /** Argument may be 0 or 1 */ - inline Vector3 point(int i) const { - debugAssert(i == 0 || i == 1); - return (i == 0) ? p1 : p2; - } - - /** Distance between the sphere centers. The total extent of the cylinder is - 2r + h. */ - inline float height() const { - return (p1 - p2).magnitude(); - } - - inline Vector3 center() const { - return (p1 + p2) / 2.0; - } - - /** Get a reference frame in which the center of mass is the origin and Y is the axis of the capsule.*/ - void getReferenceFrame(class CoordinateFrame& cframe) const; - - /** - Returns true if the point is inside the capsule or on its surface. - */ - bool contains(const Vector3& p) const; - - float volume() const; - - float area() const; - - /** Get axis aligned bounding box */ - void getBounds(AABox& out) const; - - /** Random world space point with outward facing normal. */ - void getRandomSurfacePoint(Vector3& P, Vector3& N) const; - - /** Point selected uniformly at random over the volume. */ - Vector3 randomInteriorPoint() const; -}; - -} // namespace - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/CollisionDetection.h b/externals/g3dlite/G3D.lib/include/G3D/CollisionDetection.h deleted file mode 100644 index 62f92c18d33..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/CollisionDetection.h +++ /dev/null @@ -1,1178 +0,0 @@ -/** - @file CollisionDetection.h - - - Moving collision detection for simple primitives. - - @author Morgan McGuire, matrix@graphics3d.com - @cite Spherical collision based on Paul Nettle's - ftp://ftp.3dmaileffects.com/pub/FluidStudios/CollisionDetection/Fluid_Studios_Generic_Collision_Detection_for_Games_Using_Ellipsoids.pdf - and comments by Max McGuire. Ray-sphere intersection by Eric Haines. - Box-Box intersection written by Kevin Egan. - Thanks to Max McGuire of Iron Lore for various bug fixes. - - @created 2001-11-19 - @edited 2006-01-10 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_COLLISIONDETECTION_H -#define G3D_COLLISIONDETECTION_H - -#include "G3D/platform.h" -#include "G3D/Vector3.h" -#include "G3D/Plane.h" -#include "G3D/Box.h" -#include "G3D/Triangle.h" -#include "G3D/Array.h" -#include "G3D/Ray.h" -#include "G3D/Line.h" - -namespace G3D { - - -/** - Collision detection primitives and tools for building - higher order collision detection schemes. - - These routines provide moving and static collision detection. - Moving collision detection allows the calculation of collisions that - occur during a period of time -- as opposed to the intersection of - two static bodies. - - Moving collision detection routines detect collisions between - only static primitives and moving spheres or points. Since the - reference frame can be user defined, these functions can be used to - detect the collision between two moving bodies by subtracting - the velocity vector of one object from the velocity vector of the - sphere or point the detection is to occur with. This unified - velocity vector will act as if both objects are moving simultaneously. - - Collisions are detected for single-sided objects only. That is, - no collision is detected when leaving a primitive or passing - through a plane or triangle opposite the normal... except for the - point-sphere calculation or when otherwise noted. - - For a sphere, the collision location returned is the point in world - space where the surface of the sphere and the fixed object meet. - It is not the position of the center of the sphere at - the time of the collision. - - The collision normal returned is the surface normal to the fixed - object at the collision location. - -

- Static Collision Detection: (Neither object is moving) - - - - - - - - - - - - - - -
Vector3LineSegmentRay *LinePlaneTriangleSphereCylinderCapsuleAABoxBox
Vector3Vector3::operator== Vector3::fuzzyEq G3D::distance
LineSegmentLineSegment::closestPoint LineSegment::distance CollisionDetection::closestPointOnLineSegment
Ray *Ray::closestPoint Ray::distance
LineLine::closestPoint Line::distanceCollisionDetection::closestPointsBetweenLineAndLine
Plane
Triangle
SphereSphere::contains
CylinderCylinder::contains
CapsuleCapsule::contains
AABoxAABox::contains
BoxBox::contains(treat as Ray)CollisionDetection::collisionTimeForMovingPointFixedBox(treat as Ray)CollisionDetection::penetrationDepthForFixedBoxFixedPlaneCollisionDetection::penetrationDepthForFixedBoxFixedPlaneCollisionDetection::penetrationDepthForFixedSphereFixedBoxNone (use OPCODE)CollisionDetection::movingSpherePassesThroughFixedBoxCollisionDetection::penetrationDepthForFixedBoxFixedBoxCollisionDetection::penetrationDepthForFixedBoxFixedBox
- -

- Moving Collision Detection: - - * Note: Moving collision detection against certain primitives is equivalent to static collision - detection against a bigger primitive. Ray, Line Segment == ``moving Point''; Capsule ==``moving Sphere''; Plane == ``moving Line'' - */ -class CollisionDetection { -private: - - /** - Default parameter if value passed to a function as reference is - not to be calculated. Must be explicitly supported by function. - */ - static Vector3 ignore; - - /** - Default parameter if value passed to a function as reference is - not to be calculated. Must be explicitly supported by function. - */ - static bool ignoreBool; - - /** - Default parameter if value passed to a function as reference is - not to be calculated. Must be explicitly supported by function. - */ - static Array ignoreArray; - - - // Static class! - CollisionDetection() {} - virtual ~CollisionDetection() {} - -public: - - /** - Converts an index [0, 15] to the corresponding separating axis. - Does not return normalized vector in the edge-edge case - (indices 6 through 15). - - @param separatingAxisIndex Separating axis. - @param box1 Box 1. - @param box2 Box 2. - - @return Axis that separates the two boxes. - */ - static Vector3 separatingAxisForSolidBoxSolidBox( - const int separatingAxisIndex, - const Box & box1, - const Box & box2); - - /** - Tests whether two boxes have axes that are parallel to - each other. If they are, axis1 and axis2 are set to be - the parallel axes for both box1 and box2 respectively. - - @param ca Dot products of each of the boxes axes - @param epsilon Fudge factor (small unit by which the dot - products may vary and still be considered - zero). - @param axis1 Parallel Axis 1. [Post Condition] - @param axis2 Parallel Axis 2. [Post Condition] - - @return true - If boxes have a parallel axis - @return false - otherwise. - */ - static bool parallelAxisForSolidBoxSolidBox( - const double* ca, - const double epsilon, - int & axis1, - int & axis2); - - /** - Calculates the projected distance between the two boxes along - the specified separating axis, negative distances correspond - to an overlap along that separating axis. The distance is not - divided by denominator dot(L, L), see - penetrationDepthForFixedSphereFixedBox() for more details - - @param separatingAxisIndex - @param a Box 1's bounding sphere vector - @param b Box 2's bounding sphere vector - @param D Vector between Box 1 and Box 2's center points - @param c Pointer to array of dot products of the axes of Box 1 - and Box 2. - @param ca Pointer to array of unsigned dot products of the axes - of Box 1 and Box 2. - @param ad Pointer to array of dot products of Box 1 axes and D. - @param bd Pointer to array of dot products of Box 2 axes and D. - - @return Projected distance between the two boxes along the - specified separating axis. - */ - static float projectedDistanceForSolidBoxSolidBox( - const int separatingAxisIndex, - const Vector3 & a, - const Vector3 & b, - const Vector3 & D, - const double* c, - const double* ca, - const double* ad, - const double* bd); - - - /** - Creates a set of standard information about two boxes in order to - solve for their collision. This information includes a vector to - the radius of the bounding sphere for each box, the vector between - each boxes' center and a series of dot products between differing - important vectors. These dot products include those between the axes - of both boxes (signed and unsigned values), and the dot products - between all the axes of box1 and the boxes' center vector and box2 - and the boxes' center vector. - - @pre The following space requirements must be met: - - c[] 9 elements - - ca[] 9 elements - - ad[] 3 elements - - bd[] 3 elements - - @cite dobted from David Eberly's papers, variables used in this function - correspond to variables used in pages 6 and 7 in the pdf - http://www.magic-software.com/Intersection.html - http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf - - @note Links are out-dated. (Kept to preserve origin and authorship) - - @param box1 Box 1 - @param box2 Box 2 - @param a Box 1's bounding sphere vector - @param b Box 2's bounding sphere vector - @param D Vector between Box 1 and Box 2's center points - @param c Pointer to array of dot products of the axes of Box 1 - and Box 2. - @param ca Pointer to array of unsigned dot products of the axes - of Box 1 and Box 2. - @param ad Pointer to array of dot products of Box 1 axes and D. - @param bd Pointer to array of dot products of Box 2 axes and D. - */ - static void fillSolidBoxSolidBoxInfo( - const Box & box1, - const Box & box2, - Vector3 & a, - Vector3 & b, - Vector3 & D, - double* c, - double* ca, - double* ad, - double* bd); - - /** - Performs a simple bounding sphere check between two boxes to determine - whether these boxes could possibly intersect. This is a very - cheap operation (three dot products, two sqrts and a few others). If - it returns true, an intersection is possible, but not necessarily - guaranteed. - - @param a Vector from box A's center to an outer vertex - @param b Vector from box B's center to an outer vertex - @param D Distance between the centers of the two boxes - - @return true - if possible intersection - @return false - otherwise (This does not guarantee an intersection) - */ - static bool conservativeBoxBoxTest( - const Vector3 & a, - const Vector3 & b, - const Vector3 & D); - - /** - Determines whether two fixed solid boxes intersect. - - @note To speed up collision detection, the lastSeparatingAxis from - the previous time step can be passed in and that plane can be - checked first. If the separating axis was not saved, or if the - two boxes intersected then lastSeparatingAxis should equal -1. - - @cite Adobted from David Eberly's papers, variables used in this function - correspond to variables used in pages 6 and 7 in the pdf - http://www.magic-software.com/Intersection.html - http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf - - @param box1 Box 1. - @param box2 Box 2. - @param lastSeparatingAxis Last separating axis. - (optimization - see note) - - @return true - Intersection. - @return false - otherwise. - */ - static bool fixedSolidBoxIntersectsFixedSolidBox( - const Box& box1, - const Box& box2, - const int lastSeparatingAxis = -1); - - /** - Calculates the closest points on two lines with each other. If the - lines are parallel then using the starting point, else calculate the - closest point on each line to the other. - - @note This is very similiar to calculating the intersection of two lines. - Logically then, the two points calculated would be identical if calculated - with inifinite precision, but with the finite precision of floating point - calculations, these values could (will) differ as the line slope approaches - zero or inifinity. - - @cite variables and algorithm based on derivation at the following website: - http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm - - @param line1 Line 1. - @param line2 Line 2. - @param closest1 Closest point on line 1. - @param closest2 Closest point on line 2. - */ - static void closestPointsBetweenLineAndLine( - const Line & line1, - const Line & line2, - Vector3 & closest1, - Vector3 & closest2); - - /** - Calculates the depth of penetration between two fixed boxes. - Contact normal faces away from box1 and into box2. If there is - contact, only one contact point is returned. The minimally - violated separating plane is computed - - if the separating axis corresponds to a face - the contact point is half way between the deepest vertex - and the face - - if the separating axis corresponds to two edges - the contact point is the midpoint of the smallest line - segment between the two edge lines - - @note This is very similiar to calculating the intersection of two lines. - Logically then, the two points calculated would be identical if calculated - with inifinite precision, but with the finite precision of floating point - calculations, these values could (will) differ as the line slope approaches - zero or inifinity. - - @cite adobted from David Eberly's papers, variables used in this function - correspond to variables used in pages 6 and 7 in the pdf - http://www.magic-software.com/Intersection.html - http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf - - @param box1 Box 1 - @param box2 Box 2 - @param contactPoints Contact point between boxes. [Post Condition] - @param contactNormals Surface normal at contact point. [Post Condition] - @param lastSeparatingAxis Last separating axis. (Used for optimization) - - @return Depth of penetration between the two boxes. If there is no - intersection between the boxes, then a negative value is returned. - */ - static float penetrationDepthForFixedBoxFixedBox( - const Box& box1, - const Box& box2, - Array& contactPoints, - Array& contactNormals, - const int lastSeparatingAxis = -1); - - /** - Calculates the depth of penetration between two fixed spheres as well - as the deepest point of Sphere A that penetrates Sphere B. The normal - returned points away from the object A, although it may - represent a perpendicular to either the faces of object B or object A - depending on their relative orientations. - - @param sphereA Fixed Sphere A. - @param sphereB Fixed Sphere B. - @param contactPoints Sphere A's deepest point that penetrates Sphere B. - [Post Condition] - @param contactNormals Normal at penetration point. [Post Condition] - - @return Depth of penetration. If there is no intersection between the - objects then the depth will be a negative value. - */ - static float penetrationDepthForFixedSphereFixedSphere( - const class Sphere& sphereA, - const Sphere& sphereB, - Array& contactPoints, - Array& contactNormals = ignoreArray); - - /** - Calculates the depth of penetration between a fixed sphere and a fixed - box as well as the deepest point of the sphere that penetrates the box - and the normal at that intersection. - - @note There are three possible intersections between a sphere and box. - - Sphere completely contained in the box - - Sphere intersects one edge - - Sphere intersects one vertex - - The contact point and contact normal vary for each of these situations. - - Sphere contained in Box: - - Normal is based on side of least penetration (as is the depth calculation). - - Point is based on center of sphere - - Sphere intersects one edge - - Normal is based on vector from the box center to the point of depth. - - Point is closest point to the sphere on the line - - Sphere intersects one vertex - - Normal is based on vector from the box center to the vertex of penetration. - - Point is vertex of penetration. - - @cite Adapted from Jim Arvo's method in Graphics Gems - See also http://www.win.tue.nl/~gino/solid/gdc2001depth.pdf - - @param sphere Fixed Sphere. - @param box Fixed Box. - @param contactPoints Sphere point that penetrates the box. [Post Condition] - @param contactNormals Normal at the penetration point. [Post Condition] - - @return Depth of penetration. If there is no intersection between the - objects then the depth will be a negative value. - */ - static float penetrationDepthForFixedSphereFixedBox( - const Sphere& sphere, - const Box& box, - Array& contactPoints, - Array& contactNormals = ignoreArray); - - /** - Calculates the depth of penetration between a Fixed Sphere and a Fixed - Plane as well as the deepest point of the sphere that penetrates the plane - and the plane normal at that intersection. - - @param sphere Fixed Sphere. - @param plane Fixed Plane. - @param contactPoints Sphere point that penetrates the plane. - [Post Condition] - @param contactNormals Normal at penetration point. [Post Condition] - - @return Depth of penetration. If there is no intersection between the - objects then the depth will be a negative value. - */ - static float penetrationDepthForFixedSphereFixedPlane( - const Sphere& sphereA, - const class Plane& planeB, - Array& contactPoints, - Array& contactNormals = ignoreArray); - - /** - Calculates the depth of penetration between a fixed box and a fixed - plane as well as the vertexes of the box that penetrate the plane - and the plane normals at those intersections. - - @param box Fixed Box. - @param plane Fixed Plane. - @param contactPoints Box points that penetrate the plane. - [Post Condition] - @param contactNormals Normals at penetration points [Post Condition] - - @return Depth of penetration. If there is no intersection between the - objects then the depth will be a negative value. - */ - static float penetrationDepthForFixedBoxFixedPlane( - const Box& box, - const Plane& plane, - Array& contactPoints, - Array& contactNormals = ignoreArray); - - /** - Calculates time between the intersection of a moving point and a fixed - plane. - - @note This is only a one sided collision test. The side defined by - the plane's surface normal is the only one tested. For a two sided - collision, call the function once for each side's surface normal. - - @param point Moving point. - @param velocity Point's velocity. - @param plane Fixed plane. - @param location Location of collision. [Post Condition] - (Infinite vector on no collision) - @param outNormal Plane's surface normal. [Post Condition] - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - static float collisionTimeForMovingPointFixedPlane( - const Vector3& point, - const Vector3& velocity, - const class Plane& plane, - Vector3& outLocation, - Vector3& outNormal = ignore); - - /** - Calculates time between the intersection of a moving point and a fixed - triangle. - - @note This is only a one sided collision test. The side defined by - the triangle's surface normal is the only one tested. For a two sided - collision, call the function once for each side's surface normal. - - @param orig Moving point. - @param dir Point's velocity. - @param v0 Triangle vertex 1. - @param v1 Triangle vertex 2. - @param v2 Triangle vertex 3 - @param location Location of collision. [Post Condition] - (Infinite vector on no collision) - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - inline static float collisionTimeForMovingPointFixedTriangle( - const Vector3& orig, - const Vector3& dir, - const Vector3& v0, - const Vector3& v1, - const Vector3& v2) { - return Ray::fromOriginAndDirection(orig, dir).intersectionTime(v0, v1, v2); - } - - /** - Calculates time between the intersection of a moving point and a fixed - triangle. - - @note This is only a one sided collision test. The side defined by - the triangle's surface normal is the only one tested. For a two sided - collision, call the function once for each side's surface normal. - - @param orig Moving point. - @param dir Point's velocity. - @param v0 Triangle vertex 1. - @param v1 Triangle vertex 2. - @param v2 Triangle vertex 3 - @param location Location of collision. [Post Condition] - (Infinite vector on no collision) - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - inline static float collisionTimeForMovingPointFixedTriangle( - const Vector3& orig, - const Vector3& dir, - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - Vector3& location) { - float t = collisionTimeForMovingPointFixedTriangle(orig, dir, v0, v1, v2); - if (t < inf()) { - location = orig + dir * t; - } - return t; - } - - /** - Calculates time between the intersection of a moving point and a fixed - triangle. - - @note This is only a one sided collision test. The side defined by - the triangle's surface normal is the only one tested. For a two sided - collision, call the function once for each side's surface normal. - - @param orig Moving point. - @param dir Point's velocity. - @param tri Fixed triangle. - @param location Location of collision. [Post Condition] - (Infinite vector on no collision) - @param normal Triangle's surface normal. [Post Condition] - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - inline static float collisionTimeForMovingPointFixedTriangle( - const Vector3& orig, - const Vector3& dir, - const Triangle& tri, - Vector3& location = ignore, - Vector3& normal = ignore) { - - float t = collisionTimeForMovingPointFixedTriangle( - orig, dir, tri.vertex(0), tri.vertex(1), tri.vertex(2)); - - if ((t < inf()) && (&location != &ignore)) { - location = orig + dir * t; - normal = tri.normal(); - } - return t; - } - - /** - Calculates time between the intersection of a moving point and a fixed - triangle. - - @note This is only a one sided collision test. The side defined by - the triangle's surface normal is the only one tested. For a two sided - collision, call the function once for each side's surface normal. - - @param orig Moving point. - @param dir Point's velocity. - @param v0 Triangle vertex 1. - @param v1 Triangle vertex 2. - @param v2 Triangle vertex 3 - @param location Location of collision. [Post Condition] - (Infinite vector on no collision) - @param normal Triangle's surface normal. [Post Condition] - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - inline static float collisionTimeForMovingPointFixedTriangle( - const Vector3& orig, - const Vector3& dir, - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - Vector3& location, - Vector3& normal) { - float t = collisionTimeForMovingPointFixedTriangle(orig, dir, v0, v1, v2); - if (t < inf()) { - location = orig + dir * t; - normal = (v2 - v0).cross(v1 - v0).direction(); - } - return t; - } - - /** - Unlike other methods, does not support an output normal. - If the ray origin is inside the box, returns inf() but inside - is set to true. - Beta API - - @cite Andrew Woo, from "Graphics Gems", Academic Press, 1990 - @cite Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500) - @cite Epsilon value added by Klaus Hartmann - @cite http://www.codercorner.com/RayAABB.cpp - */ - static float collisionTimeForMovingPointFixedAABox( - const Vector3& point, - const Vector3& velocity, - const class AABox& box, - Vector3& outLocation, - bool& inside = ignoreBool, - Vector3& outNormal = ignore); - - /** - Calculates time between the intersection of a moving point and a fixed - Axis-Aligned Box (AABox). - - @note Avoids the sqrt from collisionTimeForMovingPointFixedAABox. - - @param point Moving point. - @param velocity Sphere's velocity. - @param box Fixed AAbox. - @param location Location of collision. [Post Condition] - @param Inside Does the ray originate inside the box? [Post Condition] - @param normal Box's surface normal to collision [Post Condition] - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - static bool collisionLocationForMovingPointFixedAABox( - const Vector3& point, - const Vector3& velocity, - const class AABox& box, - Vector3& outLocation, - bool& inside = ignoreBool, - Vector3& normal = ignore); - - /** - Calculates time between the intersection of a moving point and a fixed - sphere. - - @note When ray is starts inside the rectangle, the exiting intersection - is detected. - - @param point Moving point. - @param velocity Point's velocity. - @param Sphere Fixed Sphere. - @param location Location of collision. [Post Condition] - @param outNormal Sphere's surface normal to collision [Post Condition] - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - static float collisionTimeForMovingPointFixedSphere( - const Vector3& point, - const Vector3& velocity, - const class Sphere& sphere, - Vector3& outLocation, - Vector3& outNormal = ignore); - - /** - Calculates time between the intersection of a moving point and a fixed - box. - - @note If the point is already inside the box, no collision: inf is returned. - - @param point Moving point. - @param velocity Sphere's velocity. - @param box Fixed box. - @param location Position of collision. [Post Condition] - @param outNormal Box's surface normal to collision [Post Condition] - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - static float collisionTimeForMovingPointFixedBox( - const Vector3& point, - const Vector3& velocity, - const class Box& box, - Vector3& outLocation, - Vector3& outNormal = ignore); - - /** - Calculates time between the intersection of a moving point and a fixed - rectangle defined by the points v0, v1, v2, & v3. - - @note This is only a one sided collision test. The side defined by - the rectangle's surface normal is the only one tested. For a two sided - collision, call the function once for each side's surface normal. - - @param point Moving point. - @param velocity Sphere's velocity. - @param v0 Rectangle vertex 1. - @param v1 Rectangle vertex 2. - @param v2 Rectangle vertex 3 - @param v3 Rectangle vertex 4. - @param location Location of collision [Post Condition] - @param outNormal Rectangle's surface normal. [Post Condition] - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - static float collisionTimeForMovingPointFixedRectangle( - const Vector3& point, - const Vector3& velocity, - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& v3, - Vector3& outLocation, - Vector3& outNormal = ignore); - - /** - Calculates time between the intersection of a moving point and a fixed - capsule. - - @param point Moving point. - @param velocity Point's velocity. - @param capsule Fixed capsule. - @param location Location of collision. [Post Condition] - @param outNormal Capsule's surface normal to collision [Post Condition] - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - static float collisionTimeForMovingPointFixedCapsule( - const Vector3& point, - const Vector3& velocity, - const class Capsule& capsule, - Vector3& outLocation, - Vector3& outNormal = ignore); - - /** - Calculates time between the intersection of a moving sphere and a fixed - triangle. - - @param sphere Moving sphere. - @param velocity Sphere's velocity. - @param plane Fixed Plane. - @param location Location of collision -- not center position of sphere - at the collision time. [Post Condition] - @param outNormal Box's surface normal to collision [Post Condition] - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - static float collisionTimeForMovingSphereFixedPlane( - const class Sphere& sphere, - const Vector3& velocity, - const class Plane& plane, - Vector3& outLocation, - Vector3& outNormal = ignore); - - /** - Calculates time between the intersection of a moving sphere and a fixed - triangle. - - @param sphere Moving sphere. - @param velocity Sphere's velocity. - @param triangle Fixed Triangle. (collisions can happen on the back side of the triangle) - @param outLocation Location of collision, if collision occurs -- not center position of sphere - at the collision time. If there is interpenetration at the start, this point may be inside - the sphere. - @param b Barycentric coordinates. These are not valid unless collision occurs. - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - static float collisionTimeForMovingSphereFixedTriangle( - const class Sphere& sphere, - const Vector3& velocity, - const Triangle& triangle, - Vector3& outLocation, - float b[3] = (float*)&ignore); - - /** - Calculates time between the intersection of a moving sphere and a fixed - rectangle defined by the points v0, v1, v2, & v3. - - @param sphere Moving sphere. - @param velocity Sphere's velocity. - @param v0 Rectangle vertex 1. - @param v1 Rectangle vertex 2. - @param v2 Rectangle vertex 3 - @param v3 Rectangle vertex 4. - @param location Location of collision -- not center position of sphere - at the collision time. [Post Condition] - @param outNormal Box's surface normal to collision [Post Condition] - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - static float collisionTimeForMovingSphereFixedRectangle( - const class Sphere& sphere, - const Vector3& velocity, - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& v3, - Vector3& outLocation, - Vector3& outNormal = ignore); - - /** - Calculates time between the intersection of a moving sphere and a fixed - box. - - @note This function will not detect an intersection between a moving object - that is already interpenetrating the fixed object. - - @param sphere Moving sphere. - @param velocity Sphere's velocity. - @param box Fixed box. - @param location Location of collision -- not center position of sphere - at the collision time. [Post Condition] - @param outNormal Box's surface normal to collision [Post Condition] - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - static float collisionTimeForMovingSphereFixedBox( - const class Sphere& sphere, - const Vector3& velocity, - const class Box& box, - Vector3& outLocation, - Vector3& outNormal = ignore); - - /** - Calculates time between the intersection of a moving sphere and a fixed - sphere. - - @note This won't detect a collision if the sphere is already interpenetrating - the fixed sphere. - - @param movingSphere Moving sphere. - @param velocity Sphere's velocity. - @param fixedSphere Fixed Sphere. - @param location Location of collision -- not center position of sphere - at the collision time. [Post Condition] - @param outNormal Sphere's surface normal to collision [Post Condition] - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - static float collisionTimeForMovingSphereFixedSphere( - const class Sphere& sphere, - const Vector3& velocity, - const class Sphere& fixedSphere, - Vector3& outLocation, - Vector3& outNormal = ignore); - - /** - Calculates time between the intersection of a moving sphere and a fixed - capsule. - - @note This won't detect a collision if the sphere is already - interpenetrating the capsule. - - @param sphere Moving sphere. - @param velocity Sphere's velocity. - @param capsule Fixed capsule. - @param location Location of collision -- not center position of sphere - at the collision time. [Post Condition] - @param outNormal Capsule's surface normal to the collision [Post Condition] - - @return Time til collision. If there is no collision then the return - value will be inf(). - */ - static float collisionTimeForMovingSphereFixedCapsule( - const class Sphere& sphere, - const Vector3& velocity, - const class Capsule& capsule, - Vector3& outLocation, - Vector3& outNormal = ignore); - - /** - Finds the direction of bounce that a sphere would have when it - intersects an object with the given time of collision, the - collision location and the collision normal. - - @note This function works like a pong style ball bounce. - - @param sphere Moving sphere. - @param velocity Sphere's velocity. - @param collisionTime Time of collision. - @param collisionLocation Collision location. - @param collisionNormal Surface collision normal. - - @return Direction of bounce. - */ - static Vector3 bounceDirection( - const class Sphere& sphere, - const Vector3& velocity, - const float collisionTime, - const Vector3& collisionLocation, - const Vector3& collisionNormal); - - /** - Finds the direction of slide given a moving sphere, its velocity, the - time of collision and the collision location. This function works as - if the sphere intersects the surface and continues to hug it. - - @note The result will work well for calculating the movement of a player - who collides with an object and continues moving along the object instead - of just bouncing off it. - - @param sphere Moving sphere. - @param velocity Sphere's velocity. - @param collisionTime Time of collision - @param collisionLocation Collision location. - - @return Direction of slide. - */ - static Vector3 slideDirection( - const class Sphere& sphere, - const Vector3& velocity, - const float collisionTime, - const Vector3& collisionLocation); - - /** - Finds the closest point on a line segment to a given point. - - @param v0 line vertex 1. - @param v1 line vertex 2. - @param point External point. - - @return Closests point to point on the line segment. - */ - static Vector3 closestPointOnLineSegment( - const Vector3& v0, - const Vector3& v1, - const Vector3& point); - - /** - Finds the closest point on a line segment to a given point. - - @note This is an optimization to closestPointOnLineSegment. Edge length - and direction can be used in this function if already pre-calculated. This - prevents doing the same work twice. - - @param v0 line vertex 0. - @param v1 line vertex 1. - @param edgeDirection The direction of the segment (unit length). - @param edgeLength The length of the segment. - @param point External point. - - @return Closests point to point on the line segment. - */ - static Vector3 closestPointOnLineSegment( - const Vector3& v0, - const Vector3& v1, - const Vector3& edgeDirection, - float edgeLength, - const Vector3& point); - - /** - Finds the closest point on the perimeter of the triangle to an external point; - given a triangle defined by three points v0, v1, & v2, and the external point. - - @param v0 Triangle vertex 0. - @param v1 Triangle vertex 1. - @param v2 Triangle vertex 2. - @param point External point. - - @return Closests point to point on the perimeter of the - triangle. - */ - static Vector3 closestPointOnTrianglePerimeter( - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& point); - - /** - Finds the closest point on the perimeter of the triangle to an external point; - given a triangle defined by the array of points v, its edge directions and - their lengths, as well as the external point. - - @note This is an optimization to closestPointToTrianglePerimeter. Edge length - and direction can be used in this function if already pre-calculated. This - prevents doing the same work twice. - - @param v0 Triangle vertex 0. - @param v1 Triangle vertex 1. - @param v2 Triangle vertex 2. - @param point External point. - @param edgeIndex The point lies on the edge between v[edgeIndex] and v[(edgeIndex + 1) % 3] - - @return Closests point to point on the perimeter of the - triangle. - */ - static Vector3 closestPointOnTrianglePerimeter( - const Vector3 v[3], - const Vector3 edgeDirection[3], - const float edgeLength[3], - const Vector3& point, - int& edgeIndex); - - /** - Tests whether a point is contained within the triangle defined by - v0, v1, and v2 and its plane's normal. - - @param v0 Triangle vertex 0. - @param v1 Triangle vertex 1. - @param v2 Triangle vertex 2. - @param normal Normal to triangle's plane. - @param point The point in question. - @param primaryAxis Primary axis of triangle. This will be detected - if not given. This parameter is provided as an optimization. - @param b Barycentric coordinates; b[i] is the weight on v[i] - - @return true - if point is inside the triangle. - @return false - otherwise - */ - static bool isPointInsideTriangle( - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& normal, - const Vector3& point, - float b[3], - Vector3::Axis primaryAxis = Vector3::DETECT_AXIS); - - inline static bool isPointInsideTriangle( - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& normal, - const Vector3& point, - Vector3::Axis primaryAxis = Vector3::DETECT_AXIS) { - - float b[3]; - return isPointInsideTriangle(v0, v1, v2, normal, point, b, primaryAxis); - } - - /** - Tests for the intersection of a moving sphere and a fixed box in a - given time limit. - - @note Returns true if any part of the sphere is inside the box - during the time period (inf means "ever"). Useful for - performing bounding-box collision detection. - - @param sphere Moving sphere. - @param velocity Velocity of moving sphere. - @param box Fixed box. - @param timeLimit Time limit for intersection test. - - @return true - if the two objects will touch. - @return false - if there is no intersection. - */ - static bool movingSpherePassesThroughFixedBox( - const Sphere& sphere, - const Vector3& velocity, - const Box& box, - double timeLimit = inf()); - - /** - Tests for the intersection of a moving sphere and a fixed sphere in a - given time limit. - - @note This function will not detect an intersection between a moving object - that is already interpenetrating the fixed object. - - @param sphere Moving sphere. - @param velocity Velocity of moving sphere. - @param fixedSphere Fixed sphere. - @param timeLimit Time limit for intersection test. - - @return true - if the two spheres will touch. - @return false - if there is no intersection. - */ - static bool movingSpherePassesThroughFixedSphere( - const Sphere& sphere, - const Vector3& velocity, - const Sphere& fixedSphere, - double timeLimit = inf()); - - /** - Tests for the intersection of two fixed spheres. - - @param sphere1 Fixed sphere 1. - @param sphere2 Fixed sphere 2. - - @return true - if the two spheres touch. - @return false - if there is no intersection. - */ - static bool fixedSolidSphereIntersectsFixedSolidSphere( - const Sphere& sphere1, - const Sphere& sphere2); - - /** - Tests for the intersection of a fixed sphere and a fixed box. - - @param sphere Fixed sphere. - @param box Fixed box. - - @return true - if the two objects touch. - @return false - if there is no intersection. - */ - static bool fixedSolidSphereIntersectsFixedSolidBox( - const Sphere& sphere, - const Box& box); - - static bool fixedSolidSphereIntersectsFixedTriangle( - const Sphere& sphere, - const Triangle& triangle); - - /** - Tests whether a point is inside a rectangle defined by the vertexes - v0, v1, v2, & v3, and the rectangle's plane normal. - - @param v0 Rectangle vertex 1. - @param v1 Rectangle vertex 2. - @param v2 Rectangle vertex 3. - @param v3 Rectangle vertex 4. - @param normal Normal to rectangle's plane. - @param point The point in question. - - @return true - if point is inside the rectangle. - @return false - otherwise - */ - static bool isPointInsideRectangle( - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& v3, - const Vector3& normal, - const Vector3& point); - - /** - Finds the closest point on the perimeter of the rectangle to an - external point; given a rectangle defined by four points v0, v1, - v2, & v3, and the external point. - - @param v0 Rectangle vertex 1. - @param v1 Rectangle vertex 2. - @param v2 Rectangle vertex 3. - @param v3 Rectangle vertex 4. - @param point External point. - - @return Closests point to point on the perimeter of the - rectangle. - */ - static Vector3 closestPointToRectanglePerimeter( - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& v3, - const Vector3& point); - - /** - Finds the closest point in the rectangle to an external point; Given - a rectangle defined by four points v0, v1, v2, & v3, and the external - point. - - @param v0 Rectangle vertex 1. - @param v1 Rectangle vertex 2. - @param v2 Rectangle vertex 3 - @param v3 Rectangle vertex 4. - @param point External point. - - @return Closet point in the rectangle to the external point. - */ - static Vector3 closestPointToRectangle( - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& v3, - const Vector3& point); -}; - -} // namespace - -#endif // G3D_COLLISIONDETECTION_H diff --git a/externals/g3dlite/G3D.lib/include/G3D/Color1.h b/externals/g3dlite/G3D.lib/include/G3D/Color1.h deleted file mode 100644 index 1958da2b6cd..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Color1.h +++ /dev/null @@ -1,129 +0,0 @@ -/** - @file Color1.h - - Monochrome Color class - - @maintainer Morgan McGuire, morgan@cs.williams.edu - @created 2007-01-31 - @edited 2008-10-02 - - Copyright 2000-2008, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_COLOR1_H -#define G3D_COLOR1_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/HashTrait.h" -#include - -namespace G3D { - -/** - Monochrome color. This is just a float, but it has nice semantics - because a scaling by 255 automatically occurs when switching between - fixed point (Color1uint8) and floating point (Color1) formats. - */ -class Color1 { -private: - // Hidden operators - bool operator<(const Color1&) const; - bool operator>(const Color1&) const; - bool operator<=(const Color1&) const; - bool operator>=(const Color1&) const; - -public: - float value; - - /** - Initializes to 0 - */ - inline Color1() : value(0) {} - - Color1(class BinaryInput& bi); - - inline explicit Color1(float v) : value(v) { - } - - Color1 (const class Color1uint8& other); - - void serialize(class BinaryOutput& bo) const; - void deserialize(class BinaryInput& bi); - - Color1 operator+ (const Color1& other) const { - return Color1(value + other.value); - } - - Color1 operator+ (const float other) const { - return Color1(value + other); - } - - Color1& operator+= (const Color1 other) { - value += other.value; - return *this; - } - - Color1& operator-= (const Color1 other) { - value -= other.value; - return *this; - } - - Color1 operator- (const Color1& other) const { - return Color1(value - other.value); - } - - Color1 operator- (const float other) const { - return Color1(value - other); - } - - Color1 operator- () const { - return Color1(-value); - } - - Color1 operator* (const Color1& other) const { - return Color1(value * other.value); - } - - Color1 operator* (const float other) const { - return Color1(value * other); - } - - Color1 operator/ (const Color1& other) const { - return Color1(value / other.value); - } - - Color1 operator/ (const float other) const { - return Color1(value / other); - } - - inline Color1 max(const Color1& other) const { - return Color1(G3D::max(value, other.value)); - } - - inline Color1 min(const Color1& other) const { - return Color1(G3D::min(value, other.value)); - } - - inline Color1 lerp(const Color1& other, float a) const { - return Color1(value + (other.value - value) * a); - - } - - inline size_t hashCode() const { - return (size_t)(value * 0xFFFFFF); - } -}; - -} - -template <> -struct HashTrait { - static size_t hashCode(const G3D::Color1& key) { - return key.hashCode(); - } -}; - - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Color1uint8.h b/externals/g3dlite/G3D.lib/include/G3D/Color1uint8.h deleted file mode 100644 index ffaa2d43ac4..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Color1uint8.h +++ /dev/null @@ -1,107 +0,0 @@ -/** - @file Color1uint8.h - - @maintainer Morgan McGuire, graphics3d.com - - @created 2007-01-30 - @edited 2007-01-30 - - Copyright 2000-2007, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_COLOR1UINT8_H -#define G3D_COLOR1UINT8_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" - -namespace G3D { - -#if defined(G3D_WIN32) - // Switch to tight alignment - #pragma pack(push, 1) -#endif - - -/** - Represents a Color1 as a packed integer. Convenient - for creating unsigned int vertex arrays. - - WARNING: Integer color formats are different than - integer vertex formats. The color channels are automatically - scaled by 255 (because OpenGL automatically scales integer - colors back by this factor). So Color3(1,1,1) == Color3uint8(255,255,255) - but Vector3(1,1,1) == Vector3int16(1,1,1). - - Note: - Conversion of a float32 to uint8 is accomplished by min(iFloor(f * 256)) and - back to float32 by u / 255.0f. This gives equal size intervals. -Consider a number line from 0 to 1 and a corresponding one from 0 to 255. If we use iRound(x * 255), then the mapping for three critical intervals are: - -

-let s = 0.5/255
-  float             int       size
-[0, s)           -> 0          s
-[s, s * 3)       -> 1         2*s
-(1 - s, 1]       -> 255        s
-
- -If we use max(floor(x * 256), 255), then we get: - -
-let s = 1/256
-  float             int           size
-[0, s)           -> 0               s
-[s, 2 * s)       -> 1               s
-(1 - s, 1]       -> 255             s
-
-and the intervals are all the same size, thus giving equal precision to all values. - */ -class Color1uint8 { -private: - // Hidden operators - bool operator<(const Color1uint8&) const; - bool operator>(const Color1uint8&) const; - bool operator<=(const Color1uint8&) const; - bool operator>=(const Color1uint8&) const; - -public: - - uint8 value; - - Color1uint8() : value(0) {} - - explicit Color1uint8(const uint8 _v) : value(_v) {} - - Color1uint8(const class Color1& c); - - Color1uint8(class BinaryInput& bi); - - void serialize(class BinaryOutput& bo) const; - - void deserialize(class BinaryInput& bi); - - inline bool operator==(const Color1uint8& other) const { - return value == other.value; - } - - inline bool operator!=(const Color1uint8& other) const { - return value != other.value; - } - -} - -#if defined(G3D_LINUX) || defined(G3D_OSX) - __attribute((aligned(1))) -#endif - -; - -#ifdef G3D_WIN32 - #pragma pack(pop) -#endif - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Color3.h b/externals/g3dlite/G3D.lib/include/G3D/Color3.h deleted file mode 100644 index b8d0f94829a..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Color3.h +++ /dev/null @@ -1,390 +0,0 @@ -/** - @file Color3.h - - Color class - - @maintainer Morgan McGuire, matrix@graphics3d.com - @cite Portions based on Dave Eberly's Magic Software Library - at http://www.magic-software.com - - @created 2001-06-02 - @edited 2008-07-17 - - Copyright 2000-2008, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_COLOR3_H -#define G3D_COLOR3_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/HashTrait.h" -#include "G3D/Color1.h" -#include - -namespace G3D { - -/** - Do not subclass-- this implementation makes assumptions about the - memory layout. - */ -class Color3 { -private: - // Hidden operators - bool operator<(const Color3&) const; - bool operator>(const Color3&) const; - bool operator<=(const Color3&) const; - bool operator>=(const Color3&) const; - -public: - /** - Does not initialize fields. - */ - Color3(); - - explicit Color3(class BinaryInput& bi); - - Color3(float r, float g, float b); - Color3(float v) : r(v), g(v), b(v) {} - - explicit Color3(const class Vector3& v); - - explicit Color3(const float value[3]); - - /** - Initialize from another color. - */ - Color3 (const Color3& other); - - Color3 (const class Color3uint8& other); - - /** - Initialize from an HTML-style color (e.g. 0xFF0000 == RED) - */ - static Color3 fromARGB(uint32); - - /** Returns one of the color wheel colors (e.g. RED, GREEN, CYAN). - Does not include white, black, or gray. */ - static const Color3& wheelRandom(); - - /** - * Channel value. - */ - float r, g, b; - - void serialize(class BinaryOutput& bo) const; - void deserialize(class BinaryInput& bi); - - // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b - // - // WARNING. These member functions rely on - // (1) Color3 not having virtual functions - // (2) the data packed in a 3*sizeof(float) memory block - const float& operator[] (int i) const; - float& operator[] (int i); - - // assignment and comparison - Color3& operator= (const Color3& rkVector); - bool operator== (const Color3& rkVector) const; - bool operator!= (const Color3& rkVector) const; - size_t hashCode() const; - - // arithmetic operations - Color3 operator+ (const Color3& rkVector) const; - Color3 operator- (const Color3& rkVector) const; - Color3 operator* (float fScalar) const; - Color3 operator* (const Color3& rkVector) const; - Color3 operator/ (float fScalar) const; - Color3 operator- () const; - - // arithmetic updates - Color3& operator+= (const Color3& rkVector); - Color3& operator-= (const Color3& rkVector); - Color3& operator*= (const Color3& rkVector); - Color3& operator*= (float fScalar); - Color3& operator/= (float fScalar); - - bool fuzzyEq(const Color3& other) const; - bool fuzzyNe(const Color3& other) const; - - inline operator float* () { - return (float*)this; - } - - operator const float* () const { - return (float*)this; - } - - // vector operations - float length () const; - Color3 direction() const; - float squaredLength () const; - float dot (const Color3& rkVector) const; - float unitize (float fTolerance = 1e-06); - Color3 cross (const Color3& rkVector) const; - Color3 unitCross (const Color3& rkVector) const; - - inline Color3 pow(const Color3& other) const { - return Color3(::pow(r, other.r), ::pow(g, other.g), ::pow(b, other.b)); - } - - inline Color3 pow(float other) const { - return Color3(::pow(r, other), ::pow(g, other), ::pow(b, other)); - } - - /**@return the largest component */ - inline float max() const { - return G3D::max(G3D::max(r, g), b); - } - - inline Color3 max(const Color3& other) const { - return Color3(G3D::max(r, other.r), G3D::max(g, other.g), G3D::max(b, other.b)); - } - - inline Color3 min(const Color3& other) const { - return Color3(G3D::min(r, other.r), G3D::min(g, other.g), G3D::min(b, other.b)); - } - - inline Color3 lerp(const Color3& other, float a) const { - return (*this) + (other - *this) * a; - - } - - inline float sum() const { - return r + g + b; - } - - inline float average() const { - return sum() / 3.0f; - } - - - /** - * Converts from HSV to RGB , note: toHSV(fromHSV(_hsv)) may not be _hsv, if it is at a grey point or black point. - * The components of _hsv should lie in the unit interval. - * @cite Alvy Ray Smith SIGGRAPH 1978 "Color Gamut Transform Pairs" - **/ - static Color3 fromHSV(const Vector3& _hsv); - static Vector3 toHSV(const Color3& _rgb); - - /** Duplicates the matlab jet colormap maps [0,1] --> (r,g,b) where blue is close to 0 and red is close to 1. */ - static Color3 jetColorMap(const float& val); - - /** Returns colors with maximum saturation and value @param hue [0, 1]*/ - static Color3 rainbowColorMap(float hue); - - std::string toString() const; - - /** Random unit vector */ - static Color3 random(); - - // Special values. - // Intentionally not inlined: see Matrix3::identity() for details. - static const Color3& red(); - static const Color3& green(); - static const Color3& blue(); - static const Color3& purple(); - static const Color3& cyan(); - static const Color3& yellow(); - static const Color3& brown(); - static const Color3& orange(); - static const Color3& black(); - static const Color3& gray(); - static const Color3& white(); - - static const Color3& zero(); - static const Color3& one(); - - inline Color3 bgr() const { - return Color3(b, g, r); - } -}; - -inline G3D::Color3 operator* (float s, const G3D::Color3& c) { - return c * s; -} - -inline G3D::Color3 operator* (G3D::Color1& s, const G3D::Color3& c) { - return c * s.value; -} - -inline G3D::Color3 operator* (const G3D::Color3& c, G3D::Color1& s) { - return c * s.value; -} - - -//---------------------------------------------------------------------------- -inline Color3::Color3 () { -} - -//---------------------------------------------------------------------------- - -inline Color3::Color3(float fX, float fY, float fZ) { - r = fX; - g = fY; - b = fZ; -} - -//---------------------------------------------------------------------------- -inline Color3::Color3(const float afCoordinate[3]) { - r = afCoordinate[0]; - g = afCoordinate[1]; - b = afCoordinate[2]; -} - -//---------------------------------------------------------------------------- -inline Color3::Color3 (const Color3& rkVector) { - r = rkVector.r; - g = rkVector.g; - b = rkVector.b; -} - -//---------------------------------------------------------------------------- -inline float& Color3::operator[] (int i) { - return ((float*)this)[i]; -} - -//---------------------------------------------------------------------------- - -inline const float& Color3::operator[] (int i) const { - return ((float*)this)[i]; -} - -//---------------------------------------------------------------------------- - -inline bool Color3::fuzzyEq(const Color3& other) const { - return G3D::fuzzyEq((*this - other).squaredLength(), 0); -} - -//---------------------------------------------------------------------------- - -inline bool Color3::fuzzyNe(const Color3& other) const { - return G3D::fuzzyNe((*this - other).squaredLength(), 0); -} - - -//---------------------------------------------------------------------------- -inline Color3& Color3::operator= (const Color3& rkVector) { - r = rkVector.r; - g = rkVector.g; - b = rkVector.b; - return *this; -} - -//---------------------------------------------------------------------------- -inline bool Color3::operator== (const Color3& rkVector) const { - return ( r == rkVector.r && g == rkVector.g && b == rkVector.b ); -} - -//---------------------------------------------------------------------------- -inline bool Color3::operator!= (const Color3& rkVector) const { - return ( r != rkVector.r || g != rkVector.g || b != rkVector.b ); -} - -//---------------------------------------------------------------------------- -inline Color3 Color3::operator+ (const Color3& rkVector) const { - return Color3(r + rkVector.r, g + rkVector.g, b + rkVector.b); -} - -//---------------------------------------------------------------------------- -inline Color3 Color3::operator- (const Color3& rkVector) const { - return Color3(r -rkVector.r, g - rkVector.g, b - rkVector.b); -} - -//---------------------------------------------------------------------------- -inline Color3 Color3::operator* (float fScalar) const { - return Color3(fScalar*r, fScalar*g, fScalar*b); -} - -//---------------------------------------------------------------------------- -inline Color3 Color3::operator* (const Color3& rkVector) const { - return Color3(r * rkVector.r, g * rkVector.g, b * rkVector.b); -} - -//---------------------------------------------------------------------------- -inline Color3 Color3::operator- () const { - return Color3( -r, -g, -b); -} - -//---------------------------------------------------------------------------- -inline Color3& Color3::operator+= (const Color3& rkVector) { - r += rkVector.r; - g += rkVector.g; - b += rkVector.b; - return *this; -} - -//---------------------------------------------------------------------------- -inline Color3& Color3::operator-= (const Color3& rkVector) { - r -= rkVector.r; - g -= rkVector.g; - b -= rkVector.b; - return *this; -} - -//---------------------------------------------------------------------------- -inline Color3& Color3::operator*= (float fScalar) { - r *= fScalar; - g *= fScalar; - b *= fScalar; - return *this; -} - -//---------------------------------------------------------------------------- -inline Color3& Color3::operator*= (const Color3& rkVector) { - r *= rkVector.r; - g *= rkVector.g; - b *= rkVector.b; - return *this; -} -//---------------------------------------------------------------------------- -inline float Color3::squaredLength () const { - return r*r + g*g + b*b; -} - -//---------------------------------------------------------------------------- -inline float Color3::length () const { - return sqrtf(r*r + g*g + b*b); -} - -//---------------------------------------------------------------------------- -inline Color3 Color3::direction () const { - float lenSquared = r * r + g * g + b * b; - - if (lenSquared != 1.0f) { - return *this / sqrtf(lenSquared); - } else { - return *this; - } -} - -//---------------------------------------------------------------------------- -inline float Color3::dot (const Color3& rkVector) const { - return r*rkVector.r + g*rkVector.g + b*rkVector.b; -} - -//---------------------------------------------------------------------------- -inline Color3 Color3::cross (const Color3& rkVector) const { - return Color3(g*rkVector.b - b*rkVector.g, b*rkVector.r - r*rkVector.b, - r*rkVector.g - g*rkVector.r); -} - -//---------------------------------------------------------------------------- -inline Color3 Color3::unitCross (const Color3& rkVector) const { - Color3 kCross(g*rkVector.b - b*rkVector.g, b*rkVector.r - r*rkVector.b, - r*rkVector.g - g*rkVector.r); - kCross.unitize(); - return kCross; -} -} // namespace - - -template <> struct HashTrait { - static size_t hashCode(const G3D::Color3& key) { - return key.hashCode(); - } -}; - - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Color3uint8.h b/externals/g3dlite/G3D.lib/include/G3D/Color3uint8.h deleted file mode 100644 index 20e225a0734..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Color3uint8.h +++ /dev/null @@ -1,127 +0,0 @@ -/** - @file Color3uint8.h - - @maintainer Morgan McGuire, graphics3d.com - - @created 2003-04-07 - @edited 2006-06-24 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_COLOR3UINT8_H -#define G3D_COLOR3UINT8_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" - -namespace G3D { - -/** - Represents a Color3 as a packed integer. Convenient - for creating unsigned int vertex arrays. Used by - G3D::GImage as the underlying format. - - WARNING: Integer color formats are different than - integer vertex formats. The color channels are automatically - scaled by 255 (because OpenGL automatically scales integer - colors back by this factor). So Color3(1,1,1) == Color3uint8(255,255,255) - but Vector3(1,1,1) == Vector3int16(1,1,1). - */ - -#if defined(G3D_WIN32) - // Switch to tight alignment - #pragma pack(push, 1) -#endif - -class Color3uint8 { -private: - // Hidden operators - bool operator<(const Color3uint8&) const; - bool operator>(const Color3uint8&) const; - bool operator<=(const Color3uint8&) const; - bool operator>=(const Color3uint8&) const; - -public: - uint8 r; - uint8 g; - uint8 b; - - Color3uint8() : r(0), g(0), b(0) {} - - Color3uint8(const uint8 _r, const uint8 _g, const uint8 _b) : r(_r), g(_g), b(_b) {} - - Color3uint8(const class Color3& c); - - Color3uint8(class BinaryInput& bi); - - inline static Color3uint8 fromARGB(uint32 i) { - Color3uint8 c; - c.r = (i >> 16) & 0xFF; - c.g = (i >> 8) & 0xFF; - c.b = i & 0xFF; - return c; - } - - inline Color3uint8 bgr() const { - return Color3uint8(b, g, r); - } - - /** - Returns the color packed into a uint32 - (the upper byte is 0xFF) - */ - inline uint32 asUInt32() const { - return (0xFF << 24) + ((uint32)r << 16) + ((uint32)g << 8) + b; - } - - void serialize(class BinaryOutput& bo) const; - - void deserialize(class BinaryInput& bi); - - // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b - // - // WARNING. These member functions rely on - // (1) Color3 not having virtual functions - // (2) the data packed in a 3*sizeof(uint8) memory block - G3D::uint8& operator[] (int i) const; - operator G3D::uint8* (); - operator const G3D::uint8* () const; - - bool operator==(const Color3uint8& other) const { - return (other.r == r) && (other.g == g) && (other.b == b); - } - - bool operator!=(const Color3uint8& other) const { - return (other.r != r) && (other.g != g) && (other.b != b); - } -} - -#if defined(G3D_LINUX) || defined(G3D_OSX) - __attribute((aligned(1))) -#endif - -; - -#ifdef G3D_WIN32 - #pragma pack(pop) -#endif - - -inline G3D::uint8& Color3uint8::operator[] (int i) const { - debugAssert((unsigned int)i < 3); - return ((G3D::uint8*)this)[i]; -} - -//---------------------------------------------------------------------------- -inline Color3uint8::operator G3D::uint8* () { - return (G3D::uint8*)this; -} - -inline Color3uint8::operator const G3D::uint8* () const { - return (G3D::uint8*)this; -} -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Color4.h b/externals/g3dlite/G3D.lib/include/G3D/Color4.h deleted file mode 100644 index 6b1b3b4c4bb..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Color4.h +++ /dev/null @@ -1,324 +0,0 @@ -/** - @file Color4.h - - Color class - - @maintainer Morgan McGuire, matrix@graphics3d.com - @cite Portions based on Dave Eberly's Magic Software Library - at http://www.magic-software.com - - @created 2002-06-25 - @edited 2008-07-16 - - Copyright 2000-2008, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_COLOR4_H -#define G3D_COLOR4_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Color3.h" -#include - -namespace G3D { - -/** - Do not subclass-- this implementation makes assumptions about the - memory layout. - */ -class Color4 { -private: - // Hidden operators - bool operator<(const Color4&) const; - bool operator>(const Color4&) const; - bool operator<=(const Color4&) const; - bool operator>=(const Color4&) const; - -public: - - /** - * Does not initialize fields. - */ - Color4 (); - - Color4(const Color3& c3, float a = 1.0); - - Color4(const class Color4uint8& c); - - Color4(class BinaryInput& bi); - - Color4(const class Vector4& v); - - /** - * Initialize from G3D::Reals. - */ - Color4(float r, float g, float b, float a = 1.0); - - /** - * Initialize from array of G3D::Reals. - */ - Color4(float value[4]); - - /** - * Initialize from another color. - */ - Color4(const Color4& other); - - void serialize(class BinaryOutput& bo) const; - void deserialize(class BinaryInput& bi); - - /** - Initialize from an HTML-style color (e.g. 0xFFFF0000 == RED) - */ - static Color4 fromARGB(uint32); - - /** - * Channel values. - */ - float r, g, b, a; - - inline Color3 rgb() const { - return Color3(r, g, b); - } - - // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b, v[3] = V.a - // - // WARNING. These member functions rely on - // (1) Color4 not having virtual functions - // (2) the data packed in a 3*sizeof(float) memory block - float& operator[] (int i) const; - operator float* (); - operator const float* () const; - - // assignment and comparison - Color4& operator= (const Color4& rkVector); - bool operator== (const Color4& rkVector) const; - bool operator!= (const Color4& rkVector) const; - size_t hashCode() const; - - // arithmetic operations - Color4 operator+ (const Color4& rkVector) const; - Color4 operator- (const Color4& rkVector) const; - Color4 operator* (float fScalar) const; - Color4 operator/ (float fScalar) const; - Color4 operator- () const; - friend Color4 operator* (double fScalar, const Color4& rkVector); - - // arithmetic updates - Color4& operator+= (const Color4& rkVector); - Color4& operator-= (const Color4& rkVector); - Color4& operator*= (float fScalar); - Color4& operator/= (float fScalar); - - bool fuzzyEq(const Color4& other) const; - bool fuzzyNe(const Color4& other) const; - - std::string toString() const; - - inline Color4 max(const Color4& other) const { - return Color4(G3D::max(r, other.r), G3D::max(g, other.g), G3D::max(b, other.b), G3D::max(a, other.a)); - } - - inline Color4 min(const Color4& other) const { - return Color4(G3D::min(r, other.r), G3D::min(g, other.g), G3D::min(b, other.b), G3D::min(a, other.a)); - } - - /** r + g + b + a */ - inline float sum() const { - return r + g + b + a; - } - - inline Color4 lerp(const Color4& other, float a) const { - return (*this) + (other - *this) * a; - - } - - // Special values. - // Intentionally not inlined: see Matrix3::identity() for details. - static const Color4& zero(); - static const Color4& clear(); - - static const Color4& inf(); - - inline Color3 bgr() const { - return Color3(b, g, r); - } -}; - -/** - Extends the c3 with alpha = 1.0 - */ -Color4 operator*(const Color3& c3, const Color4& c4); - - -inline Color4 operator*(const Color3& c3, const Color4& c4) { - return Color4(c3.r * c4.r, c3.g * c4.g, c3.b * c4.b, c4.a); -} - -//---------------------------------------------------------------------------- - -inline Color4::Color4 () { - // For efficiency in construction of large arrays of vectors, the - // default constructor does not initialize the vector. -} - -//---------------------------------------------------------------------------- - -inline Color4::Color4(const Color3& c3, float a) { - r = c3.r; - g = c3.g; - b = c3.b; - this->a = a; -} - -//---------------------------------------------------------------------------- - -inline Color4::Color4( - float r, - float g, - float b, - float a) : - r(r), g(g), b(b), a(a) { -} - -//---------------------------------------------------------------------------- -inline Color4::Color4 (float afCoordinate[4]) { - r = afCoordinate[0]; - g = afCoordinate[1]; - b = afCoordinate[2]; - a = afCoordinate[3]; -} - -//---------------------------------------------------------------------------- - -inline Color4::Color4( - const Color4& other) { - - r = other.r; - g = other.g; - b = other.b; - a = other.a; -} - -//---------------------------------------------------------------------------- - -inline float& Color4::operator[] (int i) const { - return ((float*)this)[i]; -} - -//---------------------------------------------------------------------------- -inline Color4::operator float* () { - return (float*)this; -} - -inline Color4::operator const float* () const { - return (float*)this; -} - -//---------------------------------------------------------------------------- - -inline bool Color4::fuzzyEq(const Color4& other) const { - Color4 dif = (*this - other); - return G3D::fuzzyEq(dif.r * dif.r + dif.g * dif.g + dif.b * dif.b + dif.a * dif.a, 0); -} - -//---------------------------------------------------------------------------- - -inline bool Color4::fuzzyNe(const Color4& other) const { - Color4 dif = (*this - other); - return G3D::fuzzyNe(dif.r * dif.r + dif.g * dif.g + dif.b * dif.b + dif.a * dif.a, 0); -} - - -//---------------------------------------------------------------------------- -inline Color4& Color4::operator= (const Color4& other) { - r = other.r; - g = other.g; - b = other.b; - a = other.a; - return *this; -} - -//---------------------------------------------------------------------------- - -inline bool Color4::operator== (const Color4& other) const { - return ( r == other.r && g == other.g && b == other.b && a == other.a); -} - -//---------------------------------------------------------------------------- - -inline bool Color4::operator!= (const Color4& other) const { - return ( r != other.r || g != other.g || b != other.b || a != other.a); -} - -//---------------------------------------------------------------------------- -inline Color4 Color4::operator+ (const Color4& other) const { - return Color4(r + other.r, g + other.g, b + other.b, a + other.a); -} - -//---------------------------------------------------------------------------- -inline Color4 Color4::operator- (const Color4& other) const { - return Color4(r - other.r, g - other.g, b - other.b, a - other.a); -} - -//---------------------------------------------------------------------------- - -inline Color4 Color4::operator* (float fScalar) const { - return Color4(fScalar * r, fScalar * g, fScalar * b, fScalar * a); -} - -//---------------------------------------------------------------------------- - -inline Color4 Color4::operator- () const { - return Color4(-r, -g, -b, -a); -} - -//---------------------------------------------------------------------------- - -inline Color4 operator* (float fScalar, const Color4& other) { - return Color4(fScalar * other.r, fScalar * other.g, - fScalar * other.b, fScalar * other.a); -} - -//---------------------------------------------------------------------------- - -inline Color4& Color4::operator+= (const Color4& other) { - r += other.r; - g += other.g; - b += other.b; - a += other.a; - return *this; -} - -//---------------------------------------------------------------------------- - -inline Color4& Color4::operator-= (const Color4& other) { - r -= other.r; - g -= other.g; - b -= other.b; - a -= other.a; - return *this; -} - -//---------------------------------------------------------------------------- - -inline Color4& Color4::operator*= (float fScalar) { - r *= fScalar; - g *= fScalar; - b *= fScalar; - a *= fScalar; - return *this; -} - -} // namespace - -template <> -struct HashTrait { - static size_t hashCode(const G3D::Color4& key) { - return key.hashCode(); - } -}; - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Color4uint8.h b/externals/g3dlite/G3D.lib/include/G3D/Color4uint8.h deleted file mode 100644 index 7804a6e1e51..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Color4uint8.h +++ /dev/null @@ -1,133 +0,0 @@ -/** - @file Color4uint8.h - - @maintainer Morgan McGuire, graphics3d.com - - @created 2003-04-07 - @edited 2006-03-24 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#ifndef COLOR4UINT8_H -#define COLOR4UINT8_H - -#include "G3D/g3dmath.h" -#include "G3D/platform.h" -#include "G3D/Color3uint8.h" - -namespace G3D { - -/** - Represents a Color4 as a packed integer. Convenient - for creating unsigned int vertex arrays. Used by - G3D::GImage as the underlying format. - - WARNING: Integer color formats are different than - integer vertex formats. The color channels are automatically - scaled by 255 (because OpenGL automatically scales integer - colors back by this factor). So Color4(1,1,1) == Color4uint8(255,255,255) - but Vector3(1,1,1) == Vector3int16(1,1,1). - - */ - -#ifdef G3D_WIN32 - // Switch to tight alignment - #pragma pack(push, 1) -#endif - -class Color4uint8 { -private: - // Hidden operators - bool operator<(const Color4uint8&) const; - bool operator>(const Color4uint8&) const; - bool operator<=(const Color4uint8&) const; - bool operator>=(const Color4uint8&) const; - -public: - uint8 r; - uint8 g; - uint8 b; - uint8 a; - - Color4uint8() : r(0), g(0), b(0), a(0) {} - - Color4uint8(const class Color4& c); - - Color4uint8(const uint8 _r, const uint8 _g, const uint8 _b, const uint8 _a) : r(_r), g(_g), b(_b), a(_a) {} - - Color4uint8(const Color3uint8& c, const uint8 _a) : r(c.r), g(c.g), b(c.b), a(_a) {} - - Color4uint8(class BinaryInput& bi); - - inline static Color4uint8 fromARGB(uint32 i) { - Color4uint8 c; - c.a = (i >> 24) & 0xFF; - c.r = (i >> 16) & 0xFF; - c.g = (i >> 8) & 0xFF; - c.b = i & 0xFF; - return c; - } - - inline uint32 asUInt32() const { - return ((uint32)a << 24) + ((uint32)r << 16) + ((uint32)g << 8) + b; - } - - // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b - // - // WARNING. These member functions rely on - // (1) Color4uint8 not having virtual functions - // (2) the data packed in a 3*sizeof(uint8) memory block - G3D::uint8& operator[] (int i) const; - operator G3D::uint8* (); - operator const G3D::uint8* () const; - - - inline Color3uint8 bgr() const { - return Color3uint8(b, g, r); - } - - void serialize(class BinaryOutput& bo) const; - - void deserialize(class BinaryInput& bi); - - inline Color3uint8 rgb() const { - return Color3uint8(r, g, b); - } - - bool operator==(const Color4uint8& other) const { - return *reinterpret_cast(this) == *reinterpret_cast(&other); - } - - bool operator!=(const Color4uint8& other) const { - return *reinterpret_cast(this) != *reinterpret_cast(&other); - } - -} -#if defined(G3D_LINUX) || defined(G3D_OSX) - __attribute((aligned(1))) -#endif -; - -#ifdef G3D_WIN32 - #pragma pack(pop) -#endif - - -inline G3D::uint8& Color4uint8::operator[] (int i) const { - return ((G3D::uint8*)this)[i]; -} - -//---------------------------------------------------------------------------- -inline Color4uint8::operator G3D::uint8* () { - return (G3D::uint8*)this; -} - -inline Color4uint8::operator const G3D::uint8* () const { - return (G3D::uint8*)this; -} - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Cone.h b/externals/g3dlite/G3D.lib/include/G3D/Cone.h deleted file mode 100644 index c09b9b6846c..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Cone.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - @file Cone.h - - Cone class - - @maintainer Morgan McGuire, matrix@graphics3d.com - @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com - - @created 2001-06-02 - @edited 2006-02-23 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_CONE_H -#define G3D_CONE_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Vector3.h" - -namespace G3D { - -/** - An infinite cone. - */ -class Cone { - -private: - Vector3 tip; - Vector3 direction; - - /** Angle from the center line to the edge. */ - float angle; - -public: - - /** - @param angle Angle from the center line to the edge, in radians - */ - Cone(const Vector3& tip, const Vector3& direction, float angle); - - /** - Forms the smallest cone that contains the box. Undefined if - the tip is inside or on the box. - */ - Cone(const Vector3& tip, const class Box& box); - - virtual ~Cone() {} - - /** - Returns true if the cone touches, intersects, or contains b. - - If c.intersects(s) and c.intersects(Sphere(s.center, s.radius * 2) - then the sphere s is entirely within cone c. - */ - bool intersects(const class Sphere& s) const; - - /** - True if v is a point inside the cone. - */ - bool contains(const class Vector3& v) const; -}; - -} // namespace - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/ConvexPolyhedron.h b/externals/g3dlite/G3D.lib/include/G3D/ConvexPolyhedron.h deleted file mode 100644 index 6ae9ba136ff..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/ConvexPolyhedron.h +++ /dev/null @@ -1,179 +0,0 @@ -/** - @file ConvexPolyhedron.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2001-11-11 - @edited 2006-04-10 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_CONVEXPOLYHEDRON_H -#define G3D_CONVEXPOLYHEDRON_H - -#include "G3D/platform.h" -#include "G3D/Vector3.h" -#include "G3D/Vector2.h" -#include "G3D/CoordinateFrame.h" -#include "G3D/Plane.h" -#include "G3D/Line.h" -#include "G3D/Array.h" - -namespace G3D { - -class DirectedEdge { -public: - Vector3 start; - Vector3 stop; -}; - -class ConvexPolygon { -private: - - friend class ConvexPolyhedron; - - Array _vertex; - -public: - - ConvexPolygon() {} - ConvexPolygon(const Array& __vertex); - virtual ~ConvexPolygon() {} - - /** - Counter clockwise winding order. - */ - inline const Vector3& vertex(int i) const { - return _vertex[i]; - } - - inline void setVertex(int i, const Vector3& v) { - _vertex[i] = v; - } - - /** - Zero vertices indicates an empty polygon (zero area). - */ - inline int numVertices() const { - return _vertex.size(); - } - - inline void setNumVertices(int n) { - _vertex.resize(n); - } - - /** - O(n) in the number of edges - */ - bool isEmpty() const; - - /** - Cuts the polygon at the plane. If the polygon is entirely above or below - the plane, one of the returned polygons will be empty. - - @param above The part of the polygon above (on the side the - normal points to or in the plane) the plane - @param below The part of the polygon below the plane. - @param newEdge If a new edge was introduced, this is that edge (on the above portion; the below portion is the opposite winding. - */ - void cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon &below, DirectedEdge& newEdge); - void cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon &below); - - /** - When a cut plane grazes a vertex in the polygon, two near-identical vertices may be created. - The closeness of these two points can cause a number of problems, such as ConvexPolygon::normal() - returning an infinite vector. It should be noted, however, that not all applications are - sensitive to near-identical vertices. - - removeDuplicateVertices() detects and eliminates redundant vertices. - */ - void removeDuplicateVertices(); - - /** - O(n) in the number of edges - */ - float getArea() const; - - inline Vector3 normal() const { - debugAssert(_vertex.length() >= 3); - return (_vertex[1] - _vertex[0]).cross(_vertex[2] - _vertex[0]).direction(); - } - - /** - Returns the same polygon with inverse winding. - */ - ConvexPolygon inverse() const; -}; - - - -class ConvexPolyhedron { -public: - /** - Zero faces indicates an empty polyhedron - */ - Array face; - - ConvexPolyhedron() {} - ConvexPolyhedron(const Array& _face); - - /** - O(n) in the number of edges - */ - bool isEmpty() const; - - /** - O(n) in the number of edges - */ - float getVolume() const; - - /** - Cuts the polyhedron at the plane. If the polyhedron is entirely above or below - the plane, one of the returned polyhedra will be empty. - - @param above The part of the polyhedron above (on the side the - normal points to or in the plane) the plane - @param below The part of the polyhedron below the plane. - */ - void cut(const Plane& plane, ConvexPolyhedron &above, ConvexPolyhedron &below); -}; - -/** - - */ -class ConvexPolygon2D { -private: - - Array m_vertex; - -public: - - ConvexPolygon2D() {} - - /** - Points are counter-clockwise in a Y = down, X = right coordinate - system. - - @param reverse If true, the points are reversed (i.e. winding direction is changed) - before the polygon is created. - */ - ConvexPolygon2D(const Array& pts, bool reverse = false); - - inline int numVertices() const { - return m_vertex.size(); - } - - inline const Vector2& vertex(int index) const { - debugAssert((index >= 0) && (index <= m_vertex.size())); - return m_vertex[index]; - } - - /** @param reverseWinding If true, the winding direction of the polygon is reversed for this test.*/ - bool contains(const Vector2& p, bool reverseWinding = false) const; -}; - - -} // namespace -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/CoordinateFrame.h b/externals/g3dlite/G3D.lib/include/G3D/CoordinateFrame.h deleted file mode 100644 index 705c6c93ae2..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/CoordinateFrame.h +++ /dev/null @@ -1,315 +0,0 @@ -/** - @file CoordinateFrame.h - - @maintainer Morgan McGuire, morgan@cs.williams.edu - - @created 2001-03-04 - @edited 2008-07-14 - - Copyright 2000-2008, Morgan McGuire. - All rights reserved. -*/ - -#ifndef G3D_COORDINATEFRAME_H -#define G3D_COORDINATEFRAME_H - -#include "G3D/platform.h" -#include "G3D/Vector3.h" -#include "G3D/Vector4.h" -#include "G3D/Matrix3.h" -#include "G3D/Array.h" -#include -#include -#include -#include -#include - -namespace G3D { - -/** - A rigid body RT (rotation-translation) transformation. - -CoordinateFrame abstracts a 4x4 matrix that maps object space to world space: - - v_world = C * v_object - -CoordinateFrame::rotation is the upper 3x3 submatrix, CoordinateFrame::translation -is the right 3x1 column. The 4th row is always [0 0 0 1], so it isn't stored. -So you don't have to remember which way the multiplication and transformation work, -it provides explicit toWorldSpace and toObjectSpace methods. Also, points, vectors -(directions), and surface normals transform differently, so they have separate methods. - -Some helper functions transform whole primitives like boxes in and out of object space. - -Convert to Matrix4 using CoordinateFrame::toMatrix4. You can construct a CoordinateFrame -from a Matrix4 using Matrix4::approxCoordinateFrame, however, because a Matrix4 is more -general than a CoordinateFrame, some information may be lost. - -@sa G3D::UprightFrame, G3D::PhysicsFrame, G3D::Matrix4, G3D::Quat -*/ -class CoordinateFrame { -public: - - /** Takes object space points to world space. */ - Matrix3 rotation; - - /** Takes object space points to world space. */ - Vector3 translation; - - inline bool operator==(const CoordinateFrame& other) const { - return (translation == other.translation) && (rotation == other.rotation); - } - - inline bool operator!=(const CoordinateFrame& other) const { - return !(*this == other); - } - - bool fuzzyEq(const CoordinateFrame& other) const; - - bool fuzzyIsIdentity() const; - - bool isIdentity() const; - - /** - Initializes to the identity coordinate frame. - */ - inline CoordinateFrame() : - rotation(Matrix3::identity()), translation(Vector3::zero()) { - } - - CoordinateFrame(const Vector3& _translation) : - rotation(Matrix3::identity()), translation(_translation) { - } - - CoordinateFrame(const Matrix3 &rotation, const Vector3 &translation) : - rotation(rotation), translation(translation) { - } - - CoordinateFrame(const Matrix3 &rotation) : - rotation(rotation), translation(Vector3::zero()) { - } - - CoordinateFrame(const class UprightFrame& f); - - static CoordinateFrame fromXYZYPRRadians(float x, float y, float z, float yaw = 0.0f, float pitch = 0.0f, float roll = 0.0f); - - /** Construct a coordinate frame from translation = (x,y,z) and - rotations (in that order) about Y, object space X, object space - Z. Note that because object-space axes are used, these are not - equivalent to Euler angles; they are known as Tait-Bryan - rotations and are more convenient for intuitive positioning.*/ - static CoordinateFrame fromXYZYPRDegrees(float x, float y, float z, float yaw = 0.0f, float pitch = 0.0f, float roll = 0.0f); - - CoordinateFrame(class BinaryInput& b); - - void deserialize(class BinaryInput& b); - - void serialize(class BinaryOutput& b) const; - - CoordinateFrame(const CoordinateFrame &other) : - rotation(other.rotation), translation(other.translation) {} - - /** - Computes the inverse of this coordinate frame. - */ - inline CoordinateFrame inverse() const { - CoordinateFrame out; - out.rotation = rotation.transpose(); - out.translation = -out.rotation * translation; - return out; - } - - inline ~CoordinateFrame() {} - - /** See also Matrix4::approxCoordinateFrame */ - class Matrix4 toMatrix4() const; - - void getXYZYPRRadians(float& x, float& y, float& z, float& yaw, float& pitch, float& roll) const; - void getXYZYPRDegrees(float& x, float& y, float& z, float& yaw, float& pitch, float& roll) const; - - - /** - Produces an XML serialization of this coordinate frame. - @deprecated - */ - std::string toXML() const; - - /** - Returns the heading of the lookVector as an angle in radians relative to - the world -z axis. That is, a counter-clockwise heading where north (-z) - is 0 and west (-x) is PI/2. - - Note that the heading ignores the Y axis, so an inverted - object has an inverted heading. - */ - inline float getHeading() const { - Vector3 look = rotation.getColumn(2); - float angle = -(float) atan2(-look.x, look.z); - return angle; - } - - /** - Takes the coordinate frame into object space. - this->inverse() * c - */ - inline CoordinateFrame toObjectSpace(const CoordinateFrame& c) const { - return this->inverse() * c; - } - - inline Vector4 toObjectSpace(const Vector4& v) const { - return this->inverse().toWorldSpace(v); - } - - inline Vector4 toWorldSpace(const Vector4& v) const { - return Vector4(rotation * Vector3(v.x, v.y, v.z) + translation * v.w, v.w); - } - - /** - Transforms the point into world space. - */ - inline Vector3 pointToWorldSpace(const Vector3& v) const { - return Vector3( - rotation[0][0] * v[0] + rotation[0][1] * v[1] + rotation[0][2] * v[2] + translation[0], - rotation[1][0] * v[0] + rotation[1][1] * v[1] + rotation[1][2] * v[2] + translation[1], - rotation[2][0] * v[0] + rotation[2][1] * v[1] + rotation[2][2] * v[2] + translation[2]); - } - - /** - Transforms the point into object space. Assumes that the rotation matrix is orthonormal. - */ - inline Vector3 pointToObjectSpace(const Vector3& v) const { - float p[3]; - p[0] = v[0] - translation[0]; - p[1] = v[1] - translation[1]; - p[2] = v[2] - translation[2]; - debugAssert(G3D::fuzzyEq(rotation.determinant(), 1.0f)); - return Vector3( - rotation[0][0] * p[0] + rotation[1][0] * p[1] + rotation[2][0] * p[2], - rotation[0][1] * p[0] + rotation[1][1] * p[1] + rotation[2][1] * p[2], - rotation[0][2] * p[0] + rotation[1][2] * p[1] + rotation[2][2] * p[2]); - } - - /** - Transforms the vector into world space (no translation). - */ - inline Vector3 vectorToWorldSpace(const Vector3& v) const { - return rotation * v; - } - - inline Vector3 normalToWorldSpace(const Vector3& v) const { - return rotation * v; - } - - class Ray toObjectSpace(const Ray& r) const; - - Ray toWorldSpace(const Ray& r) const; - - /** - Transforms the vector into object space (no translation). - */ - inline Vector3 vectorToObjectSpace(const Vector3 &v) const { - // Multiply on the left (same as rotation.transpose() * v) - return v * rotation; - } - - inline Vector3 normalToObjectSpace(const Vector3 &v) const { - // Multiply on the left (same as rotation.transpose() * v) - return v * rotation; - } - - void pointToWorldSpace(const Array& v, Array& vout) const; - - void normalToWorldSpace(const Array& v, Array& vout) const; - - void vectorToWorldSpace(const Array& v, Array& vout) const; - - void pointToObjectSpace(const Array& v, Array& vout) const; - - void normalToObjectSpace(const Array& v, Array& vout) const; - - void vectorToObjectSpace(const Array& v, Array& vout) const; - - class Box toWorldSpace(const class AABox& b) const; - - class Box toWorldSpace(const class Box& b) const; - - class Cylinder toWorldSpace(const class Cylinder& b) const; - - class Capsule toWorldSpace(const class Capsule& b) const; - - class Plane toWorldSpace(const class Plane& p) const; - - class Sphere toWorldSpace(const class Sphere& b) const; - - class Triangle toWorldSpace(const class Triangle& t) const; - - class Box toObjectSpace(const AABox& b) const; - - class Box toObjectSpace(const Box& b) const; - - class Plane toObjectSpace(const Plane& p) const; - - class Sphere toObjectSpace(const Sphere& b) const; - - Triangle toObjectSpace(const Triangle& t) const; - - /** Compose: create the transformation that is other followed by this.*/ - CoordinateFrame operator*(const CoordinateFrame &other) const { - return CoordinateFrame(rotation * other.rotation, - pointToWorldSpace(other.translation)); - } - - CoordinateFrame operator+(const Vector3& v) const { - return CoordinateFrame(rotation, translation + v); - } - - CoordinateFrame operator-(const Vector3& v) const { - return CoordinateFrame(rotation, translation - v); - } - - void lookAt(const Vector3& target); - - void lookAt( - const Vector3& target, - Vector3 up); - - /** The direction this camera is looking (its negative z axis)*/ - inline Vector3 lookVector() const { - return -rotation.getColumn(2); - } - - /** Returns the ray starting at the camera origin travelling in direction CoordinateFrame::lookVector. */ - class Ray lookRay() const; - - /** Up direction for this camera (its y axis). */ - inline Vector3 upVector() const { - return rotation.getColumn(1); - } - - inline Vector3 rightVector() const { - return rotation.getColumn(0); - } - - /** - If a viewer looks along the look vector, this is the viewer's "left". - Useful for strafing motions and building alternative coordinate frames. - */ - inline Vector3 leftVector() const { - return -rotation.getColumn(0); - } - - /** - Linearly interpolates between two coordinate frames, using - Quat::slerp for the rotations. - */ - CoordinateFrame lerp( - const CoordinateFrame& other, - float alpha) const; - -}; - -typedef CoordinateFrame CFrame; - -} // namespace - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Crypto.h b/externals/g3dlite/G3D.lib/include/G3D/Crypto.h deleted file mode 100644 index f8266b8721b..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Crypto.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - @file Crypto.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - - @created 2006-03-29 - @edited 2006-04-06 - */ - -#ifndef G3D_CRYPTO_H -#define G3D_CRYPTO_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include - -namespace G3D { - -/** See G3D::Crypto::md5 */ -class MD5Hash { -private: - - uint8 value[16]; - -public: - - MD5Hash() { - for (int i = 0; i < 16; ++i) { - value[i] = 0; - } - } - - explicit MD5Hash(class BinaryInput& b); - - uint8& operator[](int i) { - return value[i]; - } - - const uint8& operator[](int i) const { - return value[i]; - } - - bool operator==(const MD5Hash& other) const { - bool match = true; - for (int i = 0; i < 16; ++i) { - match = match && (other.value[i] == value[i]); - } - return match; - } - - inline bool operator!=(const MD5Hash& other) const { - return !(*this == other); - } - - void deserialize(class BinaryInput& b); - - void serialize(class BinaryOutput& b) const; -}; - - -/** Cryptography and hashing helper functions */ -class Crypto { -public: - - /** - Computes the CRC32 value of a byte array. CRC32 is designed to be a hash - function that produces different values for similar strings. - - This implementation is compatible with PKZIP and GZIP. - - Based on http://www.gamedev.net/reference/programming/features/crc32/ - */ - static uint32 crc32(const void* bytes, size_t numBytes); - - /** - Computes the MD5 hash (message digest) of a byte stream, as defined by - http://www.ietf.org/rfc/rfc1321.txt. - - @cite Based on implementation by L. Peter Deutsch, ghost@aladdin.com - */ - MD5Hash md5(const void* bytes, size_t numBytes); - - /** - Returns the nth prime less than 2000 in constant time. The first prime has index - 0 and is the number 2. - */ - static int smallPrime(int n); - - /** Returns 1 + the largest value that can be passed to smallPrime. */ - static int numSmallPrimes(); -}; - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Cylinder.h b/externals/g3dlite/G3D.lib/include/G3D/Cylinder.h deleted file mode 100644 index c341d29a2b9..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Cylinder.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - @file Cylinder.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-02-07 - @edited 2005-09-26 - - Copyright 2000-2005, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_Cylinder_H -#define G3D_Cylinder_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Vector3.h" - -namespace G3D { - -class Line; -class AABox; -/** - Right cylinder - */ -class Cylinder { -private: - Vector3 p1; - Vector3 p2; - - float mRadius; - -public: - - /** Uninitialized */ - Cylinder(); - Cylinder(class BinaryInput& b); - Cylinder(const Vector3& _p1, const Vector3& _p2, float _r); - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); - - /** The line down the center of the Cylinder */ - Line axis() const; - - /** - A reference frame in which the center of mass is at the origin and - the Y-axis is the cylinder's axis. If the cylinder is transformed, this reference frame - may freely rotate around its axis.*/ - void getReferenceFrame(class CoordinateFrame& cframe) const; - - /** Returns point 0 or 1 */ - inline const Vector3& point(int i) const { - debugAssert(i >= 0 && i <= 1); - return (i == 0) ? p1 : p2; - } - - /** - Returns true if the point is inside the Cylinder or on its surface. - */ - bool contains(const Vector3& p) const; - - float area() const; - - float volume() const; - - float radius() const; - - /** Center of mass */ - inline Vector3 center() const { - return (p1 + p2) / 2.0f; - } - - inline float height() const { - return (p1 - p2).magnitude(); - } - - /** - Get close axis aligned bounding box. - With vertical world orientation, the top and bottom might not be very tight. */ - void getBounds(AABox& out) const; - - /** Random world space point with outward facing normal. */ - void getRandomSurfacePoint(Vector3& P, Vector3& N) const; - - /** Point selected uniformly at random over the volume. */ - Vector3 randomInteriorPoint() const; -}; - -} // namespace - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Discovery.h b/externals/g3dlite/G3D.lib/include/G3D/Discovery.h deleted file mode 100644 index acd1c2c01d0..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Discovery.h +++ /dev/null @@ -1,589 +0,0 @@ -/** - @file Discovery.h - -

Discovery

- Discovery is the process by which computers on a Local Area Network (LAN) find - one another. The Discovery API allows clients to make a list of servers running - the same application. The application typically presents this list to the user - so he can choose which server to connect to. -

- Features of the Discovery API: -

- Low network traffic -
- Broadcasts mainly occur only when a new machine enters/leaves the network -
Responsive -
- Servers appear immediately after launching -
- Servers disappear immedatiately after they shut down -
Extensible -
- Add your own game information (e.g. score, num players, map name) -
Versioned -
- Tracks incompatible servers so end-users know to upgrade their client/server - -

Using the Discovery API

- - Subclass DiscoveryAdvertisement to add fields describing a server running your - application. For a game, these might be the current map name and the number - of players. -

- On the client, create an instance of DiscoveryClient. - On the server, create an instance of DiscoveryServer and initialize it with an - instance of your advertisement subclass. From your main loop, call doNetwork() - on the client and server instances. When your server shuts down, invoke cleanup() - on it. - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-06-26 - @edited 2008-11-24 - */ - -#ifndef G3D_DISCOVERY_H -#define G3D_DISCOVERY_H - -#include "G3D/platform.h" -#include "G3D/G3DGameUnits.h" -#include "G3D/NetworkDevice.h" -#include "G3D/Log.h" -#include - -/** - Different versions of G3D discovery protocols can't communicate with each other. - */ -#define G3D_DISCOVERY_PROTOCOL_NAME "G3D DISC" -#define G3D_DISCOVERY_PROTOCOL_VERSION 1 - -namespace G3D { - -/** - If a machine is running two different programs using discovery they - must have different ports. However different programs can share the - same ports if they run on the same LAN with different servers. - - @deprecated See Discovery2::Settings - */ -class DiscoverySettings { -public: - - /** - Name of the program using discovery; used so that mutliple - programs can use the same discovery ports on the same network. - */ - const char* appProtocolName; - - /** - Version of the network protocol of the program using discovery. - Used so that discovery can identify incompatible versions of - the server. - */ - int appProtocolVersion; - - /** - Port on which the server broadcasts its identity. The client - and server must agree on this value. - */ - uint16 serverBroadcastPort; - - /** - Port on which the client broadcasts a server request. The client - and server must agree on this value. - */ - uint16 clientBroadcastPort; - - /** - Clients connect into this port using a reliable conduit - to receive the advertisement from a server. The client - doesn't look at this value; it uses whatever the server - sends it. - */ - uint16 serverAdvertisementPort; - - /** - You can use the default G3D discovery ports as long as no other - program with the same protocol name is using this port. You - can run two different G3D discovery programs on the same - two ports as long as they have different application protocol - strings. - */ - DiscoverySettings( - const char* _appProtocolName, - int _appProtocolVersion, - uint16 _serverBroadcast = 6173, - uint16 _clientBroadcast = 6174, - uint16 _serverAdvertisementPort = 6175) : - appProtocolName(_appProtocolName), - appProtocolVersion(_appProtocolVersion), - serverBroadcastPort(_serverBroadcast), - clientBroadcastPort(_clientBroadcast), - serverAdvertisementPort(_serverAdvertisementPort) {} -}; - -/** - Make your own subclass of this advertisement. Add fields - (e.g. numPlayers, currentScore) to increase the amount - of information advertised. - - Overrides must provide a default constructor. - @deprecated See Discovery2::Settings - */ -class DiscoveryAdvertisement { -public: - - /** - Address to connect to on the server for the actual game. - The IP portion is ignored (the client figures out the IP - address from the packet itself) but the port is essential. - Note that this port must not be the discovery port. - */ - NetAddress address; - - /** - (Only used on the client) - Time since this advertisement was updated. - */ - RealTime lastUpdateTime; - - /** - Overrides must call DiscoveryAdvertisement::serialize(b) first. - */ - virtual void serialize(BinaryOutput& b) const; - - /** - Overrides must call DiscoveryAdvertisement::deserialize(b) first. - */ - virtual void deserialize(BinaryInput& b); - - /** - An empty virtual destructor for virtual methods. - */ - virtual ~DiscoveryAdvertisement() {} -}; - - -/** - Sent by servers to describe their location. - */ -class DiscoveryServerAddressMessage { -public: - - /** - Not part of the message; these settings are used to determine - if the correct protocol is being used. - */ - const DiscoverySettings* settings; - - - /** - Set to true if this server is running the correct protocol. - */ - bool correctProtocol; - - /** - This is set during the serialize process from the server's settings. - If different from the client's settings the discovery system will - classify this server as incompatible. - */ - int serverProtocolVersion[2]; - - Array address; - - DiscoveryServerAddressMessage() {} - DiscoveryServerAddressMessage(const DiscoverySettings* s) : settings(s) {} - - void serialize(BinaryOutput& b) const; - - void deserialize(BinaryInput& b); -}; - - -/** - Base class for DiscoveryClient and DiscoveryServer. - */ -class Discovery { -public: - - const DiscoverySettings* settings; - - enum { - SERVER_SHUTDOWN_MESSAGE = 2, - SERVER_BROADCAST_MESSAGE = 3, - CLIENT_BROADCAST_MESSAGE = 4}; - - /** - Only called from subclasses. - */ - virtual void init( - const DiscoverySettings* _settings) { - settings = _settings; - } - - /** - An empty virtual destructor for virtual methods. - */ - virtual ~Discovery() {} -}; - -/** @deprecated See Discovery2::Server*/ -class DiscoveryServer : private Discovery { -private: - - class ShutdownMessage { - public: - void serialize(BinaryOutput& b) const { (void)b; } - - void deserialize(BinaryInput& b) { (void)b; } - }; - - /** - For broadcast. - */ - LightweightConduitRef net; - - /** - Listen for clients wanting to hear the advertisement over - a reliable connection. - */ - NetListenerRef listener; - - DiscoveryAdvertisement* advertisement; - - /** - Broadcast across the lightweight conduit. - */ - DiscoveryServerAddressMessage addressMessage; - - /** - Servers periodically broadcast (unsolicited) in case - anyone missed the previous message. - */ - RealTime lastBroadcast; - - void sendAnnouncement() const; - - void sendShutDown() const; - -public: - - /** - You may update the advertisement (synchronously with calling doNetwork) - after it has been passed in. This allows a server to change the advertised - number of players or score for a game, for example. - - You must set the port of the @a _advertisement G3D::DiscoveryAdvertisement::address - to the port which the G3D::NetListener for the actual program protocol (not discovery) - is running. That field how the client knows what address to connect to using - G3D::ReliableConduit or G3D::LightweightConduit to actually initiate communication. - */ - virtual void init( - const DiscoverySettings* _settings, - DiscoveryAdvertisement* _advertisement); - - /** Returns the broadcast address in use.*/ - NetAddress broadcastAddress() const; - - /** - Returns true if this discovery server has been initialized - and is functioning properly. - */ - bool ok() const; - - /** - Call periodically to let the server do its job. - */ - void doNetwork(); - - /** - Broadcast a shutdown message. - */ - void cleanup(); -}; - - -/** - Used by DiscoveryClient to report servers running a different version - of this application's protocol. - */ -class IncompatibleServerDescription { -public: - NetAddress address; - int protocolVersion[2]; - RealTime lastUpdateTime; - - std::string toString() const; -}; - - -/** - Only one DiscoveryClient can be active on a given port at a time on - a single computer. - - AdType must be a subclass of DiscoveryAdvertisement. - - @deprecated See Discovery2::Client - */ -template -class DiscoveryClient : private Discovery { -public: - - /** - List of servers. Do not access on a second thread while in - doNetwork. - */ - Array serverList; - - /** - List of servers running the same application but a different protocol. - It is useful to show these to users to help them recognize version - conflicts between client and server. - Do not access on a second thread while in doNetwork. - */ - Array incompatibleServerList; - -private: - - class BroadcastMessage { - public: - void serialize(BinaryOutput& b) const {} - - void deserialize(BinaryInput& b) {} - }; - - /** - The client periodically checks servers to make sure they are still up - and to update its information about them. - */ - RealTime lastServerCheck; - - LightweightConduitRef net; - - /** - Returns an index in serverList of the server with the given address. - Returns -1 if there is none. Only checks IP addresses. - */ - int findServerListIndex(const NetAddress& addr) const { - for (int i = 0; i < serverList.size(); ++i) { - if (addr.ip() == serverList[i].address.ip()) { - return i; - } - } - - return -1; - } - - /** - Returns true if this discovery client has been initialized - and is functioning properly. - */ - bool ok() const { - return net->ok(); - } - - /** - Adds a server to the incompatible list if it is not already there. - */ - void addToIncompatibleList(const NetAddress& addr, uint32 p0, uint32 p1) { - const RealTime now = System::time(); - - bool alreadyHere = false; - - // Incorrect protocol; add to the incompatible list - for (int i = 0; i < incompatibleServerList.size(); ++i) { - IncompatibleServerDescription& server = incompatibleServerList[i]; - - if (server.address == addr) { - server.lastUpdateTime = now; - alreadyHere = true; - break; - } - } - - if (! alreadyHere) { - IncompatibleServerDescription server; - - server.lastUpdateTime = now; - server.address = addr; - server.protocolVersion[0] = p0; - server.protocolVersion[1] = p1; - - incompatibleServerList.append(server); - } - } - - /** - Connects to the specified server, reads its advertisement, - and adds it to the active server list. Returns true if the server - can be reached. - */ - bool readAdvertisement(const NetAddress& address) { - std::string hostname = address.toString(); - - RealTime TIMEOUT = 2.0; - - ReliableConduitRef server = ReliableConduit::create(address); - - if (! server->ok()) { - return false; - } - - AdType advertisement; - - // Read the advertisement - RealTime stopWaiting = System::time() + TIMEOUT; - bool timedOut = false; - - while (! server->messageWaiting() && ! timedOut && server->ok()) { - System::sleep(0.1); - timedOut = (System::time() > stopWaiting); - } - - if (timedOut) { - Log::common()->printf("Discovery: Timed out while reading advertisment from %s\n", - hostname.c_str()); - return false; - } - - - if (! server->ok()) { - Log::common()->printf("Discovery: Server %s dropped connection\n", hostname.c_str()); - return false; - } - - // Read the advertisement - debugAssert(server->messageWaiting()); - if (! server->receive(advertisement)) { - Log::common()->printf("Discovery: Server %s failed to send advertisement\n", hostname.c_str()); - return false; - } - - // Update existing server info or create a new entry - int index = findServerListIndex(address); - if (index == -1) { - index = serverList.size(); - serverList.resize(index + 1); - } - - // Update element index - advertisement.address = address; - serverList[index] = advertisement; - - return true; - } - - /** - Remove this address from our list if we previously - had a server there. - */ - void removeServer(const NetAddress& address) { - int index = findServerListIndex(address); - if (index > -1) { - serverList.fastRemove(index); - } - } - - /** - Tries to connect to the server through the addresses in the array. - */ - void addToServerList(const Array& addressArray) { - // Try to connect to each address listed - for (int a = addressArray.size() - 1; a >= 0; --a) { - const NetAddress& address = addressArray[a]; - - if (readAdvertisement(address)) { - // We've connected to the server - break; - } else { - removeServer(address); - } - } - } - - void checkRandomServer() { - if (serverList.size() >= 1) { - int index = iRandom(0, serverList.size() - 1); - - Array address; - address.append(serverList[index].address); - - // Remove this server - serverList.fastRemove(index); - - // Add it back with new info (or leave it removed if no response) - addToServerList(address); - } - } - -public: - - void init( - const DiscoverySettings* _settings) { - - Discovery::init(_settings); - - lastServerCheck = System::time(); - - net = LightweightConduit::create(settings->serverBroadcastPort, true, true); - - // Send announcement - NetAddress broadcast(NetworkDevice::instance()->broadcastAddressArray()[0], - settings->clientBroadcastPort); - BroadcastMessage tmp; - net->send(broadcast, CLIENT_BROADCAST_MESSAGE, tmp); - } - - /** Shut down the discovery client. */ - void cleanup() { - net = NULL; - } - - /** - Call this regularly (several times per second) to - update the server list. Not threadsafe-- you must not touch - the server list while this is running. This will not block. - */ - void doNetwork() { - if (net->messageWaiting()) { - NetAddress sender; - - switch (net->waitingMessageType()) { - case SERVER_SHUTDOWN_MESSAGE: - // Remove the server - net->receive(sender); - removeServer(sender); - break; - - case SERVER_BROADCAST_MESSAGE: - // Check the G3D protocol and the network protocol, then read the ad - DiscoveryServerAddressMessage msg(settings); - net->receive(sender, msg); - - if (msg.correctProtocol && (msg.address.size() > 0)) { - // Add the actual return address as the first one to be tried. - msg.address.append(NetAddress(sender.ip(), msg.address[0].port())); - - addToServerList(msg.address); - - } else { - - addToIncompatibleList( - sender, - msg.serverProtocolVersion[0], - msg.serverProtocolVersion[1]); - } - break; - } - } - - // Periodically re-check servers in the list to see if they crashed - // (if they shut down, they should have broadcast a shut down message). - RealTime now = System::time(); - const RealTime UPDATE_TIME_INTERVAL = 30; - - if (now > lastServerCheck + UPDATE_TIME_INTERVAL) { - lastServerCheck = now; - checkRandomServer(); - } - } -}; - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/EqualsTrait.h b/externals/g3dlite/G3D.lib/include/G3D/EqualsTrait.h deleted file mode 100644 index acf17615b45..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/EqualsTrait.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - @file EqualsTrait.h - - @maintainer Morgan McGuire, morgan@cs.williams.edu - @created 2008-10-01 - @edited 2008-10-01 - Copyright 2000-2008, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_EQUALSTRAIT_H -#define G3D_EQUALSTRAIT_H - -#include "G3D/platform.h" - -/** Default implementation of EqualsTrait. - @see G3D::Table for specialization requirements. -*/ -template struct EqualsTrait { - static bool equals(const Key& a, const Key& b) { - return a == b; - } -}; - -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/G3D.h b/externals/g3dlite/G3D.lib/include/G3D/G3D.h deleted file mode 100644 index 42ab18e2c24..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/G3D.h +++ /dev/null @@ -1,150 +0,0 @@ -/** - @file graphics3D.h - - This header includes all of the graphics3D libraries in - appropriate namespaces. - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2001-08-25 - @edited 2008-11-01 - - Copyright 2000-2008, Morgan McGuire. - All rights reserved. -*/ - -#ifndef G3D_GRAPHICS3D_H -#define G3D_GRAPHICS3D_H - -#define NOMINMAX 1 -#ifdef min - #undef min -#endif -#ifdef max - #undef max -#endif - -#include "G3D/platform.h" -#include "G3D/Array.h" -#include "G3D/Queue.h" -#include "G3D/Crypto.h" -#include "G3D/format.h" -#include "G3D/Vector2.h" -#include "G3D/Vector3.h" -#include "G3D/Vector4.h" -#include "G3D/Color1.h" -#include "G3D/Color3.h" -#include "G3D/Color4.h" -#include "G3D/Matrix2.h" -#include "G3D/Matrix3.h" -#include "G3D/Matrix4.h" -#include "G3D/CoordinateFrame.h" -#include "G3D/PhysicsFrame.h" -#include "G3D/Plane.h" -#include "G3D/Line.h" -#include "G3D/Ray.h" -#include "G3D/Sphere.h" -#include "G3D/Box.h" -#include "G3D/AABox.h" -#include "G3D/WrapMode.h" -#include "G3D/Cone.h" -#include "G3D/Quat.h" -#include "G3D/stringutils.h" -#include "G3D/prompt.h" -#include "G3D/Table.h" -#include "G3D/Set.h" -#include "G3D/GUniqueID.h" -#include "G3D/BinaryFormat.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/debug.h" -#include "G3D/G3DGameUnits.h" -#include "G3D/g3dmath.h" -#include "G3D/uint128.h" -#include "G3D/fileutils.h" -#include "G3D/ReferenceCount.h" - -template struct HashTrait< G3D::ReferenceCountedPointer > { - static size_t hashCode(G3D::ReferenceCountedPointer key) { return reinterpret_cast( key.pointer() ); } -}; - -#include "G3D/GImage.h" -#include "G3D/CollisionDetection.h" -#include "G3D/Log.h" -#include "G3D/serialize.h" -#include "G3D/TextInput.h" -#include "G3D/NetAddress.h" -#include "G3D/NetworkDevice.h" -#include "G3D/System.h" -#include "G3D/splinefunc.h" -#include "G3D/Spline.h" -#include "G3D/UprightFrame.h" -#include "G3D/LineSegment.h" -#include "G3D/Capsule.h" -#include "G3D/Cylinder.h" -#include "G3D/Triangle.h" -#include "G3D/Color3uint8.h" -#include "G3D/Color4uint8.h" -#include "G3D/Vector2int16.h" -#include "G3D/Vector3int16.h" -#include "G3D/Vector3int32.h" -#include "G3D/Vector4int8.h" -#include "G3D/ConvexPolyhedron.h" -#include "G3D/Discovery.h" -#include "G3D/MeshAlg.h" -#include "G3D/vectorMath.h" -#include "G3D/Rect2D.h" -#include "G3D/GCamera.h" -#include "G3D/GLight.h" -#include "G3D/AABSPTree.h" -#include "G3D/PointAABSPTree.h" -#include "G3D/TextOutput.h" -#include "G3D/MeshBuilder.h" -#include "G3D/Stopwatch.h" -#include "G3D/AtomicInt32.h" -#include "G3D/GThread.h" -#include "G3D/ThreadSet.h" -#include "G3D/RegistryUtil.h" -#include "G3D/AnyVal.h" -#include "G3D/PointHashGrid.h" -#include "G3D/Map2D.h" -#include "G3D/Image1.h" -#include "G3D/Image1uint8.h" -#include "G3D/Image3.h" -#include "G3D/Image3uint8.h" -#include "G3D/Image4.h" -#include "G3D/Image4uint8.h" -#include "G3D/filter.h" -#include "G3D/WeakCache.h" -#include "G3D/Pointer.h" -#include "G3D/Matrix.h" -#include "G3D/ImageFormat.h" - -#ifdef _MSC_VER -# pragma comment(lib, "zlib") -# pragma comment(lib, "ws2_32") -# pragma comment(lib, "winmm") -# pragma comment(lib, "imagehlp") -# pragma comment(lib, "gdi32") -# pragma comment(lib, "user32") -# pragma comment(lib, "kernel32") -# pragma comment(lib, "version") -# pragma comment(lib, "advapi32") -# pragma comment(lib, "png") -# pragma comment(lib, "jpeg") -# pragma comment(lib, "zip") -# ifdef _DEBUG - // Don't link against G3D when building G3D itself. -# ifndef G3D_BUILDING_LIBRARY_DLL -# pragma comment(lib, "G3Dd.lib") -# endif -# else - // Don't link against G3D when building G3D itself. -# ifndef G3D_BUILDING_LIBRARY_DLL -# pragma comment(lib, "G3D.lib") -# endif -# endif -#endif - -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/G3DAll.h b/externals/g3dlite/G3D.lib/include/G3D/G3DAll.h deleted file mode 100644 index feba3d6d390..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/G3DAll.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - @file G3DAll.h - - Includes all G3D and GLG3D files and uses the G3D namespace. - - This requires OpenGL and SDL headers. If you don't want all of this, - #include separately. - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2002-01-01 - @edited 2006-08-13 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_G3DALL_H -#define G3D_G3DALL_H - -#include "G3D/G3D.h" -#include "GLG3D/GLG3D.h" - -using namespace G3D; - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/G3DGameUnits.h b/externals/g3dlite/G3D.lib/include/G3D/G3DGameUnits.h deleted file mode 100644 index bc4c873f290..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/G3DGameUnits.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - @file G3DGameUnits.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - @created 2002-10-05 - @edited 2006-11-10 - */ - -#ifndef G3D_GAMEUNITS_H -#define G3D_GAMEUNITS_H - -#include "G3D/platform.h" - -namespace G3D { -/** - Time, in seconds. - */ -typedef double GameTime; -typedef double SimTime; - -/** - Actual wall clock time in seconds. - */ -typedef double RealTime; - -enum AMPM {AM, PM}; - -enum {SECOND=1, MINUTE=60, HOUR = 60*60, DAY=24*60*60, SUNRISE=24*60*60/4, SUNSET=24*60*60*3/4, MIDNIGHT=0, METER=1, KILOMETER=1000}; - -#define CENTIMETER (0.01) -#define DECIMETER (0.1) - -/** - Converts a 12 hour clock time into the number of seconds since - midnight. Note that 12:00 PM is noon and 12:00 AM is midnight. - - Example: toSeconds(10, 00, AM) - */ -SimTime toSeconds(int hour, int minute, double seconds, AMPM ap); -SimTime toSeconds(int hour, int minute, AMPM ap); - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/GCamera.h b/externals/g3dlite/G3D.lib/include/G3D/GCamera.h deleted file mode 100644 index 4dfa500883b..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/GCamera.h +++ /dev/null @@ -1,294 +0,0 @@ -/** - @file GCamera.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2005-07-20 - @edited 2007-07-24 -*/ - -#ifndef G3D_GCamera_H -#define G3D_GCamera_H - -#include "G3D/platform.h" -#include "G3D/CoordinateFrame.h" -#include "G3D/Vector3.h" -#include "G3D/Plane.h" -#include "G3D/debugAssert.h" - -namespace G3D { - -class Matrix4; -class Rect2D; - -/** - Abstraction of a pinhole camera. - - The area a camera sees is called a frustum. It is bounded by the near plane, the far plane, and the sides - of the view frame projected into the scene. It has the shape of a pyramid with the top cut off. - - Cameras can project points from 3D to 2D. The "unit" projection matches OpenGL. It maps the entire view frustum - to a cube of unit radius (i.e., edges of length 2) centered at the origin. The non-unit projection then maps - that cube to the specified pixel viewport in X and Y and the range [0, 1] in Z. The projection is reversable - as long as the projected Z value is known. - - All viewport arguments are the pixel bounds of the viewport-- e.g., - RenderDevice::viewport(). - */ -class GCamera { - -public: - /** - Stores the direction of the field of view - */ - enum FOVDirection {HORIZONTAL, VERTICAL}; - -private: - - - /** field of view (in radians) */ - float m_fieldOfView; - - /** Clipping plane, *not* imaging plane. Negative numbers. */ - float m_nearPlaneZ; - - /** Negative */ - float m_farPlaneZ; - - /** Stores the camera's location and orientation */ - CoordinateFrame m_cframe; - - /** Horizontal or Vertical */ - FOVDirection m_direction; - -public: - - class Frustum { - public: - class Face { - public: - /** Counter clockwise indices into vertexPos */ - int vertexIndex[4]; - - /** The plane containing the face. */ - Plane plane; - }; - - /** The vertices, in homogeneous space. If w == 0, - a vertex is at infinity. */ - Array vertexPos; - - /** The faces in the frustum. When the - far plane is at infinity, there are 5 faces, - otherwise there are 6. The faces are in the order - N,R,L,B,T,[F]. - */ - Array faceArray; - }; - - GCamera(); - - virtual ~GCamera(); - - /** Returns the current coordinate frame */ - const CoordinateFrame& coordinateFrame() const { - return m_cframe; - } - - /** Sets c to the camera's coordinate frame */ - void getCoordinateFrame(CoordinateFrame& c) const; - - /** Sets a new coordinate frame for the camera */ - void setCoordinateFrame(const CoordinateFrame& c); - - /** Sets P equal to the camera's projection matrix */ - void getProjectUnitMatrix(const Rect2D& viewport, Matrix4& P) const; - - /** Converts projected points from OpenGL standards - (-1, 1) to normal 3D coordinate standards (0, 1) */ - Vector3 convertFromUnitToNormal(const Vector3& in, const Rect2D& viewport) const; - - /** - Sets the vertical field of view, in radians. The - initial angle is toRadians(55). Must specify the direction of the angle - */ - void setFieldOfView(float angle, FOVDirection direction); - - /** Returns the current field of view angle and direction */ - inline void getFieldOfView(float& angle, FOVDirection& direction) const { - angle = m_fieldOfView; - direction = m_direction; - } - - /** - Projects a world space point onto a width x height screen. The - returned coordinate uses pixmap addressing: x = right and y = - down. The resulting z value is 0 at the near plane, 1 at the far plane, - and is a linear compression of unit cube projection. - - If the point is behind the camera, Vector3::inf() is returned. - */ - Vector3 project(const G3D::Vector3& point, - const class Rect2D& viewport) const; - - /** - Projects a world space point onto a unit cube. The resulting - x,y,z values range between -1 and 1, where z is -1 - at the near plane and 1 at the far plane and varies hyperbolically in between. - - If the point is behind the camera, Vector3::inf() is returned. - */ - Vector3 projectUnit(const G3D::Vector3& point, - const class Rect2D& viewport) const; - - /** - Gives the world-space coordinates of screen space point v, where - v.x is in pixels from the left, v.y is in pixels from - the top, and v.z is on the range 0 (near plane) to 1 (far plane). - */ - Vector3 unproject(const Vector3& v, const Rect2D& viewport) const; - - /** - Gives the world-space coordinates of unit cube point v, where - v varies from -1 to 1 on all axes. The unproject first - transforms the point into a pixel location for the viewport, then calls unproject - */ - Vector3 unprojectUnit(const Vector3& v, const Rect2D& viewport) const; - - /** - Returns the pixel area covered by a shape of the given - world space area at the given z value (z must be negative). - */ - float worldToScreenSpaceArea(float area, float z, const class Rect2D& viewport) const; - - /** - Returns the world space 3D viewport corners. These - are at the near clipping plane. The corners are constructed - from the nearPlaneZ, viewportWidth, and viewportHeight. - "left" and "right" are from the GCamera's perspective. - */ - void getNearViewportCorners(const class Rect2D& viewport, - Vector3& outUR, Vector3& outUL, - Vector3& outLL, Vector3& outLR) const; - - /** - Returns the world space 3D viewport corners. These - are at the Far clipping plane. The corners are constructed - from the nearPlaneZ, farPlaneZ, viewportWidth, and viewportHeight. - "left" and "right" are from the GCamera's perspective. - */ - void getFarViewportCorners(const class Rect2D& viewport, - Vector3& outUR, Vector3& outUL, - Vector3& outLL, Vector3& outLR) const; - - /** - Returns the image plane depth, assumes imagePlane - is the same as the near clipping plane. - returns a positive number. - */ - float imagePlaneDepth() const; - - /** - Returns the world space ray passing through the center of pixel - (x, y) on the image plane. The pixel x and y axes are opposite - the 3D object space axes: (0,0) is the upper left corner of the screen. - They are in viewport coordinates, not screen coordinates. - - The ray origin is at the origin. To start it at the image plane, - move it forward by imagePlaneDepth/ray.direction.z - - Integer (x, y) values correspond to - the upper left corners of pixels. If you want to cast rays - through pixel centers, add 0.5 to x and y. - */ - Ray worldRay( - float x, - float y, - const class Rect2D& viewport) const; - - /** - Returns a negative z-value. - */ - inline float nearPlaneZ() const { - return m_nearPlaneZ; - } - - /** - Returns a negative z-value. - */ - inline float farPlaneZ() const { - return m_farPlaneZ; - } - - /** - Sets a new value for the far clipping plane - Expects a negative value - */ - inline void setFarPlaneZ(float z) { - debugAssert(z < 0); - m_farPlaneZ = z; - } - - /** - Sets a new value for the near clipping plane - Expects a negative value - */ - inline void setNearPlaneZ(float z) { - debugAssert(z < 0); - m_nearPlaneZ = z; - } - - /** - Returns the camera space width of the viewport at the near plane. - */ - float viewportWidth(const class Rect2D& viewport) const; - - /** - Returns the camera space height of the viewport at the near plane. - */ - float viewportHeight(const class Rect2D& viewport) const; - - void setPosition(const Vector3& t); - - /** Rotate the camera in place to look at the target. Does not - persistently look at that location when the camera moves; - i.e., if you move the camera and still want it to look at the - old target, you must call lookAt again after moving the - camera.)*/ - void lookAt(const Vector3& position, const Vector3& up = Vector3::unitY()); - - /** - Returns the clipping planes of the frustum, in world space. - The planes have normals facing into the view frustum. - - The plane order is guaranteed to be: - Near, Right, Left, Top, Bottom, [Far] - - If the far plane is at infinity, the resulting array will have - 5 planes, otherwise there will be 6. - - The viewport is used only to determine the aspect ratio of the screen; the - absolute dimensions and xy values don't matter. - */ - void getClipPlanes - ( - const Rect2D& viewport, - Array& outClip) const; - - /** - Returns the world space view frustum, which is a truncated pyramid describing - the volume of space seen by this camera. - */ - void frustum(const Rect2D& viewport, GCamera::Frustum& f) const; - - GCamera::Frustum frustum(const Rect2D& viewport) const; - - /** Read and Write camera parameters */ - void serialize(class BinaryOutput& bo) const; - void deserialize(class BinaryInput& bi); - -}; - -} // namespace G3D - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/GImage.h b/externals/g3dlite/G3D.lib/include/G3D/GImage.h deleted file mode 100644 index 12003514d6a..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/GImage.h +++ /dev/null @@ -1,550 +0,0 @@ -/** - @file GImage.h - - See G3D::GImage for details. - - @cite JPEG compress/decompressor is the IJG library, used in accordance with their license. - @cite JPG code by John Chisholm, using the IJG Library - @cite TGA code by Morgan McGuire - @cite BMP code by John Chisholm, based on code by Edward "CGameProgrammer" Resnick mailto:cgp@gdnmail.net at ftp://ftp.flipcode.com/cotd/LoadPicture.txt - @cite PCX format described in the ZSOFT PCX manual http://www.nist.fss.ru/hr/doc/spec/pcx.htm#2 - @cite PNG compress/decompressor is the libpng library, used in accordance with their license. - @cite PPM code by Morgan McGuire based on http://netpbm.sourceforge.net/doc/ppm.html - - @maintainer Morgan McGuire, morgan@graphics3d.com - @created 2002-05-27 - @edited 2007-01-31 - - Copyright 2000-2007, Morgan McGuire. - All rights reserved. - - */ - -#ifndef G3D_GIMAGE_H -#define G3D_GIMAGE_H - -#include "G3D/platform.h" -#include -#include "G3D/Array.h" -#include "G3D/g3dmath.h" -#include "G3D/stringutils.h" -#include "G3D/Color1uint8.h" -#include "G3D/Color3uint8.h" -#include "G3D/Color4uint8.h" - -namespace G3D { -class BinaryInput; -class BinaryOutput; -/** - Interface to image compression & file formats. - - Supported formats (decode and encode): Color JPEG, PNG, (Uncompressed)TGA 24, (Uncompressed)TGA 32, BMP 1, BMP 4, BMP 8, BMP 24, PPM (P6), and PPM ASCII (P1, P2, P3). - 8-bit paletted PCX, 24-bit PCX, and ICO are supported for decoding only. - - Sample usage: - -

-    #include "graphics3D.h"
-
-    // Loading from disk:
-    G3D::GImage im1 = G3D::GImage("test.jpg");
-    
-    // Loading from memory:
-    G3D::GImage im2 = G3D::GImage(data, length);
-
-    // im.pixel is a pointer to RGB color data.  If you want
-    // an alpha channel, call RGBtoRGBA or RGBtoARGB for
-    // conversion.
-
-    // Saving to memory:
-    G3D::GImage im3 = G3D::GImage(width, height);
-    // (Set the pixels of im3...) 
-    uint8* data2;
-    int    len2;
-    im3.encode(G3D::GImage::JPEG, data2, len2);
-
-    // Saving to disk
-    im3.save("out.jpg");
-  
- - The free Image Magick Magick Wand API - (http://www.imagemagick.org/www/api/magick_wand.html) provides a more powerful - API for image manipulation and wider set of image load/save formats. It is - recommended over GImage (we don't include it directly in G3D because their license - is more restrictive than the BSD one). - - */ -class GImage { -private: - uint8* _byte; - -public: - - class Error { - public: - Error( - const std::string& reason, - const std::string& filename = "") : - reason(reason), filename(filename) {} - - std::string reason; - std::string filename; - }; - - enum Format {JPEG, BMP, TGA, PCX, ICO, PNG, PPM_ASCII, PPM, AUTODETECT, UNKNOWN}; - - int width; - int height; - - /** - The number of channels; either 3 (RGB) or 4 (RGBA) - */ - int channels; - - inline const uint8* byte() const { - return _byte; - } - - /** Returns a pointer to the upper left pixel - as Color3uint8. - */ - inline const Color3uint8* pixel3() const { - debugAssertM(channels == 3, format("Tried to call GImage::pixel3 on an image with %d channels", channels)); - return (Color3uint8*)_byte; - } - - /** Returns a pointer to the upper left pixel - as Color4uint8. - */ - inline const Color4uint8* pixel4() const { - debugAssertM(channels == 4, format("Tried to call GImage::pixel4 on an image with %d channels", channels)); - return (Color4uint8*)_byte; - } - - inline const Color1uint8* pixel1() const { - debugAssertM(channels == 1, format("Tried to call GImage::pixel1 on an image with %d channels", channels)); - return (Color1uint8*)_byte; - } - - inline Color1uint8* pixel1() { - debugAssertM(channels == 1, format("Tried to call GImage::pixel1 on an image with %d channels", channels)); - return (Color1uint8*)_byte; - } - - /** Returns the pixel at (x, y), where (0,0) is the upper left. */ - inline const Color1uint8& pixel1(int x, int y) const { - debugAssert(x >= 0 && x < width); - debugAssert(y >= 0 && y < height); - return pixel1()[x + y * width]; - } - - /** Returns the pixel at (x, y), where (0,0) is the upper left. */ - inline Color1uint8& pixel1(int x, int y) { - debugAssert(x >= 0 && x < width); - debugAssert(y >= 0 && y < height); - return pixel1()[x + y * width]; - } - - /** Returns the pixel at (x, y), where (0,0) is the upper left. */ - inline const Color3uint8& pixel3(int x, int y) const { - debugAssert(x >= 0 && x < width); - debugAssert(y >= 0 && y < height); - return pixel3()[x + y * width]; - } - - inline Color3uint8& pixel3(int x, int y) { - debugAssert(x >= 0 && x < width); - debugAssert(y >= 0 && y < height); - return pixel3()[x + y * width]; - } - - /** Returns the pixel at (x, y), where (0,0) is the upper left. */ - inline const Color4uint8& pixel4(int x, int y) const { - debugAssert(x >= 0 && x < width); - debugAssert(y >= 0 && y < height); - return pixel4()[x + y * width]; - } - - inline Color4uint8& pixel4(int x, int y) { - debugAssert(x >= 0 && x < width); - debugAssert(y >= 0 && y < height); - return pixel4()[x + y * width]; - } - - inline uint8* byte() { - return _byte; - } - - inline Color3uint8* pixel3() { - debugAssert(channels == 3); - return (Color3uint8*)_byte; - } - - inline Color4uint8* pixel4() { - debugAssert(channels == 4); - return (Color4uint8*)_byte; - } - -private: - - void encodeBMP( - BinaryOutput& out) const; - - /** - The TGA file will be either 24- or 32-bit depending - on the number of channels. - */ - void encodeTGA( - BinaryOutput& out) const; - - /** - Converts this image into a JPEG - */ - void encodeJPEG( - BinaryOutput& out) const; - - /** - Converts this image into a JPEG - */ - void encodePNG( - BinaryOutput& out) const; - - void encodePPM( - BinaryOutput& out) const; - - void encodePPMASCII( - BinaryOutput& out) const; - - void decodeTGA( - BinaryInput& input); - - void decodeBMP( - BinaryInput& input); - - void decodeJPEG( - BinaryInput& input); - - void decodePCX( - BinaryInput& input); - - void decodeICO( - BinaryInput& input); - - void decodePNG( - BinaryInput& input); - - void decodePPM( - BinaryInput& input); - - void decodePPMASCII( - BinaryInput& input); - - /** - Given [maybe] a filename, memory buffer, and [maybe] a format, - returns the most likely format of this file. - */ - static Format resolveFormat( - const std::string& filename, - const uint8* data, - int dataLen, - Format maybeFormat); - - void _copy( - const GImage& other); - -public: - static Format resolveFormat(const std::string& filename); - - GImage() { - width = height = channels = 0; - _byte = NULL; - } - - /** - Load an encoded image from disk and decode it. - Throws GImage::Error if something goes wrong. - */ - GImage( - const std::string& filename, - Format format = AUTODETECT); - - /** - Decodes an image stored in a buffer. - */ - GImage( - const unsigned char*data, - int length, - Format format = AUTODETECT); - - /** - Create an empty image of the given size. - */ - GImage( - int width, - int height, - int channels = 3); - - GImage( - const GImage& other); - - GImage& operator=(const GImage& other); - - /** - Returns a new GImage that has 4 channels. RGB is - taken from this GImage and the alpha from the red - channel of the supplied image. The new GImage is passed - as a reference parameter for speed. - */ - void insertRedAsAlpha(const GImage& alpha, GImage& output) const; - - GImage G3D_DEPRECATED insertRedAsAlpha(const GImage& alpha) const; - - /** - Returns a new GImage with 3 channels, removing - the alpha channel if there is one. The new GImage - is passed as a reference parameter for speed. - */ - void stripAlpha(GImage& output) const; - - GImage G3D_DEPRECATED stripAlpha() const; - - /** - Loads an image from disk (clearing the old one first). - */ - void load( - const std::string& filename, - Format format = AUTODETECT); - - /** - Frees memory and resets to a 0x0 image. - */ - void clear(); - - /** - Deallocates the pixels. - */ - virtual ~GImage(); - - /** - Resizes the internal buffer to (width x height) with the - number of channels specified. All data is set to 0 (black). - */ - void resize(int width, int height, int channels); - - - /** - Copies src sub-image data into dest at a certain offset. - The dest variable must already contain an image that is large - enough to contain the src sub-image at the specified offset. - Returns true on success and false if the src sub-image cannot - completely fit within dest at the specified offset. Both - src and dest must have the same number of channels. - */ - static bool pasteSubImage(GImage & dest, const GImage & src, - int destX, int destY, int srcX, int srcY, int srcWidth, int srcHeight); - - /** - creates dest from src sub-image data. - Returns true on success and false if the src sub-image - is not within src. - */ - static bool copySubImage(GImage & dest, const GImage & src, - int srcX, int srcY, int srcWidth, int srcHeight); - - void convertToRGBA(); - - void convertToRGB(); - - /** Averages color channels if they exist */ - void convertToL8(); - - /** - Returns true if format is supported. Format - should be an extension string (e.g. "BMP"). - */ - static bool supportedFormat( - const std::string& format); - - /** - Converts a string to an enum, returns UNKNOWN if not recognized. - */ - static Format stringToFormat( - const std::string& format); - - /** - Encode and save to disk. - */ - void save( - const std::string& filename, - Format format = AUTODETECT) const; - - /** - The caller must delete the returned buffer. - */ - void encode( - Format format, - uint8*& outData, - int& outLength) const; - - /** - Does not commit the BinaryOutput when done. - */ - void encode( - Format format, - BinaryOutput& out) const; - - /** - Decodes the buffer into this image. - @format Must be the correct format. - */ - void decode( - BinaryInput& input, - Format format); - - /** Returns the size of this object in bytes */ - int sizeInMemory() const; - - - /** Ok for in == out */ - static void R8G8B8_to_Y8U8V8(int width, int height, const uint8* in, uint8* out); - - /** Ok for in == out */ - static void Y8U8V8_to_R8G8B8(int width, int height, const uint8* in, uint8* out); - - /** - @param in RGB buffer of numPixels * 3 bytes - @param out Buffer of numPixels * 4 bytes - @param numPixels Number of RGB pixels to convert - */ - static void RGBtoRGBA( - const uint8* in, - uint8* out, - int numPixels); - - static void RGBtoARGB( - const uint8* in, - uint8* out, - int numPixels); - - /** Safe for in == out */ - static void RGBtoBGR( - const uint8* in, - uint8* out, - int numPixels); - - /** - Win32 32-bit HDC format. - */ - static void RGBtoBGRA( - const uint8* in, - uint8* out, - int numPixels); - - static void RGBAtoRGB( - const uint8* in, - uint8* out, - int numPixels); - /** - Uses the red channel of the second image as an alpha channel. - */ - static void RGBxRGBtoRGBA( - const uint8* colorRGB, - const uint8* alphaRGB, - uint8* out, - int numPixels); - - /** - Flips the image along the vertical axis. - Safe for in == out. - */ - static void flipRGBVertical( - const uint8* in, - uint8* out, - int width, - int height); - - static void flipRGBAVertical( - const uint8* in, - uint8* out, - int width, - int height); - - /** - Given a tangent space bump map, computes a new image where the - RGB channels are a tangent space normal map and the alpha channel - is the original bump map. Assumes the input image is tileable. - - In the resulting image, x = red = tangent, y = green = binormal, and z = blue = normal. - - Particularly useful as part of the idiom: -
- 	    GImage normal;
-	    computeNormalMap(GImage(filename), normal);
-	    return Texture::fromGImage(filename, normal);
-    
- - @param lowPassBump If true, a 9x9 filter of 1's is used to low-pass filter the elevations, - which produces better results for parallax mapping. - - @param scaleHeightByNz After computing normals, scale the height by |N.z|, a trick that - reduces texture swim in steep areas for parallax mapping. - - @param whiteHeightInPixels How high should the brightest input value be considered for purposes - of normal computation, compared to the horizontal and vertical size of a pixel. - A value of 255 means that a 255 x 255 bump image with a full black-to-white gradient will - produce a 45-degree ramp (this also results in "cubic" voxels). - A special (default) value of -1 means scale the effective white height so that it is equal - to the larger spatial dimension. - */ - static void computeNormalMap( - const class GImage& bump, - class GImage& normal, - float whiteHeightInPixels = -1.0f, - bool lowPassBump = false, - bool scaleHeightByNz = false); - - static void computeNormalMap( - int width, - int height, - int channels, - const uint8* src, - GImage& normal, - float whiteHeightInPixels, - bool lowPassBump, - bool scaleHeightByNz); - - /** - Bayer demosaicing using the filter proposed in - - HIGH-QUALITY LINEAR INTERPOLATION FOR DEMOSAICING OF BAYER-PATTERNED COLOR IMAGES - Henrique S. Malvar, Li-wei He, and Ross Cutler - - The filter wraps at the image boundaries. - - Assumes in != out. - */ - static void BAYER_G8B8_R8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out); - static void BAYER_G8R8_B8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out); - static void BAYER_R8G8_G8B8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out); - static void BAYER_B8G8_G8R8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out); - - /** Fast conversion; the output has 1/2 the size of the input in each direction. Assumes in != out. - See G3D::BAYER_G8B8_R8G8_to_R8G8B8_MHC for a much better result. */ - static void BAYER_G8B8_R8G8_to_Quarter_R8G8B8(int inWidth, int inHeight, const uint8* in, uint8* out); - - /** Attempt to undo fast conversion of G3D::BAYER_G8B8_R8G8_to_Quarter_R8G8B8; - the green channel will lose data. Assumes in != out - The input should have size 3 * inWidth * inHeight. The output should have size - 2 * inWidth * 2 * inHeight. - */ - static void Quarter_R8G8B8_to_BAYER_G8B8_R8G8(int inWidth, int inHeight, const uint8* in, uint8* out); - - /** Overwrites every pixel with one of the two colors in a checkerboard pattern. - The fields used from the two colors depend on the current number of channels in @a im. - */ - static void makeCheckerboard(GImage& im, int checkerSize = 1, const Color4uint8& color1 = Color4uint8(255,255,255,255), const Color4uint8& color2 = Color4uint8(0,0,0,255)); -}; - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/GLight.h b/externals/g3dlite/G3D.lib/include/G3D/GLight.h deleted file mode 100644 index b8fa7b54261..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/GLight.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - @file GLight.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-11-12 - @edited 2006-02-08 -*/ - -#ifndef G3D_GLIGHT_H -#define G3D_GLIGHT_H - -#include "G3D/platform.h" -#include "G3D/Vector4.h" -#include "G3D/Vector3.h" -#include "G3D/Color4.h" - -namespace G3D { - -/** - A light representation that closely follows the OpenGL light format. - */ -class GLight { -public: - /** World space position (for a directional light, w = 0 */ - Vector4 position; - - /** Direction in which the light faces, if a spot light. This is the "look vector" of the light source. */ - Vector3 spotDirection; - - /** In degrees. 180 = no cutoff (point/dir) >90 = spot light */ - float spotCutoff; - - /** Constant, linear, quadratic */ - float attenuation[3]; - - /** May be outside the range [0, 1] */ - Color3 color; - - /** If false, this light is ignored */ - bool enabled; - - /** If false, this light does not create specular highlights (useful when using negative lights). */ - bool specular; - - /** If false, this light does not create diffuse illumination (useful when rendering a specular-only pass). */ - bool diffuse; - - GLight(); - - /** @param toLight will be normalized */ - static GLight directional(const Vector3& toLight, const Color3& color, bool specular = true, bool diffuse = true); - - static GLight point(const Vector3& pos, const Color3& color, float constAtt = 1, float linAtt = 0, float quadAtt = 0.5f, bool specular = true, bool diffuse = true); - - /** @param pointDirection Will be normalized. Points in the direction that light propagates. - @param cutOffAngleDegrees Must be on the range [0, 90]. This is the angle from the point direction - to the edge of the light cone. - */ - static GLight spot(const Vector3& pos, const Vector3& pointDirection, float cutOffAngleDegrees, const Color3& color, float constAtt = 1, float linAtt = 0, float quadAtt = 0, bool specular = true, bool diffuse = true); - - /** Returns the sphere within which this light has some noticable effect. May be infinite. - @param cutoff The value at which the light intensity is considered negligible. */ - class Sphere effectSphere(float cutoff = 30.0f / 255) const; - - bool operator==(const GLight& other) const; - bool operator!=(const GLight& other) const; -}; - -} // namespace -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/GThread.h b/externals/g3dlite/G3D.lib/include/G3D/GThread.h deleted file mode 100644 index 63f1c235bda..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/GThread.h +++ /dev/null @@ -1,169 +0,0 @@ -/** - @file GThread.h - - @created 2005-09-22 - @edited 2007-01-31 - - */ - -#ifndef G3D_GTHREAD_H -#define G3D_GTHREAD_H - -#include "G3D/platform.h" -#include "G3D/ReferenceCount.h" -#include - -#ifndef G3D_WIN32 -# include -# include -#endif - - -namespace G3D { - -typedef ReferenceCountedPointer GThreadRef; - -/** - Platform independent thread implementation. You can either subclass and - override GThread::threadMain or call the create method with a method. - - Beware of reference counting and threads. If circular references exist between - GThread subclasses then neither class will ever be deallocated. Also, - dropping all pointers (and causing deallocation) of a GThread does NOT - stop the underlying process. - - @sa G3D::GMutex, G3D::AtomicInt32 -*/ -class GThread : public ReferenceCountedObject { -private: - // "Status" is a reserved work on FreeBSD - enum GStatus {STATUS_CREATED, STATUS_STARTED, STATUS_RUNNING, STATUS_COMPLETED}; - - // Not implemented on purpose, don't use - GThread(const GThread &); - GThread& operator=(const GThread&); - bool operator==(const GThread&); - -#ifdef G3D_WIN32 - static DWORD WINAPI internalThreadProc(LPVOID param); -#else - static void* internalThreadProc(void* param); -#endif //G3D_WIN32 - - volatile GStatus m_status; - - // Thread handle to hold HANDLE and pthread_t -#ifdef G3D_WIN32 - HANDLE m_handle; - HANDLE m_event; -#else - pthread_t m_handle; -#endif //G3D_WIN32 - - std::string m_name; - -public: - - GThread(const std::string& name); - - virtual ~GThread(); - - /** Constructs a basic GThread without requiring a subclass. - - @param proc The global or static function for the threadMain() */ - static GThreadRef create(const std::string& name, void (*proc)(void*), void* param); - - /** @deprecated use overload that accepts void* param */ - static GThreadRef create(const std::string& name, void (*proc)()); - - /** Starts the thread and executes threadMain(). Returns false if - the thread failed to start (either because it was already started - or because the OS refused).*/ - bool start(); - - /** Terminates the thread without notifying or - waiting for a cancelation point. */ - void terminate(); - - /** - Returns true if threadMain is currently executing. This will - only be set when the thread is actually running and might not - be set when start() returns. */ - bool running() const; - - /** True after start() has been called, even through the thread - may have already completed(), or be currently running().*/ - bool started() const; - - /** Returns true if the thread has exited. */ - bool completed() const; - - /** Waits for the thread to finish executing. */ - void waitForCompletion(); - - /** Returns thread name */ - inline const std::string& name() { - return m_name; - } - - /** Overriden by the thread implementor */ - virtual void threadMain() = 0; -}; - - -/** - Mutual exclusion lock used for synchronization. - @sa G3D::GThread, G3D::AtomicInt32 -*/ -class GMutex { -private: -# ifdef G3D_WIN32 - CRITICAL_SECTION m_handle; -# else - pthread_mutex_t m_handle; -# endif - - // Not implemented on purpose, don't use - GMutex(const GMutex &mlock); - GMutex &operator=(const GMutex &); - bool operator==(const GMutex&); - -public: - GMutex(); - ~GMutex(); - - /** Locks the mutex or blocks until available. */ - void lock(); - - /** Unlocks the mutex. */ - void unlock(); -}; - - -/** - Automatically locks while in scope. -*/ -class GMutexLock { -private: - GMutex* m; - - // Not implemented on purpose, don't use - GMutexLock(const GMutexLock &mlock); - GMutexLock &operator=(const GMutexLock &); - bool operator==(const GMutexLock&); - -public: - GMutexLock(GMutex* mutex) { - m = mutex; - m->lock(); - } - - ~GMutexLock() { - m->unlock(); - } -}; - - -} // namespace G3D - -#endif //G3D_GTHREAD_H diff --git a/externals/g3dlite/G3D.lib/include/G3D/GUniqueID.h b/externals/g3dlite/G3D.lib/include/G3D/GUniqueID.h deleted file mode 100644 index 44ec6e03405..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/GUniqueID.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - @file GUniqueID.h - @author Morgan McGuire, morgan@cs.williams.edu - */ -#ifndef G3D_GUNIQUEID_H -#define G3D_GUNIQUEID_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Table.h" - -namespace G3D { - -/** Globally unique identifiers. The probability of two different - programs generating the same value from UniqueID::create is - vanishingly small. - - UniqueIDs optionally contain a 10-bit application specific tag - that distinguishes their type. -*/ -class GUniqueID { -private: - - uint64 id; - -public: - - GUniqueID() : id(0) {} - - bool uninitialized() const { - return id == 0; - } - - uint16 tag() const { - return id >> 54; - } - - operator uint64() const { - return id; - } - - bool operator==(const GUniqueID& other) const { - return id == other.id; - } - - bool operator!=(const GUniqueID& other) const { - return id != other.id; - } - - void serialize(class BinaryOutput& b) const; - - void deserialize(class BinaryInput& b); - - void serialize(class TextOutput& t) const; - - void deserialize(class TextInput& t); - - /** Create a new ID */ - static GUniqueID create(uint16 tag = 0); -}; - -} // G3D - -/** For Table and Set */ -template<> struct HashTrait { - static size_t hashCode(G3D::GUniqueID id) { return (size_t)(G3D::uint64)id; } -}; - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/HashTrait.h b/externals/g3dlite/G3D.lib/include/G3D/HashTrait.h deleted file mode 100644 index 702903ff09b..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/HashTrait.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - @file HashTrait.h - - @maintainer Morgan McGuire, morgan@cs.williams.edu - @created 2008-10-01 - @edited 2008-10-01 - Copyright 2000-2008, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_HASHTRAIT_H -#define G3D_HASHTRAIT_H - -#include "G3D/platform.h" -#include "G3D/Crypto.h" -#include "G3D/g3dmath.h" -#include "G3D/uint128.h" - -/** Must be specialized for custom types. - @see G3D::Table for specialization requirements. -*/ -template struct HashTrait{}; - -template struct HashTrait { - static size_t hashCode(const void* k) { return reinterpret_cast(k); } -}; - -template <> struct HashTrait { - static size_t hashCode(int k) { return static_cast(k); } -}; - -template <> struct HashTrait { - static size_t hashCode(G3D::uint32 k) { return static_cast(k); } -}; - -template <> struct HashTrait { - static size_t hashCode(G3D::uint64 k) { return static_cast(k); } -}; - -template <> struct HashTrait { - static size_t hashCode(const std::string& k) { return static_cast(G3D::Crypto::crc32(k.c_str(), k.size())); } -}; - -template <> struct HashTrait { - // Use the FNV-1 hash (http://isthe.com/chongo/tech/comp/fnv/#FNV-1). - static size_t hashCode(G3D::uint128 key) { - static const G3D::uint128 FNV_PRIME_128(1 << 24, 0x159); - static const G3D::uint128 FNV_OFFSET_128(0xCF470AAC6CB293D2LL, 0xF52F88BF32307F8FLL); - - G3D::uint128 hash = FNV_OFFSET_128; - G3D::uint128 mask(0, 0xFF); - for (int i = 0; i < 16; ++i) { - hash *= FNV_PRIME_128; - hash ^= (mask & key); - key >>= 8; - } - - G3D::uint64 foldedHash = hash.hi ^ hash.lo; - return static_cast((foldedHash >> 32) ^ (foldedHash & 0xFFFFFFFF)); - } -}; - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Image1.h b/externals/g3dlite/G3D.lib/include/G3D/Image1.h deleted file mode 100644 index f0850710d2c..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Image1.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - @file Image1.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-01-31 - @edited 2007-01-31 -*/ - - -#ifndef G3D_IMAGE1_H -#define G3D_IMAGE1_H - -#include "G3D/platform.h" -#include "G3D/Map2D.h" -#include "G3D/Color1.h" -#include "G3D/GImage.h" - -namespace G3D { - -typedef ReferenceCountedPointer Image1Ref; - -/** - Luminance image with 32-bit floating point storage. - - See also G3D::Image1uint8, G3D::GImage. - */ -class Image1 : public Map2D { -public: - - typedef Image1 Type; - typedef Image1Ref Ref; - -protected: - - Image1(int w, int h, WrapMode wrap); - - void copyGImage(const class GImage& im); - void copyArray(const Color1* src, int w, int h); - void copyArray(const Color3* src, int w, int h); - void copyArray(const Color4* src, int w, int h); - void copyArray(const Color1uint8* src, int w, int h); - void copyArray(const Color3uint8* src, int w, int h); - void copyArray(const Color4uint8* src, int w, int h); - -public: - - const class ImageFormat* format() const; - - /** Creates an all-zero width x height image. */ - static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR); - - /** Creates a 0 x 0 image. */ - static Ref createEmpty(WrapMode wrap = WrapMode::ERROR); - - static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT); - - static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - - static Ref fromImage1uint8(const ReferenceCountedPointer& im); - - static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR); - - /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input, - it is stripped. */ - void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); - - /** Saves in any of the formats supported by G3D::GImage. */ - void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); -}; - -} // G3D - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Image1uint8.h b/externals/g3dlite/G3D.lib/include/G3D/Image1uint8.h deleted file mode 100644 index 7225ca35db8..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Image1uint8.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - @file Image1uint8.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-01-31 - @edited 2007-01-31 -*/ - -#ifndef G3D_IMAGE1UINT8_H -#define G3D_IMAGE1UINT8_H - -#include "G3D/platform.h" -#include "G3D/Map2D.h" -#include "G3D/Color1uint8.h" -#include "G3D/Color1.h" -#include "G3D/GImage.h" - -namespace G3D { - -typedef ReferenceCountedPointer Image1uint8Ref; - -/** - Compact storage for luminance 8-bit images. - - See also G3D::Image3, G3D::GImage - */ -class Image1uint8 : public Map2D { -public: - - typedef Image1uint8 Type; - typedef Image1uint8Ref Ref; - -protected: - - Image1uint8(int w, int h, WrapMode wrap); - - void copyGImage(const class GImage& im); - void copyArray(const Color1* src, int w, int h); - void copyArray(const Color3* src, int w, int h); - void copyArray(const Color4* src, int w, int h); - void copyArray(const Color1uint8* src, int w, int h); - void copyArray(const Color3uint8* src, int w, int h); - void copyArray(const Color4uint8* src, int w, int h); - -public: - - const class ImageFormat* format() const; - - /** Creates an all-zero width x height image. */ - static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR); - - /** Creates a 0 x 0 image. */ - static Ref createEmpty(WrapMode wrap = WrapMode::ERROR); - - static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT); - - static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR); - - static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - - static Ref fromImage1(const ReferenceCountedPointer& im); - static Ref fromImage3uint8(const ReferenceCountedPointer& im); - - /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input, - it is stripped. */ - void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); - - /** Saves in any of the formats supported by G3D::GImage. */ - void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); -}; - -} // G3D - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Image3.h b/externals/g3dlite/G3D.lib/include/G3D/Image3.h deleted file mode 100644 index c67669c1c5e..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Image3.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - @file Image3.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-01-31 - @edited 2007-01-31 -*/ - - -#ifndef G3D_IMAGE3_H -#define G3D_IMAGE3_H - -#include "G3D/platform.h" -#include "G3D/Map2D.h" -#include "G3D/Color3.h" -#include "G3D/GImage.h" - -namespace G3D { - -typedef ReferenceCountedPointer Image3Ref; - -/** - RGB image with 32-bit floating point storage for each channel. - - See also G3D::Image3uint8, G3D::GImage. - */ -class Image3 : public Map2D { -public: - - typedef Image3 Type; - typedef Image3Ref Ref; - -protected: - - Image3(int w, int h, WrapMode wrap); - - void copyGImage(const class GImage& im); - void copyArray(const Color1* src, int w, int h); - void copyArray(const Color3* src, int w, int h); - void copyArray(const Color4* src, int w, int h); - void copyArray(const Color1uint8* src, int w, int h); - void copyArray(const Color3uint8* src, int w, int h); - void copyArray(const Color4uint8* src, int w, int h); - -public: - - const class ImageFormat* format() const; - - /** Creates an all-zero width x height image. */ - static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR); - - /** Creates a 0 x 0 image. */ - static Ref createEmpty(WrapMode wrap = WrapMode::ERROR); - - static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT); - - static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - - static Ref fromImage3uint8(const ReferenceCountedPointer& im); - - static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR); - - /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input, - it is stripped. */ - void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); - - /** Saves in any of the formats supported by G3D::GImage. */ - void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); -}; - -} // G3D - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Image3uint8.h b/externals/g3dlite/G3D.lib/include/G3D/Image3uint8.h deleted file mode 100644 index 9ee1ef6678b..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Image3uint8.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - @file Image3uint8.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-01-31 - @edited 2007-01-31 -*/ - -#ifndef G3D_IMAGE3UINT8_H -#define G3D_IMAGE3UINT8_H - -#include "G3D/platform.h" -#include "G3D/Map2D.h" -#include "G3D/Color3uint8.h" -#include "G3D/Color3.h" -#include "G3D/GImage.h" - -namespace G3D { - -typedef ReferenceCountedPointer Image3uint8Ref; - -/** - Compact storage for RGB 8-bit per channel images. - - See also G3D::Image3, G3D::GImage - */ -class Image3uint8 : public Map2D { -public: - - typedef Image3uint8 Type; - typedef Image3uint8Ref Ref; - -protected: - - Image3uint8(int w, int h, WrapMode wrap); - - void copyGImage(const class GImage& im); - void copyArray(const Color1* src, int w, int h); - void copyArray(const Color3* src, int w, int h); - void copyArray(const Color4* src, int w, int h); - void copyArray(const Color1uint8* src, int w, int h); - void copyArray(const Color3uint8* src, int w, int h); - void copyArray(const Color4uint8* src, int w, int h); - -public: - - const class ImageFormat* format() const; - - /** Creates an all-zero width x height image. */ - static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR); - - - /** Creates a 0 x 0 image. */ - static Ref createEmpty(WrapMode wrap = WrapMode::ERROR); - - - static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT); - - static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR); - - static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - - static Ref fromImage3(const ReferenceCountedPointer& im); - static Ref fromImage1uint8(const ReferenceCountedPointer& im); - - /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input, - it is stripped. */ - void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); - - /** Saves in any of the formats supported by G3D::GImage. */ - void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); - - /** Extracts color channel 0 <= c <= 2 and returns it as a new monochrome image. */ - ReferenceCountedPointer getChannel(int c) const; -}; - -} // G3D - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Image4.h b/externals/g3dlite/G3D.lib/include/G3D/Image4.h deleted file mode 100644 index 04df43f9527..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Image4.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - @file Image4.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-01-31 - @edited 2007-01-31 -*/ - - -#ifndef G3D_IMAGE4_H -#define G3D_IMAGE4_H - -#include "G3D/platform.h" -#include "G3D/Map2D.h" -#include "G3D/Color4.h" -#include "G3D/GImage.h" - -namespace G3D { - -typedef ReferenceCountedPointer Image4Ref; - -/** - RGBA image with 32-bit floating point storage for each channel. - - Whenever a method needs to convert from RGB to ARGB, A=1 is assumed. - - See also G3D::Image4uint8, G3D::GImage. - */ -class Image4 : public Map2D { -public: - - typedef Image4 Type; - typedef Image4Ref Ref; - -protected: - - Image4(int w, int h, WrapMode wrap); - - void copyGImage(const class GImage& im); - void copyArray(const Color1* src, int w, int h); - void copyArray(const Color3* src, int w, int h); - void copyArray(const Color4* src, int w, int h); - void copyArray(const Color1uint8* src, int w, int h); - void copyArray(const Color3uint8* src, int w, int h); - void copyArray(const Color4uint8* src, int w, int h); - -public: - - const class ImageFormat* format() const; - - /** Creates an all-zero width x height image. */ - static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR); - - /** Creates a 0 x 0 image. */ - static Ref createEmpty(WrapMode wrap = WrapMode::ERROR); - - static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT); - - static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - - static Ref fromImage4uint8(const ReferenceCountedPointer& im); - - static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR); - - /** Loads from any of the file formats supported by G3D::GImage. */ - void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); - - /** Saves in any of the formats supported by G3D::GImage. */ - void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); -}; - -} // G3D - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Image4uint8.h b/externals/g3dlite/G3D.lib/include/G3D/Image4uint8.h deleted file mode 100644 index 11daf97c83c..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Image4uint8.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - @file Image4uint8.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-01-31 - @edited 2007-01-31 -*/ - -#ifndef G3D_IMAGE4UINT8_H -#define G3D_IMAGE4UINT8_H - -#include "G3D/platform.h" -#include "G3D/Map2D.h" -#include "G3D/Color4uint8.h" -#include "G3D/Color4.h" -#include "G3D/GImage.h" -#include "G3D/Image1uint8.h" - -namespace G3D { - -typedef ReferenceCountedPointer Image4uint8Ref; - -/** - Compact storage for RGBA 8-bit per channel images. - - See also G3D::Image4, G3D::GImage - */ -class Image4uint8 : public Map2D { -public: - - typedef Image4uint8 Type; - typedef Image4uint8Ref Ref; - -protected: - - Image4uint8(int w, int h, WrapMode wrap); - - void copyGImage(const class GImage& im); - void copyArray(const Color1* src, int w, int h); - void copyArray(const Color3* src, int w, int h); - void copyArray(const Color4* src, int w, int h); - void copyArray(const Color1uint8* src, int w, int h); - void copyArray(const Color3uint8* src, int w, int h); - void copyArray(const Color4uint8* src, int w, int h); - -public: - - const class ImageFormat* format() const; - - /** Creates an all-zero width x height image. */ - static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR); - - - /** Creates a 0 x 0 image. */ - static Ref createEmpty(WrapMode wrap = WrapMode::ERROR); - - - static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT); - - static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR); - - static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); - - static Ref fromImage4(const ReferenceCountedPointer& im); - - /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input, - it is stripped. */ - void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); - - /** Saves in any of the formats supported by G3D::GImage. */ - void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); - - /** Extracts color channel 0 <= c <= 3 and returns it as a new monochrome image. */ - ReferenceCountedPointer getChannel(int c) const; -}; - -} // G3D - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/ImageFormat.h b/externals/g3dlite/G3D.lib/include/G3D/ImageFormat.h deleted file mode 100644 index a1334fb1a5a..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/ImageFormat.h +++ /dev/null @@ -1,362 +0,0 @@ -/** - @file ImageFormat.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-05-23 - @edited 2008-07-17 -*/ - -#ifndef GLG3D_ImageFormat_H -#define GLG3D_ImageFormat_H - -#include "G3D/platform.h" -#include "G3D/Table.h" -#include "G3D/enumclass.h" - -namespace G3D { - -/** Information about common image formats. - Don't construct these; use the methods provided. - - For most formats, the number indicates the number of bits per channel and a suffix of "F" indicates - floating point. This does not hold for the YUV and DXT formats.*/ -class ImageFormat { -public: - - // Must update ImageFormat::name() when this enum changes. - enum Code { - CODE_NONE = -1, - CODE_L8, - CODE_L16, - CODE_L16F, - CODE_L32F, - - CODE_A8, - CODE_A16, - CODE_A16F, - CODE_A32F, - - CODE_LA4, - CODE_LA8, - CODE_LA16, - CODE_LA16F, - CODE_LA32F, - - CODE_RGB5, - CODE_RGB5A1, - CODE_RGB8, - CODE_RGB10, - CODE_RGB10A2, - CODE_RGB16, - CODE_RGB16F, - CODE_RGB32F, - - CODE_ARGB8, - CODE_BGR8, - - CODE_RGBA8, - CODE_RGBA16, - CODE_RGBA16F, - CODE_RGBA32F, - - CODE_BAYER_RGGB8, - CODE_BAYER_GRBG8, - CODE_BAYER_GBRG8, - CODE_BAYER_BGGR8, - CODE_BAYER_RGGB32F, - CODE_BAYER_GRBG32F, - CODE_BAYER_GBRG32F, - CODE_BAYER_BGGR32F, - - CODE_HSV8, - CODE_HSV32F, - - CODE_YUV420_PLANAR, - CODE_YUV422, - CODE_YUV444, - - CODE_RGB_DXT1, - CODE_RGBA_DXT1, - CODE_RGBA_DXT3, - CODE_RGBA_DXT5, - - CODE_DEPTH16, - CODE_DEPTH24, - CODE_DEPTH32, - CODE_DEPTH32F, - - CODE_STENCIL1, - CODE_STENCIL4, - CODE_STENCIL8, - CODE_STENCIL16, - - CODE_DEPTH24_STENCIL8, - - CODE_NUM - }; - - enum ColorSpace { - COLOR_SPACE_NONE, - COLOR_SPACE_RGB, - COLOR_SPACE_HSV, - COLOR_SPACE_YUV - }; - - enum BayerPattern { - BAYER_PATTERN_NONE, - BAYER_PATTERN_RGGB, - BAYER_PATTERN_GRBG, - BAYER_PATTERN_GBRG, - BAYER_PATTERN_BGGR - }; - - /** Number of channels (1 for a depth texture). */ - int numComponents; - bool compressed; - - /** Useful for serializing. */ - Code code; - - ColorSpace colorSpace; - - /** If this is a Bayer format, what is the pattern. */ - BayerPattern bayerPattern; - - /** The OpenGL format equivalent to this one, e.g, GL_RGB8 Zero if there is no equivalent. This is actually a GLenum */ - int openGLFormat; - - /** The OpenGL base format equivalent to this one (e.g., GL_RGB, GL_ALPHA). Zero if there is no equivalent. */ - int openGLBaseFormat; - - int luminanceBits; - - /** Number of bits per pixel storage for alpha values; Zero for compressed textures and non-RGB. */ - int alphaBits; - - /** Number of bits per pixel storage for red values; Zero for compressed textures and non-RGB. */ - int redBits; - - /** Number of bits per pixel storage for green values; Zero for compressed textures and non-RGB. */ - int greenBits; - - /** Number of bits per pixel storage for blue values; Zero for compressed textures and non-RGB. */ - int blueBits; - - /** Number of bits per pixel */ - int stencilBits; - - /** Number of depth bits (for depth textures; e.g. shadow maps) */ - int depthBits; - - /** Amount of CPU memory per pixel when packed into an array, discounting any end-of-row padding. */ - int cpuBitsPerPixel; - - /** Amount of CPU memory per pixel when packed into an array, discounting any end-of-row padding. @deprecated Use cpuBitsPerPixel*/ - int packedBitsPerTexel; - - /** - Amount of GPU memory per pixel on most graphics cards, for formats supported by OpenGL. This is - only an estimate--the actual amount of memory may be different on your actual card. - - This may be greater than the sum of the per-channel bits - because graphics cards need to pad to the nearest 1, 2, or - 4 bytes. - */ - int openGLBitsPerPixel; - - /** @deprecated Use openGLBitsPerPixel */ - int hardwareBitsPerTexel; - - /** The OpenGL bytes format of the data buffer used with this texture format, e.g., GL_UNSIGNED_BYTE */ - int openGLDataFormat; - - /** True if there is no alpha channel for this texture. */ - bool opaque; - - /** True if the bit depths specified are for float formats. */ - bool floatingPoint; - - /** Human readable name of this texture.*/ - std::string name() const; - -private: - - ImageFormat( - int numComponents, - bool compressed, - int glFormat, - int glBaseFormat, - int luminanceBits, - int alphaBits, - int redBits, - int greenBits, - int blueBits, - int depthBits, - int stencilBits, - int hardwareBitsPerTexel, - int packedBitsPerTexel, - int glDataFormat, - bool opaque, - bool floatingPoint, - Code code, - ColorSpace colorSpace, - BayerPattern bayerPattern = BAYER_PATTERN_NONE); - -public: - - static const ImageFormat* L8(); - - static const ImageFormat* L16(); - - static const ImageFormat* L16F(); - - static const ImageFormat* L32F(); - - static const ImageFormat* A8(); - - static const ImageFormat* A16(); - - static const ImageFormat* A16F(); - - static const ImageFormat* A32F(); - - static const ImageFormat* LA4(); - - static const ImageFormat* LA8(); - - static const ImageFormat* LA16(); - - static const ImageFormat* LA16F(); - - static const ImageFormat* LA32F(); - - static const ImageFormat* BGR8(); - - static const ImageFormat* RGB5(); - - static const ImageFormat* RGB5A1(); - - static const ImageFormat* RGB8(); - - static const ImageFormat* RGB10(); - - static const ImageFormat* RGB10A2(); - - static const ImageFormat* RGB16(); - - static const ImageFormat* RGB16F(); - - static const ImageFormat* RGB32F(); - - static const ImageFormat* RGBA8(); - - static const ImageFormat* RGBA16(); - - static const ImageFormat* RGBA16F(); - - static const ImageFormat* RGBA32F(); - - static const ImageFormat* RGB_DXT1(); - - static const ImageFormat* RGBA_DXT1(); - - static const ImageFormat* RGBA_DXT3(); - - static const ImageFormat* RGBA_DXT5(); - - static const ImageFormat* DEPTH16(); - - static const ImageFormat* DEPTH24(); - - static const ImageFormat* DEPTH32(); - - static const ImageFormat* DEPTH32F(); - - static const ImageFormat* STENCIL1(); - - static const ImageFormat* STENCIL4(); - - static const ImageFormat* STENCIL8(); - - static const ImageFormat* STENCIL16(); - - static const ImageFormat* DEPTH24_STENCIL8(); - - static const ImageFormat* YUV420_PLANAR(); - - static const ImageFormat* YUV422(); - - static const ImageFormat* YUV444(); - - /** - NULL pointer; indicates that the G3D::Texture class should choose - either RGBA8 or RGB8 depending on the presence of an alpha channel - in the input. - */ - static const ImageFormat* AUTO() { return NULL; } - - /** Returns DEPTH16, DEPTH24, or DEPTH32 according to the bits - specified. You can use "glGetInteger(GL_DEPTH_BITS)" to match - the screen's format.*/ - static const ImageFormat* depth(int depthBits = 24); - - /** Returns STENCIL1, STENCIL4, STENCIL8 or STENCIL16 according to the bits - specified. You can use "glGetInteger(GL_STENCIL_BITS)" to match - the screen's format.*/ - static const ImageFormat* stencil(int bits = 8); - - /** Returns the matching ImageFormat* identified by the Code. May return NULL - if this format's code is reserved but not yet implemented by G3D. */ - static const ImageFormat* fromCode(ImageFormat::Code code); - - - - /** For use with ImageFormat::convert. */ - class BayerAlgorithm { - public: - enum Value { - NEAREST, - BILINEAR, - mhc, - HIGH_QUALITY = mhc - }; - private: - - Value value; - - public: - - G3D_DECLARE_ENUM_CLASS_METHODS(BayerAlgorithm); - }; - - /** Converts between arbitrary formats on the CPU. Not all format conversions are supported or directly supported. - Formats without direct conversions will attempt to convert through RGBA first. - - A conversion routine might only support source or destination padding or y inversion or none. - If support is needed and not available in any of the direct conversion routines, then no conversion is done. - - YUV422 expects data in YUY2 format (Y, U, Y2, v). Most YUV formats require width and heights that are multiples of 2. - - Returns true if a conversion was available, false if none occurred. - */ - static bool convert(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, - const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, - bool invertY = false, BayerAlgorithm bayerAlg = BayerAlgorithm::HIGH_QUALITY); - - /* Checks if a conversion between two formats is available. */ - static bool conversionAvailable(const ImageFormat* srcFormat, int srcRowPadBits, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY = false); -}; - -typedef ImageFormat TextureFormat; - -} - -template <> -struct HashTrait { - static size_t hashCode(const G3D::ImageFormat* key) { return reinterpret_cast(key); } -}; - - - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Line.h b/externals/g3dlite/G3D.lib/include/G3D/Line.h deleted file mode 100644 index ff6dc8d08e7..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Line.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - @file Line.h - - Line class - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2001-06-02 - @edited 2006-02-28 - */ - -#ifndef G3D_LINE_H -#define G3D_LINE_H - -#include "G3D/platform.h" -#include "G3D/Vector3.h" - -namespace G3D { - -class Plane; - -/** - An infinite 3D line. - */ -class Line { -protected: - - Vector3 _point; - Vector3 _direction; - - Line(const Vector3& point, const Vector3& direction) { - _point = point; - _direction = direction.direction(); - } - -public: - - /** Undefined (provided for creating Array only) */ - inline Line() {} - - Line(class BinaryInput& b); - - void serialize(class BinaryOutput& b) const; - - void deserialize(class BinaryInput& b); - - virtual ~Line() {} - - /** - Constructs a line from two (not equal) points. - */ - static Line fromTwoPoints(const Vector3 &point1, const Vector3 &point2) { - return Line(point1, point2 - point1); - } - - /** - Creates a line from a point and a (nonzero) direction. - */ - static Line fromPointAndDirection(const Vector3& point, const Vector3& direction) { - return Line(point, direction); - } - - /** - Returns the closest point on the line to point. - */ - Vector3 closestPoint(const Vector3& pt) const; - - /** - Returns the distance between point and the line - */ - double distance(const Vector3& point) const { - return (closestPoint(point) - point).magnitude(); - } - - /** Returns a point on the line */ - Vector3 point() const; - - /** Returns the direction (or negative direction) of the line */ - Vector3 direction() const; - - /** - Returns the point where the line and plane intersect. If there - is no intersection, returns a point at infinity. - */ - Vector3 intersection(const Plane &plane) const; - - - /** Finds the closest point to the two lines. - - @param minDist Returns the minimum distance between the lines. - - @cite http://objectmix.com/graphics/133793-coordinates-closest-points-pair-skew-lines.html - */ - Vector3 closestPoint(const Line& B, float& minDist) const; - - inline Vector3 closestPoint(const Line& B) const { - float m; - return closestPoint(B, m); - } -}; - -};// namespace - - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/LineSegment.h b/externals/g3dlite/G3D.lib/include/G3D/LineSegment.h deleted file mode 100644 index 092b0c9ca6d..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/LineSegment.h +++ /dev/null @@ -1,115 +0,0 @@ -/** - @file LineSegment.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-02-08 - @edited 2008-02-02 - */ - -#ifndef G3D_LINESEGMENT_H -#define G3D_LINESEGMENT_H - -#include "G3D/platform.h" -#include "G3D/Vector3.h" - -namespace G3D { - -/** - An finite segment of an infinite 3D line. - */ -class LineSegment { -protected: - - Vector3 _point; - - /** Not normalized */ - Vector3 direction; - - LineSegment(const Vector3& __point, const Vector3& _direction) : _point(__point), direction(_direction) { - } - -public: - - inline LineSegment() : _point(Vector3::zero()), direction(Vector3::zero()) {} - - LineSegment(class BinaryInput& b); - - void serialize(class BinaryOutput& b) const; - - void deserialize(class BinaryInput& b); - - virtual ~LineSegment() {} - - /** - * Constructs a line from two (not equal) points. - */ - static LineSegment fromTwoPoints(const Vector3 &point1, const Vector3 &point2) { - return LineSegment(point1, point2 - point1); - } - - /** Call with 0 or 1 */ - Vector3 point(int i) const; - - inline float length() const { - return direction.magnitude(); - } - - /** - * Returns the closest point on the line segment to point. - */ - Vector3 closestPoint(const Vector3 &point) const; - - /** - Returns the distance between point and the line - */ - double distance(const Vector3& p) const { - return (closestPoint(p) - p).magnitude(); - } - - double distanceSquared(const Vector3& p) const { - return (closestPoint(p) - p).squaredMagnitude(); - } - - /** Returns true if some part of this segment is inside the sphere */ - bool intersectsSolidSphere(const class Sphere& s) const; - - Vector3 randomPoint() const; - -}; - - -class LineSegment2D { -private: - - Vector2 m_origin; - - /** Not normalized */ - Vector2 m_direction; - - /** Length of m_direction */ - float m_length; - -public: - - LineSegment2D() {} - - static LineSegment2D fromTwoPoints(const Vector2& p0, const Vector2& p1); - - /** Returns the intersection of these segements (including - testing endpoints), or Vector2::inf() if they do not intersect. */ - Vector2 intersection(const LineSegment2D& other) const; - - Vector2 point(int i) const; - - Vector2 closestPoint(const Vector2& Q) const; - - float distance(const Vector2& p) const; - - float length() const; -}; - -} // namespace - - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Log.h b/externals/g3dlite/G3D.lib/include/G3D/Log.h deleted file mode 100644 index 19b4b65c82d..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Log.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - @file Log.h - - @maintainer Morgan McGuire, morgan@graphics3d.com - @cite Backtrace by Aaron Orenstein - @created 2001-08-04 - @edited 2005-11-04 - */ - -#ifndef G3D_LOG_H -#define G3D_LOG_H - -#include -#include -#include "G3D/platform.h" - -#ifndef G3D_WIN32 - #include -#endif - -namespace G3D { - -/** Prints to the common system log, log.txt, which is usually - in the working directory of the program. If your disk is - not writable or is slow, it will attempt to write to "c:/tmp/log.txt" or - "c:/temp/log.txt" on Windows systems instead. - - Unlike printf or debugPrintf, - this function guarantees that all output is committed before it returns. - This is very useful for debugging a crash, which might hide the last few - buffered print statements otherwise. - - Many G3D routines write useful warnings and debugging information to the - system log, which makes it a good first place to go when tracking down - a problem. - */ -void logPrintf(const char* fmt, ...); - -/** - System log for debugging purposes. The first log opened - is the "common log" and can be accessed with the static - method common(). If you access common() and a common log - does not yet exist, one is created for you. - */ -class Log { -private: - - /** - Log messages go here. - */ - FILE* logFile; - - std::string filename; - - static Log* commonLog; - - int stripFromStackBottom; - - /** - Prints the time & stack trace. - */ - void printHeader(); - -public: - - /** - @param stripFromStackBottom Number of call stacks to strip from the - bottom of the stack when printing a trace. Useful for hiding - routines like "main" and "WinMain". If the specified file cannot - be opened for some reason, tries to open "c:/tmp/log.txt" or - "c:/temp/log.txt" instead. - */ - Log(const std::string& filename = "log.txt", - int stripFromStackBottom = 0); - - virtual ~Log(); - - /** - Returns the handle to the file log. - */ - FILE* getFile() const; - - /** - Marks the beginning of a logfile section. - */ - void section(const std::string& s); - - /** - Given arguments like printf, writes characters to the debug text overlay. - */ - // We want G3D_CHECK_PRINTF_ARGS here, but that conflicts with the - // overload. - void __cdecl printf(const char* fmt, ...) G3D_CHECK_PRINTF_METHOD_ARGS; - - void __cdecl vprintf(const char*, va_list argPtr) G3D_CHECK_VPRINTF_METHOD_ARGS; - - static Log* common(); - - static std::string getCommonLogFilename(); - - void print(const std::string& s); - - - void println(const std::string& s); -}; - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Map2D.h b/externals/g3dlite/G3D.lib/include/G3D/Map2D.h deleted file mode 100644 index 48e2e957a5f..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Map2D.h +++ /dev/null @@ -1,665 +0,0 @@ -/** - @file Map2D.h - - More flexible support than provided by G3D::GImage. - - @maintainer Morgan McGuire, morgan@cs.brown.edu - @created 2004-10-10 - @edited 2007-07-18 - */ -#ifndef G3D_MAP2D_H -#define G3D_MAP2D_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Array.h" -#include "G3D/Vector2int16.h" -#include "G3D/ReferenceCount.h" -#include "G3D/AtomicInt32.h" -#include "G3D/GThread.h" -#include "G3D/Rect2D.h" -#include "G3D/WrapMode.h" - -#include - -namespace G3D { -namespace _internal { - -/** The default compute type for a type is the type itself. */ -template class _GetComputeType { -public: - typedef Storage Type; -}; - -} // _internal -} // G3D - -// This weird syntax is needed to support VC6, which doesn't -// properly implement template overloading. -#define DECLARE_COMPUTE_TYPE(StorageType, ComputeType) \ -namespace G3D { \ - namespace _internal { \ - template<> class _GetComputeType < StorageType > { \ - public: \ - typedef ComputeType Type; \ - }; \ - } \ -} - -DECLARE_COMPUTE_TYPE( float32, float64) -DECLARE_COMPUTE_TYPE( float64, float64) - -DECLARE_COMPUTE_TYPE( int8, float32) -DECLARE_COMPUTE_TYPE( int16, float32) -DECLARE_COMPUTE_TYPE( int32, float64) -DECLARE_COMPUTE_TYPE( int64, float64) - -DECLARE_COMPUTE_TYPE( uint8, float32) -DECLARE_COMPUTE_TYPE( uint16, float32) -DECLARE_COMPUTE_TYPE( uint32, float64) -DECLARE_COMPUTE_TYPE( uint64, float64) - -DECLARE_COMPUTE_TYPE( Vector2, Vector2) -DECLARE_COMPUTE_TYPE( Vector2int16, Vector2) - -DECLARE_COMPUTE_TYPE( Vector3, Vector3) -DECLARE_COMPUTE_TYPE( Vector3int16, Vector3) - -DECLARE_COMPUTE_TYPE( Vector4, Vector4) - -DECLARE_COMPUTE_TYPE( Color3, Color3) -DECLARE_COMPUTE_TYPE( Color3uint8, Color3) - -DECLARE_COMPUTE_TYPE( Color4, Color4) -DECLARE_COMPUTE_TYPE( Color4uint8, Color4) -#undef DECLARE_COMPUTE_TYPE - -namespace G3D { - -/** - Map of values across a discrete 2D plane. Can be thought of as a generic class for 2D images, - allowing flexibility as to pixel format and convenient methods. - In fact, the "pixels" can be any values - on a grid that can be sensibly interpolated--RGB colors, scalars, 4D vectors, and so on. - - Other "image" classes in G3D: - - G3D::GImage - Supports file formats, fast, Color3uint8 and Color4uint8 formats. No interpolation. - - G3D::Texture::Ref - Represents image on the graphics card (not directly readable on the CPU). Supports 2D, 3D, and a variety of interpolation methods, loads file formats. - - G3D::Image3 - A subclass of Map2D that supports image loading and saving and conversion to Texture. - - G3D::Image4 - A subclass of Map2D that supports image loading and saving and conversion to Texture. - - G3D::Image3uint8 - A subclass of Map2D that supports image loading and saving and conversion to Texture. - - G3D::Image4uint8 - A subclass of Map2D that supports image loading and saving and conversion to Texture. - - There are two type parameters-- the first (@ Storage) is the type - used to store the "pixel" values efficiently and - the second (@a Compute) is - the type operated on by computation. The Compute::Compute(Storage&) constructor - is used to convert between storage and computation types. - @a Storage is often an integer version of @a Compute, for example - Map2D. By default, the computation type is: - -
-     Storage       Computation
-
-     uint8          float32
-     uint16         float32
-     uint32         float64
-     uint64         float64
-
-     int8           float32
-     int16          float32
-     int32          float64
-     int64          float64
-
-     float32        float64
-     float64        float64
-
-     Vector2        Vector2
-     Vector2int16   Vector2
-
-     Vector3        Vector3
-     Vector3int16   Vector3
-
-     Vector4        Vector4
-
-     Color3         Color3
-     Color3uint8    Color3
-
-     Color4         Color4
-     Color4uint8    Color4
-    
- Any other storage type defaults to itself as the computation type. - - The computation type can be any that - supports lerp, +, -, *, /, and an empty constructor. - - Assign value: - - im->set(x, y, 7); or - im->get(x, y) = 7; - - Read value: - - int c = im(x, y); - - Can also sample with nearest neighbor, bilinear, and bicubic - interpolation. - - Sampling follows OpenGL conventions, where - pixel values represent grid points and (0.5, 0.5) is half-way - between two vertical and two horizontal grid points. - To draw an image of dimensions w x h with nearest neighbor - sampling, render pixels from [0, 0] to [w - 1, h - 1]. - - Under the WrapMode::CLAMP wrap mode, the value of bilinear interpolation - becomes constant outside [1, w - 2] horizontally. Nearest neighbor - interpolation is constant outside [0, w - 1] and bicubic outside - [3, w - 4]. The class does not offer quadratic interpolation because - the interpolation filter could not center over a pixel. - - @author Morgan McGuire, morgan@cs.williams.edu - */ -template< typename Storage, -typename Compute = typename G3D::_internal::_GetComputeType::Type> -class Map2D : public ReferenceCountedObject { - -// -// It doesn't make sense to automatically convert from Compute back to Storage -// because the rounding rule (and scaling) is application dependent. -// Thus the interpolation methods all return type Compute. -// - -public: - - typedef Storage StorageType; - typedef Compute ComputeType; - typedef Map2D Type; - typedef ReferenceCountedPointer Ref; - -protected: - - Storage ZERO; - - /** Width, in pixels. */ - uint32 w; - - /** Height, in pixels. */ - uint32 h; - - WrapMode _wrapMode; - - /** 0 if no mutating method has been invoked - since the last call to setChanged(); */ - AtomicInt32 m_changed; - - Array data; - - /** Handles the exceptional cases from get */ - const Storage& slowGet(int x, int y, WrapMode wrap) { - switch (wrap) { - case WrapMode::CLAMP: - return fastGet(iClamp(x, 0, w - 1), iClamp(y, 0, h - 1)); - - case WrapMode::TILE: - return fastGet(iWrap(x, w), iWrap(y, h)); - - case WrapMode::ZERO: - return ZERO; - - case WrapMode::ERROR: - alwaysAssertM(((uint32)x < w) && ((uint32)y < h), - format("Index out of bounds: (%d, %d), w = %d, h = %d", - x, y, w, h)); - - // intentionally fall through - case WrapMode::IGNORE: - // intentionally fall through - default: - { - static Storage temp; - return temp; - } - } - } - -public: - - /** Unsafe access to the underlying data structure with no wrapping support; requires that (x, y) is in bounds. */ - inline const Storage& fastGet(int x, int y) const { - debugAssert(((uint32)x < w) && ((uint32)y < h)); - return data[x + y * w]; - } - - /** Unsafe access to the underlying data structure with no wrapping support; requires that (x, y) is in bounds. */ - inline void fastSet(int x, int y, const Storage& v) { - debugAssert(((uint32)x < w) && ((uint32)y < h)); - data[x + y * w] = v; - } - -protected: - - /** Given four control points and a value on the range [0, 1) - evaluates the Catmull-rom spline between the times of the - middle two control points */ - Compute bicubic(const Compute* ctrl, double s) const { - - // f = B * S * ctrl' - - // B matrix: Catmull-Rom spline basis - static const double B[4][4] = { - { 0.0, -0.5, 1.0, -0.5}, - { 1.0, 0.0, -2.5, 1.5}, - { 0.0, 0.5, 2.0, -1.5}, - { 0.0, 0.0, -0.5, 0.5}}; - - // S: Powers of the fraction - double S[4]; - double s2 = s * s; - S[0] = 1.0; - S[1] = s; - S[2] = s2; - S[3] = s2 * s; - - Compute sum(ZERO); - - for (int c = 0; c < 4; ++c) { - double coeff = 0.0; - for (int power = 0; power < 4; ++power) { - coeff += B[c][power] * S[power]; - } - sum += ctrl[c] * coeff; - } - - return sum; - } - - - Map2D(int w, int h, WrapMode wrap) : w(0), h(0), _wrapMode(wrap), m_changed(1) { - ZERO = Storage(Compute(Storage()) * 0); - resize(w, h); - } - -public: - - /** - Although Map2D is not threadsafe (except for the setChanged() method), - you can use this mutex to create your own threadsafe access to a Map2D. - Not used by the default implementation. - */ - GMutex mutex; - - static Ref create(int w = 0, int h = 0, WrapMode wrap = WrapMode::ERROR) { - return new Map2D(w, h, wrap); - } - - /** Resizes without clearing, leaving garbage. - */ - void resize(uint32 newW, uint32 newH) { - if ((newW != w) || (newH != h)) { - w = newW; - h = newH; - data.resize(w * h); - setChanged(true); - } - } - - /** - Returns true if this map has been written to since the last call to setChanged(false). - This is useful if you are caching a texture map other value that must be recomputed - whenever this changes. - */ - bool changed() { - return m_changed.value() != 0; - } - - /** Set/unset the changed flag. */ - void setChanged(bool c) { - m_changed = c ? 1 : 0; - } - - /** Returns a pointer to the underlying row-major data. There is no padding at the end of the row. - Be careful--this will be reallocated during a resize. You should call setChanged(true) if you mutate the array.*/ - Storage* getCArray() { - return data.getCArray(); - } - - - const Storage* getCArray() const { - return data.getCArray(); - } - - - /** Row-major array. You should call setChanged(true) if you mutate the array. */ - Array& getArray() { - return data; - } - - - const Array& getArray() const { - return data; - } - - /** is (x, y) strictly within the image bounds, or will it trigger some kind of wrap mode */ - inline bool inBounds(int x, int y) const { - return (((uint32)x < w) && ((uint32)y < h)); - } - - /** is (x, y) strictly within the image bounds, or will it trigger some kind of wrap mode */ - inline bool inBounds(const Vector2int16& v) const { - return inBounds(v.x, v.y); - } - - /** Get the value at (x, y). - - Note that the type of image->get(x, y) is - the storage type, not the computation - type. If the constructor promoting Storage to Compute rescales values - (as, for example Color3(Color3uint8&) does), this will not match the value - returned by Map2D::nearest. - */ - inline const Storage& get(int x, int y, WrapMode wrap) const { - if (((uint32)x < w) && ((uint32)y < h)) { - return data[x + y * w]; - } else { - // Remove the const to allow a slowGet on this object - // (we're returning a const reference so this is ok) - return const_cast(this)->slowGet(x, y, wrap); - } -# ifndef G3D_WIN32 - // gcc gives a useless warning that the above code might reach the end of the function; - // we use this line to supress the warning. - return ZERO; -# endif - } - - inline const Storage& get(int x, int y) const { - return get(x, y, _wrapMode); - } - - inline const Storage& get(const Vector2int16& p) const { - return get(p.x, p.y, _wrapMode); - } - - inline const Storage& get(const Vector2int16& p, WrapMode wrap) const { - return get(p.x, p.y, wrap); - } - - inline Storage& get(int x, int y, WrapMode wrap) { - return const_cast(const_cast(this)->get(x, y, wrap)); -# ifndef G3D_WIN32 - // gcc gives a useless warning that the above code might reach the end of the function; - // we use this line to supress the warning. - return ZERO; -# endif - } - - inline Storage& get(int x, int y) { - return const_cast(const_cast(this)->get(x, y)); -# ifndef G3D_WIN32 - // gcc gives a useless warning that the above code might reach the end of the function; - // we use this line to supress the warning. - return ZERO; -# endif - } - - inline Storage& get(const Vector2int16& p) { - return get(p.x, p.y); - } - - /** Sets the changed flag to true */ - inline void set(const Vector2int16& p, const Storage& v) { - set(p.x, p.y, v); - } - - /** Sets the changed flag to true */ - void set(int x, int y, const Storage& v, WrapMode wrap) { - setChanged(true); - if (((uint32)x < w) && ((uint32)y < h)) { - // In bounds, wrapping isn't an issue. - data[x + y * w] = v; - } else { - const_cast(slowGet(x, y, wrap)) = v; - } - } - - void set(int x, int y, const Storage& v) { - set(x, y, v, _wrapMode); - } - - - void setAll(const Storage& v) { - for(int i = 0; i < data.size(); ++i) { - data[i] = v; - } - setChanged(true); - } - - /** flips if @a flip is true*/ - void maybeFlipVertical(bool flip) { - if (flip) { - flipVertical(); - } - } - - virtual void flipVertical() { - int halfHeight = h/2; - Storage* d = data.getCArray(); - for (int y = 0; y < halfHeight; ++y) { - int o1 = y * w; - int o2 = (h - y - 1) * w; - for (int x = 0; x < (int)w; ++x) { - int i1 = o1 + x; - int i2 = o2 + x; - Storage temp = d[i1]; - d[i1] = d[i2]; - d[i2] = temp; - } - } - setChanged(true); - } - - virtual void flipHorizontal() { - int halfWidth = w / 2; - Storage* d = data.getCArray(); - for (int x = 0; x < halfWidth; ++x) { - for (int y = 0; y < (int)h; ++y) { - int i1 = y * w + x; - int i2 = y * w + (w - x - 1); - Storage temp = d[i1]; - d[i1] = d[i2]; - d[i2] = temp; - } - } - setChanged(true); - } - - /** - Crops this map so that it only contains pixels between (x, y) and (x + w - 1, y + h - 1) inclusive. - */ - virtual void crop(int newX, int newY, int newW, int newH) { - alwaysAssertM(newX + newW <= (int)w, "Cannot grow when cropping"); - alwaysAssertM(newY + newH <= (int)h, "Cannot grow when cropping"); - alwaysAssertM(newX >= 0 && newY >= 0, "Origin out of bounds."); - - // Always safe to copy towards the upper left, provided - // that we're iterating towards the lower right. This lets us avoid - // reallocating the underlying array. - for (int y = 0; y < newH; ++y) { - for (int x = 0; x < newW; ++x) { - data[x + y * newW] = data[(x + newX) + (y + newY) * w]; - } - } - - resize(newW, newH); - } - - /** iRounds to the nearest x0 and y0. */ - virtual void crop(const Rect2D& rect) { - crop(iRound(rect.x0()), iRound(rect.y0()), iRound(rect.x1()) - iRound(rect.x0()), iRound(rect.y1()) - iRound(rect.y0())); - } - - /** Returns the nearest neighbor. Pixel values are considered - to be at the upper left corner, so image->nearest(x, y) == image(x, y) - */ - inline Compute nearest(float x, float y, WrapMode wrap) const { - return Compute(get(iRound(x), iRound(y), wrap)); - } - - inline Compute nearest(float x, float y) const { - return nearest(x, y, _wrapMode); - } - - inline Compute nearest(const Vector2& p) const { - return nearest(p.x, p.y); - } - - /** Returns the average value of all elements of the map */ - Compute average() const { - if ((w == 0) || (h == 0)) { - return ZERO; - } - - // To avoid overflows, compute the average of row averages - - Compute rowSum = ZERO; - for (unsigned int y = 0; y < h; ++y) { - Compute sum = ZERO; - int offset = y * w; - for (unsigned int x = 0; x < w; ++x) { - sum += Compute(data[offset + x]); - } - rowSum += sum * (1.0f / w); - } - - return rowSum * (1.0f / h); - } - - /** - Needs to access elements from (floor(x), floor(y)) - to (floor(x) + 1, floor(y) + 1) and will use - the wrap mode appropriately (possibly generating - out of bounds errors). - - Guaranteed to match nearest(x, y) at integers. */ - Compute bilinear(float x, float y, WrapMode wrap) const { - int i = iFloor(x); - int j = iFloor(y); - - float fX = x - i; - float fY = y - j; - - // Horizontal interpolation, first row - Compute t0(get(i, j, wrap)); - Compute t1(get(i + 1, j, wrap)); - Compute A = lerp(t0, t1, fX); - - // Horizontal interpolation, second row - Compute t2(get(i, j + 1, wrap)); - Compute t3(get(i + 1, j + 1, wrap)); - Compute B = lerp(t2, t3, fX); - - // Vertical interpolation - return lerp(A, B, fY); - } - - Compute bilinear(float x, float y) const { - return bilinear(x, y, _wrapMode); - } - - inline Compute bilinear(const Vector2& p) const { - return bilinear(p.x, p.y, _wrapMode); - } - - inline Compute bilinear(const Vector2& p, WrapMode wrap) const { - return bilinear(p.x, p.y, wrap); - } - - /** - Uses Catmull-Rom splines to interpolate between grid - values. Guaranteed to match nearest(x, y) at integers. - */ - Compute bicubic(float x, float y, WrapMode wrap) const { - int i = iFloor(x); - int j = iFloor(y); - float fX = x - i; - float fY = y - j; - - // 'static' prevents constructors from being called - // every time through this loop. - static Compute vsample[4]; - for (int v = 0; v < 4; ++v) { - - // Horizontal interpolation - static Compute hsample[4]; - for (int u = 0; u < 4; ++u) { - hsample[u] = Compute(get(i + u - 1, j + v - 1, wrap)); - } - - vsample[v] = bicubic(hsample, fX); - } - - // Vertical interpolation - return bicubic(vsample, fY); - } - - Compute bicubic(float x, float y) const { - return bicubic(x, y, _wrapMode); - } - - inline Compute bicubic(const Vector2& p, WrapMode wrap) const { - return bicubic(p.x, p.y, wrap); - } - - inline Compute bicubic(const Vector2& p) const { - return bicubic(p.x, p.y, _wrapMode); - } - - /** Pixel width */ - inline int32 width() const { - return (int32)w; - } - - - /** Pixel height */ - inline int32 height() const { - return (int32)h; - } - - - /** Dimensions in pixels */ - Vector2int16 size() const { - return Vector2int16(w, h); - } - - /** Rectangle from (0, 0) to (w, h) */ - Rect2D rect2DBounds() const { - return Rect2D::xywh(0, 0, w, h); - } - - /** Number of bytes occupied by the image data and this structure */ - size_t sizeInMemory() const { - return data.size() * sizeof(Storage) + sizeof(*this); - } - - - WrapMode wrapMode() const { - return _wrapMode; - } - - - void setWrapMode(WrapMode m) { - _wrapMode = m; - } -}; - - - -} - -#endif // G3D_IMAGE_H diff --git a/externals/g3dlite/G3D.lib/include/G3D/Matrix.h b/externals/g3dlite/G3D.lib/include/G3D/Matrix.h deleted file mode 100644 index 481af940324..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Matrix.h +++ /dev/null @@ -1,634 +0,0 @@ -/** - @file Matrix.h - @author Morgan McGuire, morgan@cs.williams.edu - - @created 2005-10-23 - @edited 2007-07-18 - */ - -#ifndef G3D_MATRIX_H -#define G3D_MATRIX_H - -#include "G3D/g3dmath.h" -#include "G3D/Vector3.h" -#include "G3D/Vector4.h" -#include "G3D/Matrix3.h" -#include "G3D/Matrix4.h" -#include "G3D/ReferenceCount.h" - -namespace G3D { - -/** - N x M matrix. - - The actual data is tracked internally by a reference counted pointer; - it is efficient to pass and assign Matrix objects because no data is actually copied. - This avoids the headache of pointers and allows natural math notation: - -
-    Matrix A, B, C;
-    // ...
-
-    C = A * f(B);
-    C = C.inverse();
-
-    A = Matrix::identity(4);
-    C = A;
-    C.set(0, 0, 2.0); // Triggers a copy of the data so that A remains unchanged.
-
-    // etc.
-
-  
- - The Matrix::debugNumCopyOps and Matrix::debugNumAllocOps counters - increment every time an operation forces the copy and allocation of matrices. You - can use these to detect slow operations when efficiency is a major concern. - - Some methods accept an output argument instead of returning a value. For example, - A = B.transpose() can also be invoked as B.transpose(A). - The latter may be more efficient, since Matrix may be able to re-use the storage of - A (if it has approximatly the right size and isn't currently shared with another matrix). - - @sa G3D::Matrix3, G3D::Matrix4, G3D::Vector2, G3D::Vector3, G3D::Vector4, G3D::CoordinateFrame - - @beta - */ -class Matrix { -public: - /** - Internal precision. Currently float, but this may become a templated class in the future - to allow operations like Matrix and Matrix. - - Not necessarily a plain-old-data type (e.g., could ComplexFloat), but must be something - with no constructor, that can be safely memcpyd, and that has a bit pattern of all zeros - when zero.*/ - typedef float T; - - /** Incremented every time the elements of a matrix are copied. Useful for profiling your - own code that uses Matrix to determine when it is slow due to copying.*/ - static int debugNumCopyOps; - - /** Incremented every time a new matrix object is allocated. Useful for profiling your - own code that uses Matrix to determine when it is slow due to allocation.*/ - static int debugNumAllocOps; - -private: -public: - - /** Used internally by Matrix. - - Does not throw exceptions-- assumes the caller has taken care of - argument checking. */ - class Impl : public ReferenceCountedObject { - public: - - static void* operator new(size_t size) { - return System::malloc(size); - } - - static void operator delete(void* p) { - System::free(p); - } - - ~Impl(); - - private: - friend class Matrix; - - /** elt[r][c] = the element. Pointers into data.*/ - T** elt; - - /** Row major data for the entire matrix. */ - T* data; - - /** The number of rows */ - int R; - - /** The number of columns */ - int C; - - int dataSize; - - /** If R*C is much larger or smaller than the current, deletes all previous data - and resets to random data. Otherwise re-uses existing memory and just resets - R, C, and the row pointers. */ - void setSize(int newRows, int newCols); - - inline Impl() : elt(NULL), data(NULL), R(0), C(0), dataSize(0) {} - - Impl(const Matrix3& M); - - Impl(const Matrix4& M); - - inline Impl(int r, int c) : elt(NULL), data(NULL), R(0), C(0), dataSize(0) { - setSize(r, c); - } - - Impl& operator=(const Impl& m); - - inline Impl(const Impl& B) : elt(NULL), data(NULL), R(0), C(0), dataSize(0) { - // Use the assignment operator - *this = B; - } - - void setZero(); - - inline void set(int r, int c, T v) { - debugAssert(r < R); - debugAssert(c < C); - elt[r][c] = v; - } - - inline const T& get(int r, int c) const { - debugAssert(r < R); - debugAssert(c < C); - return elt[r][c]; - } - - /** Multiplies this by B and puts the result in out. */ - void mul(const Impl& B, Impl& out) const; - - /** Ok if out == this or out == B */ - void add(const Impl& B, Impl& out) const; - - /** Ok if out == this or out == B */ - void add(T B, Impl& out) const; - - /** Ok if out == this or out == B */ - void sub(const Impl& B, Impl& out) const; - - /** Ok if out == this or out == B */ - void sub(T B, Impl& out) const; - - /** B - this */ - void lsub(T B, Impl& out) const; - - /** Ok if out == this or out == B */ - void arrayMul(const Impl& B, Impl& out) const; - - /** Ok if out == this or out == B */ - void mul(T B, Impl& out) const; - - /** Ok if out == this or out == B */ - void arrayDiv(const Impl& B, Impl& out) const; - - /** Ok if out == this or out == B */ - void div(T B, Impl& out) const; - - void negate(Impl& out) const; - - /** Slow way of computing an inverse; for reference */ - void inverseViaAdjoint(Impl& out) const; - - /** Use Gaussian elimination with pivots to solve for the inverse destructively in place. */ - void inverseInPlaceGaussJordan(); - - void adjoint(Impl& out) const; - - /** Matrix of all cofactors */ - void cofactor(Impl& out) const; - - /** - Cofactor [r][c] is defined as C[r][c] = -1 ^(r+c) * det(A[r][c]), - where A[r][c] is the (R-1)x(C-1) matrix formed by removing row r and - column c from the original matrix. - */ - T cofactor(int r, int c) const; - - /** Ok if out == this or out == B */ - void transpose(Impl& out) const; - - T determinant() const; - - /** Determinant computed without the given row and column */ - T determinant(int r, int c) const; - - void arrayLog(Impl& out) const; - - void arrayExp(Impl& out) const; - - void arraySqrt(Impl& out) const; - - void arrayCos(Impl& out) const; - - void arraySin(Impl& out) const; - - void swapRows(int r0, int r1); - - void swapAndNegateCols(int c0, int c1); - - void mulRow(int r, const T& v); - - void abs(Impl& out) const; - - /** Makes a (R-1)x(C-1) copy of this matrix */ - void withoutRowAndCol(int excludeRow, int excludeCol, Impl& out) const; - - bool anyNonZero() const; - - bool allNonZero() const; - - void setRow(int r, const T* vals); - - void setCol(int c, const T* vals); - }; -private: - - typedef ReferenceCountedPointer ImplRef; - - ImplRef impl; - - inline Matrix(ImplRef i) : impl(i) {} - inline Matrix(Impl* i) : impl(ImplRef(i)) {} - - /** Used by SVD */ - class SortRank { - public: - T value; - int col; - - inline bool operator>(const SortRank& x) const { - return x.value > value; - } - - inline bool operator<(const SortRank& x) const { - return x.value < value; - } - - inline bool operator>=(const SortRank& x) const { - return x.value >= value; - } - - inline bool operator<=(const SortRank& x) const { - return x.value <= value; - } - - inline bool operator==(const SortRank& x) const { - return x.value == value; - } - - inline bool operator!=(const SortRank& x) const { - return x.value != value; - } - }; - - Matrix vectorPseudoInverse() const; - Matrix partitionPseudoInverse() const; - Matrix colPartPseudoInverse() const; - Matrix rowPartPseudoInverse() const; - - Matrix col2PseudoInverse(const Matrix& B) const; - Matrix col3PseudoInverse(const Matrix& B) const; - Matrix col4PseudoInverse(const Matrix& B) const; - Matrix row2PseudoInverse(const Matrix& B) const; - Matrix row3PseudoInverse(const Matrix& B) const; - Matrix row4PseudoInverse(const Matrix& B) const; - -public: - - Matrix() : impl(new Impl(0, 0)) {} - - Matrix(const Matrix3& M) : impl(new Impl(M)) {} - - Matrix(const Matrix4& M) : impl(new Impl(M)) {} - - template - static Matrix fromDiagonal(const Array& d) { - Matrix D = zero(d.length(), d.length()); - for (int i = 0; i < d.length(); ++i) { - D.set(i, i, d[i]); - } - return D; - } - - static Matrix fromDiagonal(const Matrix& d); - - /** Returns a new matrix that is all zero. */ - Matrix(int R, int C) : impl(new Impl(R, C)) { - impl->setZero(); - } - - /** Returns a new matrix that is all zero. */ - static Matrix zero(int R, int C); - - /** Returns a new matrix that is all one. */ - static Matrix one(int R, int C); - - /** Returns a new identity matrix */ - static Matrix identity(int N); - - /** Uniformly distributed values between zero and one. */ - static Matrix random(int R, int C); - - /** The number of rows */ - inline int rows() const { - return impl->R; - } - - /** Number of columns */ - inline int cols() const { - return impl->C; - } - - /** Generally more efficient than A * B */ - Matrix& operator*=(const T& B); - - /** Generally more efficient than A / B */ - Matrix& operator/=(const T& B); - - /** Generally more efficient than A + B */ - Matrix& operator+=(const T& B); - - /** Generally more efficient than A - B */ - Matrix& operator-=(const T& B); - - /** No performance advantage over A * B because - matrix multiplication requires intermediate - storage. */ - Matrix& operator*=(const Matrix& B); - - /** Generally more efficient than A + B */ - Matrix& operator+=(const Matrix& B); - - /** Generally more efficient than A - B */ - Matrix& operator-=(const Matrix& B); - - /** Returns a new matrix that is a subset of this one, - from r1:r2 to c1:c2, inclusive.*/ - Matrix subMatrix(int r1, int r2, int c1, int c2) const; - - /** Matrix multiplication. To perform element-by-element multiplication, - see arrayMul. */ - inline Matrix operator*(const Matrix& B) const { - Matrix C(impl->R, B.impl->C); - impl->mul(*B.impl, *C.impl); - return C; - } - - /** See also A *= B, which is more efficient in many cases */ - inline Matrix operator*(const T& B) const { - Matrix C(impl->R, impl->C); - impl->mul(B, *C.impl); - return C; - } - - /** See also A += B, which is more efficient in many cases */ - inline Matrix operator+(const Matrix& B) const { - Matrix C(impl->R, impl->C); - impl->add(*B.impl, *C.impl); - return C; - } - - /** See also A -= B, which is more efficient in many cases */ - inline Matrix operator-(const Matrix& B) const { - Matrix C(impl->R, impl->C); - impl->sub(*B.impl, *C.impl); - return C; - } - - /** See also A += B, which is more efficient in many cases */ - inline Matrix operator+(const T& v) const { - Matrix C(impl->R, impl->C); - impl->add(v, *C.impl); - return C; - } - - /** See also A -= B, which is more efficient in many cases */ - inline Matrix operator-(const T& v) const { - Matrix C(impl->R, impl->C); - impl->sub(v, *C.impl); - return C; - } - - - Matrix operator>(const T& scalar) const; - - Matrix operator<(const T& scalar) const; - - Matrix operator>=(const T& scalar) const; - - Matrix operator<=(const T& scalar) const; - - Matrix operator==(const T& scalar) const; - - Matrix operator!=(const T& scalar) const; - - /** scalar B - this */ - inline Matrix lsub(const T& B) const { - Matrix C(impl->R, impl->C); - impl->lsub(B, *C.impl); - return C; - } - - inline Matrix arrayMul(const Matrix& B) const { - Matrix C(impl->R, impl->C); - impl->arrayMul(*B.impl, *C.impl); - return C; - } - - Matrix3 toMatrix3() const; - - Matrix4 toMatrix4() const; - - Vector2 toVector2() const; - - Vector3 toVector3() const; - - Vector4 toVector4() const; - - /** Mutates this */ - void arrayMulInPlace(const Matrix& B); - - /** Mutates this */ - void arrayDivInPlace(const Matrix& B); - - // Declares an array unary method and its explicit-argument counterpart -# define DECLARE_METHODS_1(method)\ - inline Matrix method() const {\ - Matrix C(impl->R, impl->C);\ - impl->method(*C.impl);\ - return C;\ - }\ - void method(Matrix& out) const; - - - DECLARE_METHODS_1(abs) - DECLARE_METHODS_1(arrayLog) - DECLARE_METHODS_1(arrayExp) - DECLARE_METHODS_1(arraySqrt) - DECLARE_METHODS_1(arrayCos) - DECLARE_METHODS_1(arraySin) - DECLARE_METHODS_1(negate) - -# undef DECLARE_METHODS_1 - - inline Matrix operator-() const { - return negate(); - } - - /** - A-1 computed using the Gauss-Jordan algorithm, - for square matrices. - Run time is O(R3), where R is the - number of rows. - */ - inline Matrix inverse() const { - Impl* A = new Impl(*impl); - A->inverseInPlaceGaussJordan(); - return Matrix(A); - } - - inline T determinant() const { - return impl->determinant(); - } - - /** - AT - */ - inline Matrix transpose() const { - Impl* A = new Impl(cols(), rows()); - impl->transpose(*A); - return Matrix(A); - } - - /** Transpose in place; more efficient than transpose */ - void transpose(Matrix& out) const; - - inline Matrix adjoint() const { - Impl* A = new Impl(cols(), rows()); - impl->adjoint(*A); - return Matrix(A); - } - - /** - (ATA)-1AT) computed - using SVD. - - @param tolerance Use -1 for automatic tolerance. - */ - Matrix pseudoInverse(float tolerance = -1) const; - - /** Called from pseudoInverse when the matrix has size > 4 along some dimension.*/ - Matrix svdPseudoInverse(float tolerance = -1) const; - - /** - (ATA)-1AT) computed - using Gauss-Jordan elimination. - */ - inline Matrix gaussJordanPseudoInverse() const { - Matrix trans = transpose(); - return (trans * (*this)).inverse() * trans; - } - - /** Singular value decomposition. Factors into three matrices - such that @a this = @a U * fromDiagonal(@a d) * @a V.transpose(). - - The matrix must have at least as many rows as columns. - - Run time is O(C2*R). - - @param sort If true (default), the singular values - are arranged so that D is sorted from largest to smallest. - */ - void svd(Matrix& U, Array& d, Matrix& V, bool sort = true) const; - - void set(int r, int c, T v); - - void setCol(int c, const Matrix& vec); - - void setRow(int r, const Matrix& vec); - - Matrix col(int c) const; - - Matrix row(int r) const; - - T get(int r, int c) const; - - Vector2int16 size() const { - return Vector2int16(rows(), cols()); - } - - int numElements() const { - return rows() * cols(); - } - - void swapRows(int r0, int r1); - - /** Swaps columns c0 and c1 and negates both */ - void swapAndNegateCols(int c0, int c1); - - void mulRow(int r, const T& v); - - /** Returns true if any element is non-zero */ - bool anyNonZero() const; - - /** Returns true if all elements are non-zero */ - bool allNonZero() const; - - inline bool allZero() const { - return !anyNonZero(); - } - - inline bool anyZero() const { - return !allNonZero(); - } - - /** Serializes in Matlab source format */ - void serialize(TextOutput& t) const; - - std::string toString(const std::string& name) const; - - std::string toString() const { - static const std::string name = ""; - return toString(name); - } - - /** 2-norm squared: sum(squares). (i.e., dot product with itself) */ - double normSquared() const; - - /** 2-norm (sqrt(sum(squares)) */ - double norm() const; - - /** - Low-level SVD functionality. Useful for applications that do not want - to construct a Matrix but need to perform the SVD operation. - - this = U * D * V' - - Assumes that rows >= cols - - @return NULL on success, a string describing the error on failure. - @param U rows x cols matrix to be decomposed, gets overwritten with U, a rows x cols matrix with orthogonal columns. - @param D vector of singular values of a (diagonal of the D matrix). Length cols. - @param V returns the right orthonormal transformation matrix, size cols x cols - - @cite Based on Dianne Cook's implementation, which is adapted from - svdecomp.c in XLISP-STAT 2.1, which is code from Numerical Recipes - adapted by Luke Tierney and David Betz. The Numerical Recipes code - is adapted from Forsythe et al, who based their code on Golub and - Reinsch's original implementation. - */ - static const char* svdCore(float** U, int rows, int cols, float* D, float** V); - -}; - -} - -inline G3D::Matrix operator-(const G3D::Matrix::T& v, const G3D::Matrix& M) { - return M.lsub(v); -} - -inline G3D::Matrix operator*(const G3D::Matrix::T& v, const G3D::Matrix& M) { - return M * v; -} - -inline G3D::Matrix operator+(const G3D::Matrix::T& v, const G3D::Matrix& M) { - return M + v; -} - -inline G3D::Matrix abs(const G3D::Matrix& M) { - return M.abs(); -} - -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/Matrix2.h b/externals/g3dlite/G3D.lib/include/G3D/Matrix2.h deleted file mode 100644 index eaf4aefa220..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Matrix2.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef G3D_MATRIX2_H -#define G3D_MATRIX2_H - -#include "G3D/platform.h" -#include "G3D/Vector2.h" - -namespace G3D { - -/** @beta */ -class Matrix2 { -private: - - float data[2][2]; - -public: - - inline Matrix2() { - data[0][0] = 1.0f; data[0][1] = 0.0f; - data[1][0] = 0.0f; data[1][1] = 1.0f; - } - - inline Matrix2(float v00, float v01, float v10, float v11) { - data[0][0] = v00; data[0][1] = v01; - data[1][0] = v10; data[1][1] = v11; - } - - inline Vector2 operator*(const Vector2& v) const { - return Vector2(data[0][0] * v[0] + data[0][1] * v[1], - data[1][0] * v[0] + data[1][1] * v[1]); - } - - inline Matrix2 inverse() const { - return Matrix2(data[0][0], data[1][0], - data[0][1], data[1][1]) * (1.0f / determinant()); - } - - inline Matrix2 transpose() const { - return Matrix2(data[0][0], data[1][0], - data[0][1], data[1][1]); - } - - inline float determinant() const { - return data[0][0] * data[1][1] - data[0][1] * data[1][0]; - } - - inline Matrix2 operator*(float f) const { - return Matrix2(data[0][0] * f, data[0][1] * f, - data[1][0] * f, data[1][1] * f); - } - - inline Matrix2 operator/(float f) const { - return Matrix2(data[0][0] / f, data[0][1] / f, - data[1][0] / f, data[1][1] / f); - } - - inline float* operator[](int i) { - debugAssert(i >= 0 && i <= 2); - return data[i]; - } - - inline const float* operator[](int i) const { - debugAssert(i >= 0 && i <= 1); - return data[i]; - } -}; - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Matrix3.h b/externals/g3dlite/G3D.lib/include/G3D/Matrix3.h deleted file mode 100644 index ad09cd3860f..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Matrix3.h +++ /dev/null @@ -1,323 +0,0 @@ -/** - @file Matrix3.h - - 3x3 matrix class - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com - - @created 2001-06-02 - @edited 2006-04-05 - */ - -#ifndef G3D_MATRIX3_H -#define G3D_MATRIX3_H - -#include "G3D/platform.h" -#include "G3D/Vector3.h" -#include "G3D/Vector4.h" -#include "G3D/debugAssert.h" - -#include - -namespace G3D { - -/** - 3x3 matrix. Do not subclass. - */ -class Matrix3 { -private: - - float elt[3][3]; - - // Hidden operators - bool operator<(const Matrix3&) const; - bool operator>(const Matrix3&) const; - bool operator<=(const Matrix3&) const; - bool operator>=(const Matrix3&) const; - -public: - - /** Initial values are undefined for performance. See also - Matrix3::zero(), Matrix3::identity(), Matrix3::fromAxisAngle, etc.*/ - inline Matrix3() {} - - Matrix3 (class BinaryInput& b); - Matrix3 (const float aafEntry[3][3]); - Matrix3 (const Matrix3& rkMatrix); - Matrix3 (float fEntry00, float fEntry01, float fEntry02, - float fEntry10, float fEntry11, float fEntry12, - float fEntry20, float fEntry21, float fEntry22); - - bool fuzzyEq(const Matrix3& b) const; - - /** Constructs a matrix from a quaternion. - @cite Graphics Gems II, p. 351--354 - @cite Implementation from Watt and Watt, pg 362*/ - Matrix3(const class Quat& q); - - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); - - /** - Sets all elements. - */ - void set(float fEntry00, float fEntry01, float fEntry02, - float fEntry10, float fEntry11, float fEntry12, - float fEntry20, float fEntry21, float fEntry22); - - /** - * member access, allows use of construct mat[r][c] - */ - inline float* operator[] (int iRow) { - debugAssert(iRow >= 0); - debugAssert(iRow < 3); - return (float*)&elt[iRow][0]; - } - - inline const float* operator[] (int iRow) const { - debugAssert(iRow >= 0); - debugAssert(iRow < 3); - return (const float*)&elt[iRow][0]; - } - - inline operator float* () { - return (float*)&elt[0][0]; - } - - inline operator const float* () const{ - return (const float*)&elt[0][0]; - } - - /** @deprecated */ - Vector3 getColumn (int iCol) const; - /** @deprecated */ - Vector3 getRow (int iRow) const; - - Vector3 column(int c) const; - const Vector3& row(int r) const; - - void setColumn(int iCol, const Vector3 &vector); - void setRow(int iRow, const Vector3 &vector); - - // assignment and comparison - inline Matrix3& operator= (const Matrix3& rkMatrix) { - memcpy(elt, rkMatrix.elt, 9 * sizeof(float)); - return *this; - } - - bool operator== (const Matrix3& rkMatrix) const; - bool operator!= (const Matrix3& rkMatrix) const; - - // arithmetic operations - Matrix3 operator+ (const Matrix3& rkMatrix) const; - Matrix3 operator- (const Matrix3& rkMatrix) const; - /** Matrix-matrix multiply */ - Matrix3 operator* (const Matrix3& rkMatrix) const; - Matrix3 operator- () const; - - Matrix3& operator+= (const Matrix3& rkMatrix); - Matrix3& operator-= (const Matrix3& rkMatrix); - Matrix3& operator*= (const Matrix3& rkMatrix); - - /** - * matrix * vector [3x3 * 3x1 = 3x1] - */ - inline Vector3 operator* (const Vector3& v) const { - Vector3 kProd; - - for (int r = 0; r < 3; ++r) { - kProd[r] = - elt[r][0] * v[0] + - elt[r][1] * v[1] + - elt[r][2] * v[2]; - } - - return kProd; - } - - - /** - * vector * matrix [1x3 * 3x3 = 1x3] - */ - friend Vector3 operator* (const Vector3& rkVector, - const Matrix3& rkMatrix); - - /** - * matrix * scalar - */ - Matrix3 operator* (float fScalar) const; - - /** scalar * matrix */ - friend Matrix3 operator* (double fScalar, const Matrix3& rkMatrix); - friend Matrix3 operator* (float fScalar, const Matrix3& rkMatrix); - friend Matrix3 operator* (int fScalar, const Matrix3& rkMatrix); - -private: - /** Multiplication where out != A and out != B */ - static void _mul(const Matrix3& A, const Matrix3& B, Matrix3& out); -public: - - /** Optimized implementation of out = A * B. It is safe (but slow) to call - with A, B, and out possibly pointer equal to one another.*/ - // This is a static method so that it is not ambiguous whether "this" - // is an input or output argument. - inline static void mul(const Matrix3& A, const Matrix3& B, Matrix3& out) { - if ((&out == &A) || (&out == &B)) { - // We need a temporary anyway, so revert to the stack method. - out = A * B; - } else { - // Optimized in-place multiplication. - _mul(A, B, out); - } - } - -private: - static void _transpose(const Matrix3& A, Matrix3& out); -public: - - /** Optimized implementation of out = A.transpose(). It is safe (but slow) to call - with A and out possibly pointer equal to one another. - - Note that A.transpose() * v can be computed - more efficiently as v * A. - */ - inline static void transpose(const Matrix3& A, Matrix3& out) { - if (&A == &out) { - out = A.transpose(); - } else { - _transpose(A, out); - } - } - - /** Returns true if the rows and column L2 norms are 1.0 and the rows are orthogonal. */ - bool isOrthonormal() const; - - Matrix3 transpose () const; - bool inverse (Matrix3& rkInverse, float fTolerance = 1e-06) const; - Matrix3 inverse (float fTolerance = 1e-06) const; - float determinant () const; - - /** singular value decomposition */ - void singularValueDecomposition (Matrix3& rkL, Vector3& rkS, - Matrix3& rkR) const; - /** singular value decomposition */ - void singularValueComposition (const Matrix3& rkL, - const Vector3& rkS, const Matrix3& rkR); - - /** Gram-Schmidt orthonormalization (applied to columns of rotation matrix) */ - void orthonormalize(); - - /** orthogonal Q, diagonal D, upper triangular U stored as (u01,u02,u12) */ - void qDUDecomposition (Matrix3& rkQ, Vector3& rkD, - Vector3& rkU) const; - - float spectralNorm () const; - - /** matrix must be orthonormal */ - void toAxisAngle(Vector3& rkAxis, float& rfRadians) const; - - static Matrix3 fromDiagonal(const Vector3& d) { - return Matrix3(d.x, 0, 0, - 0, d.y, 0, - 0, 0, d.z); - } - - static Matrix3 fromAxisAngle(const Vector3& rkAxis, float fRadians); - - /** - * The matrix must be orthonormal. The decomposition is yaw*pitch*roll - * where yaw is rotation about the Up vector, pitch is rotation about the - * right axis, and roll is rotation about the Direction axis. - */ - bool toEulerAnglesXYZ (float& rfYAngle, float& rfPAngle, - float& rfRAngle) const; - bool toEulerAnglesXZY (float& rfYAngle, float& rfPAngle, - float& rfRAngle) const; - bool toEulerAnglesYXZ (float& rfYAngle, float& rfPAngle, - float& rfRAngle) const; - bool toEulerAnglesYZX (float& rfYAngle, float& rfPAngle, - float& rfRAngle) const; - bool toEulerAnglesZXY (float& rfYAngle, float& rfPAngle, - float& rfRAngle) const; - bool toEulerAnglesZYX (float& rfYAngle, float& rfPAngle, - float& rfRAngle) const; - static Matrix3 fromEulerAnglesXYZ (float fYAngle, float fPAngle, float fRAngle); - static Matrix3 fromEulerAnglesXZY (float fYAngle, float fPAngle, float fRAngle); - static Matrix3 fromEulerAnglesYXZ (float fYAngle, float fPAngle, float fRAngle); - static Matrix3 fromEulerAnglesYZX (float fYAngle, float fPAngle, float fRAngle); - static Matrix3 fromEulerAnglesZXY (float fYAngle, float fPAngle, float fRAngle); - static Matrix3 fromEulerAnglesZYX (float fYAngle, float fPAngle, float fRAngle); - - /** eigensolver, matrix must be symmetric */ - void eigenSolveSymmetric (float afEigenvalue[3], - Vector3 akEigenvector[3]) const; - - static void tensorProduct (const Vector3& rkU, const Vector3& rkV, - Matrix3& rkProduct); - std::string toString() const; - - static const float EPSILON; - - // Special values. - // The unguaranteed order of initialization of static variables across - // translation units can be a source of annoying bugs, so now the static - // special values (like Vector3::ZERO, Color3::WHITE, ...) are wrapped - // inside static functions that return references to them. - // These functions are intentionally not inlined, because: - // "You might be tempted to write [...] them as inline functions - // inside their respective header files, but this is something you - // must definitely not do. An inline function can be duplicated - // in every file in which it appears œóõ½ and this duplication - // includes the static object definition. Because inline functions - // automatically default to internal linkage, this would result in - // having multiple static objects across the various translation - // units, which would certainly cause problems. So you must - // ensure that there is only one definition of each wrapping - // function, and this means not making the wrapping functions inline", - // according to Chapter 10 of "Thinking in C++, 2nd ed. Volume 1" by Bruce Eckel, - // http://www.mindview.net/ - static const Matrix3& zero(); - static const Matrix3& identity(); - -protected: - - // support for eigensolver - void tridiagonal (float afDiag[3], float afSubDiag[3]); - bool qLAlgorithm (float afDiag[3], float afSubDiag[3]); - - // support for singular value decomposition - static const float ms_fSvdEpsilon; - static const int ms_iSvdMaxIterations; - static void bidiagonalize (Matrix3& kA, Matrix3& kL, - Matrix3& kR); - static void golubKahanStep (Matrix3& kA, Matrix3& kL, - Matrix3& kR); - - // support for spectral norm - static float maxCubicRoot (float afCoeff[3]); - -}; - - -//---------------------------------------------------------------------------- -/** v * M == M.transpose() * v */ -inline Vector3 operator* (const Vector3& rkPoint, const Matrix3& rkMatrix) { - Vector3 kProd; - - for (int r = 0; r < 3; ++r) { - kProd[r] = - rkPoint[0] * rkMatrix.elt[0][r] + - rkPoint[1] * rkMatrix.elt[1][r] + - rkPoint[2] * rkMatrix.elt[2][r]; - } - - return kProd; -} - - -} // namespace - -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/Matrix4.h b/externals/g3dlite/G3D.lib/include/G3D/Matrix4.h deleted file mode 100644 index 5bb6cecfdf9..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Matrix4.h +++ /dev/null @@ -1,206 +0,0 @@ -/** - @file Matrix4.h - - 4x4 matrix class - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-10-02 - @edited 2007-04-05 - */ - -#ifndef G3D_MATRIX4_H -#define G3D_MATRIX4_H - -#ifdef _MSC_VER -// Disable conditional expression is constant, which occurs incorrectly on inlined functions -# pragma warning (push) -# pragma warning( disable : 4127 ) -#endif - -#include "G3D/platform.h" -#include "G3D/debugAssert.h" -#include "G3D/Matrix3.h" -#include "G3D/Vector3.h" - -namespace G3D { - -/** - A 4x4 matrix. - - See also G3D::CoordinateFrame, G3D::Matrix3, G3D::Quat - */ -class Matrix4 { -private: - - float elt[4][4]; - - /** - Computes the determinant of the 3x3 matrix that lacks excludeRow - and excludeCol. - */ - float subDeterminant(int excludeRow, int excludeCol) const; - - // Hidden operators - bool operator<(const Matrix4&) const; - bool operator>(const Matrix4&) const; - bool operator<=(const Matrix4&) const; - bool operator>=(const Matrix4&) const; - -public: - Matrix4( - float r1c1, float r1c2, float r1c3, float r1c4, - float r2c1, float r2c2, float r2c3, float r2c4, - float r3c1, float r3c2, float r3c3, float r3c4, - float r4c1, float r4c2, float r4c3, float r4c4); - - /** - init should be row major. - */ - Matrix4(const float* init); - - /** - a is the upper left 3x3 submatrix and b is the upper right 3x1 submatrix. The last row of the created matrix is (0,0,0,1). - */ - Matrix4(const class Matrix3& upper3x3, const class Vector3& lastCol = Vector3::zero()); - - Matrix4(const class CoordinateFrame& c); - - Matrix4(const double* init); - - Matrix4(); - - /** Produces an RT transformation that nearly matches this Matrix4. - Because a Matrix4 may not be precisely a rotation and translation, - this may introduce error. */ - class CoordinateFrame approxCoordinateFrame() const; - - // Special values. - // Intentionally not inlined: see Matrix3::identity() for details. - static const Matrix4& identity(); - static const Matrix4& zero(); - - inline float* operator[](int r) { - debugAssert(r >= 0); - debugAssert(r < 4); - return (float*)&elt[r]; - } - - inline const float* operator[](int r) const { - debugAssert(r >= 0); - debugAssert(r < 4); - return (const float*)&elt[r]; - } - - inline operator float* () { - return (float*)&elt[0][0]; - } - - inline operator const float* () const { - return (const float*)&elt[0][0]; - } - - Matrix4 operator*(const Matrix4& other) const; - - class Matrix3 upper3x3() const; - - /** Homogeneous multiplication. Let k = M * [v w]^T. result = k.xyz() / k.w */ - class Vector3 homoMul(const class Vector3& v, float w) const; - - /** - Constructs an orthogonal projection matrix from the given parameters. - Near and far are the NEGATIVE of the near and far plane Z values - (to follow OpenGL conventions). - */ - static Matrix4 orthogonalProjection( - float left, - float right, - float bottom, - float top, - float nearval, - float farval); - - static Matrix4 orthogonalProjection( - const class Rect2D& rect, - float nearval, - float farval); - - static Matrix4 perspectiveProjection( - float left, - float right, - float bottom, - float top, - float nearval, - float farval); - - void setRow(int r, const class Vector4& v); - void setColumn(int c, const Vector4& v); - - /** @deprecated */ - Vector4 getRow(int r) const; - /** @deprecated */ - Vector4 getColumn(int c) const; - - const Vector4& row(int r) const; - Vector4 column(int c) const; - - Matrix4 operator*(const float s) const; - Vector4 operator*(const Vector4& vector) const; - - Matrix4 transpose() const; - - bool operator!=(const Matrix4& other) const; - bool operator==(const Matrix4& other) const; - - float determinant() const; - Matrix4 inverse() const; - - /** - Transpose of the cofactor matrix (used in computing the inverse). - Note: This is in fact only one type of adjoint. More generally, - an adjoint of a matrix is any mapping of a matrix which possesses - certain properties. This returns the so-called adjugate - or classical adjoint. - */ - Matrix4 adjoint() const; - Matrix4 cofactor() const; - - /** Serializes row-major */ - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); - - std::string toString() const; - - /** 3D scale matrix */ - inline static Matrix4 scale(const Vector3& v) { - return Matrix4(v.x, 0, 0, 0, - 0, v.y, 0, 0, - 0, 0, v.z, 0, - 0, 0, 0, 1); - } - - /** 3D scale matrix */ - inline static Matrix4 scale(float x, float y, float z) { - return scale(Vector3(x, y, z)); - } - - /** 3D scale matrix */ - inline static Matrix4 scale(float s) { - return scale(s,s,s); - } - - /** 3D translation matrix */ - inline static Matrix4 translation(const Vector3& v) { - return Matrix4(Matrix3::identity(), v); - } -}; - - - -} // namespace - -#ifdef _MSC_VER -# pragma warning (pop) -#endif - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/MeshAlg.h b/externals/g3dlite/G3D.lib/include/G3D/MeshAlg.h deleted file mode 100644 index be381eff117..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/MeshAlg.h +++ /dev/null @@ -1,718 +0,0 @@ -/** - @file MeshAlg.h - - Indexed Mesh algorithms. - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-09-14 - @edited 2008-07-30 -*/ - -#ifndef G3D_MESHALG_H -#define G3D_MESHALG_H - -#include "G3D/platform.h" -#include "G3D/Array.h" -#include "G3D/Vector3.h" -#include "G3D/CoordinateFrame.h" - -namespace G3D { - -/** - Indexed mesh algorithms. You have to build your own mesh class. -

- No mesh class is provided with G3D because there isn't an "ideal" - mesh format-- one application needs keyframed animation, another - skeletal animation, a third texture coordinates, a fourth - cannot precompute information, etc. Instead of compromising, this - class implements the hard parts of mesh computation and you can write - your own ideal mesh class on top of it. - */ -class MeshAlg { -public: - - enum Primitive {LINES, LINE_STRIP, TRIANGLES, TRIANGLE_STRIP, - TRIANGLE_FAN, QUADS, QUAD_STRIP, POINTS}; - - - /** Adjacency information for a vertex. - Does not contain the vertex position or normal, - which are stored in the MeshAlg::Geometry object. - Vertexs must be stored in an array - parallel to (indexed in the same way as) - MeshAlg::Geometry::vertexArray. - */ - class Vertex { - public: - Vertex() {} - - /** - Array of edges adjacent to this vertex. - Let e = edgeIndex[i]. - edge[(e >= 0) ? e : ~e].vertexIndex[0] == this - vertex index. - - Edges may be listed multiple times if they are - degenerate. - */ - Array edgeIndex; - - /** - Returns true if e or ~e is in the edgeIndex list. - */ - inline bool inEdge(int e) const { - return edgeIndex.contains(~e) || edgeIndex.contains(e); - } - - /** - Array of faces containing this vertex. Faces - may be listed multiple times if they are degenerate. - */ - Array faceIndex; - - inline bool inFace(int f) const { - debugAssert(f >= 0); - return faceIndex.contains(f); - } - }; - - - /** - Oriented, indexed triangle. - */ - class Face { - public: - Face(); - - /** - Used by Edge::faceIndex to indicate a missing face. - This is a large negative value. - */ - static const int NONE; - - - /** - Vertices in the face in counter-clockwise order. - Degenerate faces may include the same vertex multiple times. - */ - int vertexIndex[3]; - - inline bool containsVertex(int v) const { - return contains(vertexIndex, 3, v); - } - - /** - Edge indices in counter-clockwise order. Edges are - undirected, so it is important to know which way - each edge is pointing in a face. This is encoded - using negative indices. - - If edgeIndex[i] >= 0 then this face - contains the directed edge - between vertex indices - edgeArray[face.edgeIndex[i]].vertexIndex[0] - and - edgeArray[face.edgeIndex[i]].vertexIndex[1]. - - If edgeIndex[i] < 0 then - ~edgeIndex[i] (i.e. the two's - complement of) is used and this face contains the directed - edge between vertex indices - edgeArray[~face.edgeIndex[i]].vertexIndex[0] - and - edgeArray[~face.edgeIndex[i]].vertexIndex[1]. - - Degenerate faces may include the same edge multiple times. - */ - // Temporarily takes on the value Face::NONE during adjacency - // computation to indicate an edge that has not yet been assigned. - int edgeIndex[3]; - - inline bool containsEdge(int e) const { - if (e < 0) { - e = ~e; - } - return contains(edgeIndex, 3, e) || contains(edgeIndex, 3, ~e); - } - - /** Contains the forward edge e if e >= 0 and the backward edge - ~e otherwise. */ - inline bool containsDirectedEdge(int e) const { - return contains(edgeIndex, 3, e); - } - }; - - - /** Oriented, indexed edge */ - class Edge { - public: - Edge(); - - /** Degenerate edges may include the same vertex times. */ - int vertexIndex[2]; - - inline bool containsVertex(int v) const { - return contains(vertexIndex, 2, v); - } - - /** - The edge is directed forward in face 0 - backward in face 1. Face index of MeshAlg::Face::NONE - indicates a boundary (a.k.a. crack, broken) edge. - */ - int faceIndex[2]; - - /** Returns true if f is contained in the faceIndex array in either slot. - To see if it is forward in that face, just check edge.faceIndex[0] == f.*/ - inline bool inFace(int f) const { - return contains(faceIndex, 2, f); - } - - /** - Returns true if either faceIndex is NONE. - */ - inline bool boundary() const { - return (faceIndex[0] == Face::NONE) || - (faceIndex[1] == Face::NONE); - } - - /** - Returns the reversed edge. - */ - inline Edge reverse() const { - Edge e; - e.vertexIndex[0] = vertexIndex[1]; - e.vertexIndex[1] = vertexIndex[0]; - e.faceIndex[0] = faceIndex[1]; - e.faceIndex[1] = faceIndex[0]; - return e; - } - }; - - - /** - Convenient for passing around the per-vertex data that changes under - animation. The faces and edges are needed to interpret - these values. - */ - class Geometry { - public: - /** Vertex positions */ - Array vertexArray; - - /** Vertex normals */ - Array normalArray; - - /** - Assignment is optimized using SSE. - */ - Geometry& operator=(const Geometry& src); - - void clear() { - vertexArray.clear(); - normalArray.clear(); - } - }; - - /** - Given a set of vertices and a set of indices for traversing them - to create triangles, computes other mesh properties. - - Colocated vertices are treated as separate. To have - colocated vertices collapsed (necessary for many algorithms, - like shadowing), weld the mesh before computing adjacency. - - Recent change: In version 6.00, colocated vertices were automatically - welded by this routine and degenerate faces and edges were removed. That - is no longer the case. - - Where two faces meet, there are two opposite directed edges. These - are collapsed into a single bidirectional edge in the edgeArray. - If four faces meet exactly at the same edge, that edge will appear - twice in the array, and so on. If an edge is a boundary of the mesh - (i.e. if the edge has only one adjacent face) it will appear in the - array with one face index set to MeshAlg::Face::NONE. - - @param vertexGeometry %Vertex positions to use when deciding colocation. - @param indexArray Order to traverse vertices to make triangles - @param faceArray Output - @param edgeArray Output. Sorted so that boundary edges are at the end of the array. - @param vertexArray Output - */ - static void computeAdjacency( - const Array& vertexGeometry, - const Array& indexArray, - Array& faceArray, - Array& edgeArray, - Array& vertexArray); - - /** - @deprecated Use the other version of computeAdjacency, which takes Array. - @param facesAdjacentToVertex Output adjacentFaceArray[v] is an array of - indices for faces touching vertex index v - */ - static void computeAdjacency( - const Array& vertexArray, - const Array& indexArray, - Array& faceArray, - Array& edgeArray, - Array< Array >& facesAdjacentToVertex); - - /** - Computes some basic mesh statistics including: min, max mean and median, - edge lengths; and min, mean, median, and max face area. - - @param vertexGeometry %Vertex positions to use when deciding colocation. - @param indexArray Order to traverse vertices to make triangles - @param minEdgeLength Minimum edge length - @param meanEdgeLength Mean edge length - @param medianEdgeLength Median edge length - @param maxEdgeLength Max edge length - @param minFaceArea Minimum face area - @param meanFaceArea Mean face area - @param medianFaceArea Median face area - @param maxFaceArea Max face area - */ - static void computeAreaStatistics( - const Array& vertexArray, - const Array& indexArray, - double& minEdgeLength, - double& meanEdgeLength, - double& medianEdgeLength, - double& maxEdgeLength, - double& minFaceArea, - double& meanFaceArea, - double& medianFaceArea, - double& maxFaceArea); - -private: - /** - Computes the tangent space basis vectors for - a counter-clockwise oriented face. - - @cite Max McGuire - */ - static void computeTangentVectors( - const Vector3& normal, - const Vector3 position[3], - const Vector2 texCoord[3], - Vector3& tangent, - Vector3& binormal); - - /** Helper for weldAdjacency */ - static void weldBoundaryEdges( - Array& faceArray, - Array& edgeArray, - Array& vertexArray); - -public: - - /** - Computes tangent and binormal vectors, - which provide a (mostly) consistent - parameterization over the surface for - effects like bump mapping. In the resulting coordinate frame, - T = x (varies with texture s coordinate), B = y (varies with negative texture t coordinate), - and N = z for a right-handed coordinate frame. If a billboard is vertical on the screen - in view of the camera, the tangent space matches the camera's coordinate frame. - - The vertex, texCoord, tangent, and binormal - arrays are parallel arrays. - - The resulting tangent and binormal might not be exactly - perpendicular to each other. They are guaranteed to - be perpendicular to the normal. - - @cite Max McGuire - */ - static void computeTangentSpaceBasis( - const Array& vertexArray, - const Array& texCoordArray, - const Array& vertexNormalArray, - const Array& faceArray, - Array& tangent, - Array& binormal); - - /** @deprecated */ - static void computeNormals( - const Array& vertexArray, - const Array& faceArray, - const Array< Array >& adjacentFaceArray, - Array& vertexNormalArray, - Array& faceNormalArray); - - /** - Vertex normals are weighted by the area of adjacent faces. - Nelson Max showed this is superior to uniform weighting for - general meshes in jgt. - - @param vertexNormalArray Output. Unit length - @param faceNormalArray Output. Degenerate faces produce zero magnitude normals. Unit length - @see weld - */ - static void computeNormals( - const Array& vertexGeometry, - const Array& faceArray, - const Array& vertexArray, - Array& vertexNormalArray, - Array& faceNormalArray); - - /** Computes unit length normals in place using the other computeNormals methods. - If you already have a face array use another method; it will be faster. - @see weld*/ - static void computeNormals( - Geometry& geometry, - const Array& indexArray); - - /** - Computes face normals only. Significantly faster (especially if - normalize is false) than computeNormals. - @see weld - */ - static void computeFaceNormals( - const Array& vertexArray, - const Array& faceArray, - Array& faceNormals, - bool normalize = true); - - /** - Classifies each face as a backface or a front face relative - to the observer point P (which is at infinity when P.w = 0). - A face with normal exactly perpendicular to the observer vector - may be classified as either a front or a back face arbitrarily. - */ - static void identifyBackfaces( - const Array& vertexArray, - const Array& faceArray, - const Vector4& P, - Array& backface); - - /** A faster version of identifyBackfaces for the case where - face normals have already been computed */ - static void identifyBackfaces( - const Array& vertexArray, - const Array& faceArray, - const Vector4& P, - Array& backface, - const Array& faceNormals); - - /** - Welds nearby and colocated elements of the oldVertexArray together so that - newVertexArray contains no vertices within radius of one another. - Every vertex in newVertexPositions also appears in oldVertexPositions. - This is useful for downsampling meshes and welding cracks created by artist errors - or numerical imprecision. - - The two integer arrays map indices back and forth between the arrays according to: -

-     oldVertexArray[toOld[ni]] == newVertexArray[ni]
-     oldVertexArray[oi] == newVertexArray[toNew[ni]]
-     
- - Note that newVertexPositions is never longer than oldVertexPositions - and is shorter when vertices are welded. - - Welding with a large radius will effectively compute a lower level of detail for - the mesh. - - The welding method runs in roughly linear time in the length of oldVertexArray-- - a uniform spatial grid is used to achieve nearly constant time vertex collapses - for uniformly distributed vertices. - - It is sometimes desirable to keep the original vertex ordering but - identify the unique vertices. The following code computes - array canonical s.t. canonical[v] = first occurance of - a vertex near oldVertexPositions[v] in oldVertexPositions. - -
-        Array canonical(oldVertexPositions.size()), toNew, toOld;
-        computeWeld(oldVertexPositions, Array(), toNew, toOld, radius);
-        for (int v = 0; v < canonical.size(); ++v) {
-            canonical[v] = toOld[toNew[v]];
-        }
-     
- - See also G3D::MeshAlg::weldAdjacency. - - @cite The method is that described as the 'Grouper' in Baum, Mann, Smith, and Winget, - Making Radiosity Usable: Automatic Preprocessing and Meshing Techniques for - the Generation of Accurate Radiosity Solutions, Computer Graphics vol 25, no 4, July 1991. - - @deprecated Use weld. - */ - static void computeWeld( - const Array& oldVertexPositions, - Array& newVertexPositions, - Array& toNew, - Array& toOld, - double radius = G3D::fuzzyEpsilon); - - /** - Modifies the face, edge, and vertex arrays in place so that - colocated (within radius) vertices are treated as identical. - Note that the vertexArray and corresponding geometry will - contain elements that are no longer used. In the vertexArray, - these elements are initialized to MeshAlg::Vertex() but not - removed (because removal would change the indexing). - - This is a good preprocessing step for algorithms that are only - concerned with the shape of a mesh (e.g. cartoon rendering, fur, shadows) - and not the indexing of the vertices. - - Use this method when you have already computed adjacency information - and want to collapse colocated vertices within that data without - disturbing the actual mesh vertices or indexing scheme. - - If you have not computed adjacency already, use MeshAlg::computeWeld - instead and compute adjacency information after welding. - - @deprecated Use weld. - - @param faceArray Mutated in place. Size is maintained (degenerate - faces are not removed). - @param edgeArray Mutated in place. May shrink if boundary edges - are welded together. - @param vertexArray Mutated in place. Size is maintained (duplicate - vertices contain no adjacency info). - */ - static void weldAdjacency( - const Array& originalGeometry, - Array& faceArray, - Array& edgeArray, - Array& vertexArray, - double radius = G3D::fuzzyEpsilon); - - - /** - Counts the number of edges (in an edge array returned from - MeshAlg::computeAdjacency) that have only one adjacent face. - */ - static int countBoundaryEdges(const Array& edgeArray); - - - /** - Generates an array of integers from start to start + n - 1 that have run numbers - in series then omit the next skip before the next run. Useful for turning - a triangle list into an indexed face set. - - Example: -
-       createIndexArray(10, x);
-       // x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
-
-       createIndexArray(5, x, 2);
-       // x = [2, 3, 4, 5, 6, 7] 
-
-       createIndexArray(6, x, 0, 2, 1);
-       // x = [0, 1, 3, 4, 6, 7]
-     
- */ - static void createIndexArray( - int n, - Array& array, - int start = 0, - int run = 1, - int skip = 0); - - /** - Computes a conservative, near-optimal axis aligned bounding box and sphere. - - @cite The bounding sphere uses the method from J. Ritter. An effcient bounding sphere. In Andrew S. Glassner, editor, Graphics Gems. Academic Press, Boston, MA, 1990. - - */ - static void computeBounds(const Array& vertex, class Box& box, class Sphere& sphere); - - /** Computes bounds for a subset of the vertices. It is ok if vertices appear more than once in the index array. */ - static void computeBounds(const Array& vertex, const Array& index, class Box& box, class Sphere& sphere); - - /** - Mutates geometry, texCoord, and indexArray so that the output has collocated vertices collapsed (welded). - - @param vertices Input and output - @param textureCoords Input and output - @param normals Output only - @param indices Input and output. This is an array of trilist indices. - @param oldToNewIndex Output argument - @param normalSmoothingAngle Varies from 0 (flat shading) to toRadians(180) for extremely smooth shading. Default is toRadians(70) - */ - static void weld( - Array& vertices, - Array& textureCoords, - Array& normals, - Array*>& indices, - float normalSmoothingAngle = toRadians(70.0f), - float vertexWeldRadius = 0.0001f, - float textureWeldRadius = 0.0001f, - float normalWeldRadius = 0.01f); - - inline static void weld( - Array& vertices, - Array& textureCoords, - Array& normals, - Array& indices, - float normalSmoothingAngle = toRadians(70.0f), - float vertexWeldRadius = 0.0002f, - float textureWeldRadius = 0.00001f, - float normalWeldRadius = 0.00001f) { - - Array*> meta; - meta.append(&indices); - weld(vertices, textureCoords, normals, meta, normalSmoothingAngle, vertexWeldRadius, textureWeldRadius, normalWeldRadius); - } - - /** - In debug mode, asserts that the adjacency references between the - face, edge, and vertex array are consistent. - */ - static void debugCheckConsistency( - const Array& faceArray, - const Array& edgeArray, - const Array& vertexArray); - - /** - Generates a unit square in the X-Z plane composed of a grid of wCells x hCells - squares and then transforms it by xform. - - @param vertex Output vertices - @param texCoord Output texture coordinates - @param index Output triangle list indices - @param textureScale Lower-right texture coordinate - @param spaceCentered If true, the coordinates generated are centered at the origin before the transformation. - @param twoSided If true, matching top and bottom planes are generated. - */ - static void generateGrid( - Array& vertex, - Array& texCoord, - Array& index, - int wCells = 10, - int hCells = 10, - const Vector2& textureScale = Vector2(1,1), - bool spaceCentered = true, - bool twoSided = true, - const CoordinateFrame& xform = CoordinateFrame()); - - /** Converts quadlist (QUADS), - triangle fan (TRIANGLE_FAN), - tristrip(TRIANGLE_STRIP), and quadstrip (QUAD_STRIP) indices into - triangle list (TRIANGLES) indices and appends them to outIndices. */ - template - static void toIndexedTriList( - const Array& inIndices, - MeshAlg::Primitive inType, - Array& outIndices) { - - debugAssert( - inType == MeshAlg::TRIANGLE_STRIP || - inType == MeshAlg::TRIANGLE_FAN || - inType == MeshAlg::QUADS || - inType == MeshAlg::QUAD_STRIP); - - const int inSize = inIndices.size(); - - switch(inType) { - case MeshAlg::TRIANGLE_FAN: - { - debugAssert(inSize >= 3); - - int N = outIndices.size(); - outIndices.resize(N + (inSize - 2) * 3); - - for (IndexType i = 1, outIndex = N; i <= (inSize - 2); ++i, outIndex += 3) { - outIndices[outIndex] = inIndices[0]; - outIndices[outIndex + 1] = inIndices[i]; - outIndices[outIndex + 2] = inIndices[i + 1]; - } - - break; - } - - case MeshAlg::TRIANGLE_STRIP: - { - debugAssert(inSize >= 3); - - int N = outIndices.size(); - outIndices.resize(N + (inSize - 2) * 3); - - bool atEven = false; - for (IndexType i = 0, outIndex = N; i <= (inSize - 2); ++i, outIndex += 3) { - if (atEven) { - outIndices[outIndex] = inIndices[i + 1]; - outIndices[outIndex + 1] = inIndices[i]; - outIndices[outIndex + 2] = inIndices[i + 2]; - atEven = false; - } else { - outIndices[outIndex] = inIndices[i]; - outIndices[outIndex + 1] = inIndices[i + 1]; - outIndices[outIndex + 2] = inIndices[i + 2]; - atEven = true; - } - } - - break; - } - - case MeshAlg::QUADS: - { - debugAssert(inIndices.size() >= 4); - - int N = outIndices.size(); - outIndices.resize(N + (inSize / 4) * 3); - - for (IndexType i = 0, outIndex = N; i <= (inSize - 4); i += 4, outIndex += 6) { - outIndices[outIndex] = inIndices[i]; - outIndices[outIndex + 1] = inIndices[i + 1]; - outIndices[outIndex + 2] = inIndices[i + 3]; - outIndices[outIndex + 3] = inIndices[i + 1]; - outIndices[outIndex + 4] = inIndices[i + 2]; - outIndices[outIndex + 5] = inIndices[i + 3]; - } - - break; - } - - case MeshAlg::QUAD_STRIP: - { - debugAssert(inIndices.size() >= 4); - - int N = outIndices.size(); - outIndices.resize(N + (inSize - 2) * 3); - - for (IndexType i = 0, outIndex = N; i <= (inSize - 2); i += 2, outIndex += 6) { - outIndices[outIndex] = inIndices[i]; - outIndices[outIndex + 1] = inIndices[i + 1]; - outIndices[outIndex + 2] = inIndices[i + 2]; - outIndices[outIndex + 3] = inIndices[i + 2]; - outIndices[outIndex + 4] = inIndices[i + 1]; - outIndices[outIndex + 5] = inIndices[i + 3]; - } - break; - } - default: - alwaysAssertM(false, "Illegal argument"); - } - } - -protected: - - /** - Helper for computeAdjacency. If a directed edge with index e already - exists from i0 to i1 then e is returned. If a directed edge with index e - already exists from i1 to i0, ~e is returned (the complement) and - edgeArray[e] is set to f. Otherwise, a new edge is created from i0 to i1 - with first face index f and its index is returned. - - @param vertexArray Vertex positions to use when deciding colocation. - - @param area Area of face f. When multiple edges of the same direction - are found between the same vertices (usually because of degenerate edges) - the face with larger area is kept in the edge table. - */ - static int findEdgeIndex( - const Array& vertexArray, - Array& geometricEdgeArray, - int i0, int i1, int f, double area); -}; -} -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/MeshBuilder.h b/externals/g3dlite/G3D.lib/include/G3D/MeshBuilder.h deleted file mode 100644 index 3256c0de823..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/MeshBuilder.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - @file MeshBuilder.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2002-02-27 - @edited 2004-10-04 - */ -#ifndef G3D_MESHBUILDER_H -#define G3D_MESHBUILDER_H - -#include "G3D/platform.h" -#include "G3D/Array.h" -#include "G3D/Vector3.h" -#include "G3D/Triangle.h" - -namespace G3D { - -/** - Allows creation of optimized watertight meshes from unoptimized polygon soups. - See also G3D::MeshAlg for algorithms that operate on the output. - */ -class MeshBuilder { -public: - - /** - Set setWeldRadius to AUTO_WELD to weld vertices closer than 1/2 - the smallest edge length in a model. - */ - enum {AUTO_WELD = -100}; - -private: - /** Indices of vertices in or near a grid cell. */ - typedef Array List; - - std::string name; - - /** - All of the triangles, as a long triangle list. - */ - Array triList; - - void centerTriList(); - void computeBounds(Vector3& min, Vector3& max); - - bool _twoSided; - - /** Collapse radius */ - double close; - -public: - - inline MeshBuilder(bool twoSided = false) : _twoSided(twoSided), close(AUTO_WELD) {} - - /** Writes the model to the arrays, which can then be used with - G3D::IFSModel::save and G3D::MeshAlg */ - void commit(std::string& name, Array& indexArray, Array& vertexArray); - - /** - Adds a new triangle to the model. (Counter clockwise) - */ - void addTriangle(const Vector3& a, const Vector3& b, const Vector3& c); - - /** - Adds two new triangles to the model. (Counter clockwise) - */ - void addQuad(const Vector3& a, const Vector3& b, const Vector3& c, const Vector3& d); - - void addTriangle(const Triangle& t); - - void setName(const std::string& n); - - /** Vertices within this distance are considered identical. - Use AUTO_WELD (the default) to have the distance be a function of the model size.*/ - void setWeldRadius(double r) { - close = r; - } -}; - -} // namespace - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/NetAddress.h b/externals/g3dlite/G3D.lib/include/G3D/NetAddress.h deleted file mode 100644 index 8ed20a06690..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/NetAddress.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef G3D_NETADDRESS_H -#define G3D_NETADDRESS_H - -#include "G3D/platform.h" -#include "G3D/Table.h" - -/** These control the version of Winsock used by G3D. - Version 2.0 is standard for G3D 6.09 and later. - Version 1.1 is standard for G3D 6.08 and earlier. - */ -#define G3D_WINSOCK_MAJOR_VERSION 2 -#define G3D_WINSOCK_MINOR_VERSION 0 - -#ifdef G3D_WIN32 -# if (G3D_WINSOCK_MAJOR_VERSION == 2) -# include -# elif (G3D_WINSOCK_MAJOR_VERSION == 1) -# include -# endif -#else -# include -# include -# include -# ifndef SOCKADDR_IN -# define SOCKADDR_IN struct sockaddr_in -# endif -# ifndef SOCKET -# define SOCKET int -# endif -#endif - -#include "G3D/g3dmath.h" - -namespace G3D { - -class NetAddress { -private: - friend class NetworkDevice; - friend class LightweightConduit; - friend class ReliableConduit; - - /** Host byte order */ - void init(uint32 host, uint16 port); - void init(const std::string& hostname, uint16 port); - NetAddress(const SOCKADDR_IN& a); - NetAddress(const struct in_addr& addr, uint16 port = 0); - - SOCKADDR_IN addr; - -public: - /** - In host byte order - */ - NetAddress(uint32 host, uint16 port = 0); - - /** - @param port Specified in host byte order (i.e., don't worry about endian issues) - */ - NetAddress(const std::string& hostname, uint16 port); - - /** - @param hostnameAndPort in the form "hostname:port" or "ip:port" - */ - NetAddress(const std::string& hostnameAndPort); - - /** - @deprecated Use G3D::NetworkDevice::broadcastAddressArray() - - @brief Creates a UDP broadcast address for use with a - G3D::LightweightConduit. - - UDP broadcast allows one machine to send a packet to all machines - on the same local network. The IP portion of the address is - 0xFFFFFFFF, which indicates "broadcast" to the underlying socket - API. This feature is not available with the connection-based TCP - protocol abstracted by G3D::ReliableConduit; use multisend - instead. - */ - static NetAddress broadcastAddress(uint16 port); - - NetAddress(); - - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); - - /** @brief Returns true if this is not an illegal address. */ - bool ok() const; - - /** @brief Returns a value in host format (i.e., don't worry about - endian issues) */ - inline uint32 ip() const { - return ntohl(addr.sin_addr.s_addr); - //return ntohl(addr.sin_addr.S_un.S_addr); - } - - inline uint16 port() const { - return ntohs(addr.sin_port); - } - - std::string ipString() const; - std::string toString() const; - -}; - -std::ostream& operator<<(std::ostream& os, const NetAddress&); - -} // namespace G3D - -template <> struct HashTrait { - static size_t hashCode(const G3D::NetAddress& key) { - return static_cast(key.ip() + (static_cast(key.port()) << 16)); - } -}; - -namespace G3D { - -/** - Two addresses may point to the same computer but be != because - they have different IP's. - */ -inline bool operator==(const NetAddress& a, const NetAddress& b) { - return (a.ip() == b.ip()) && (a.port() == b.port()); -} - - -inline bool operator!=(const NetAddress& a, const NetAddress& b) { - return !(a == b); -} - -} // namespace G3D - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/NetworkDevice.h b/externals/g3dlite/G3D.lib/include/G3D/NetworkDevice.h deleted file mode 100644 index faffa56d690..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/NetworkDevice.h +++ /dev/null @@ -1,738 +0,0 @@ -/** - @file NetworkDevice.h - - These classes abstract networking from the socket level to a - serialized messaging style that is more appropriate for games. The - performance has been tuned for sending many small messages. The - message protocol contains a header that prevents them from being used - with raw UDP/TCP (e.g. connecting to an HTTP server). - - LightweightConduit and ReliableConduits have different interfaces - because they have different semantics. You would never want to - interchange them without rewriting the surrounding code. - - NetworkDevice creates conduits because they need access to a global - log pointer and because I don't want non-reference counted conduits - being created. - - Be careful with threads and reference counting. The reference - counters are not threadsafe, and are also not updated correctly if a - thread is explicitly killed. Since the conduits will be passed by - const XConduitRef& most of the time this doesn't appear as a major - problem. With non-blocking conduits, you should need few threads - anyway. - - LightweightConduits preceed each message with a 4-byte host order - unsigned integer that is the message type. This does not appear in - the message serialization/deserialization. - - ReliableConduits preceed each message with two 4-byte host order - unsigned integers. The first is the message type and the second - indicates the length of the rest of the data. The size does not - include the size of the header itself. The minimum message is 9 - bytes:a 4-byte type, a 4-byte header equal to "1", and one byte of data. - - @maintainer Morgan McGuire, morgan@graphics3d.com - @created 2002-11-22 - @edited 2006-11-25 - */ - -#ifndef G3D_NETWORKDEVICE_H -#define G3D_NETWORKDEVICE_H - -#include "G3D/platform.h" -#include "G3D/NetAddress.h" - -#include -#include -#include "G3D/g3dmath.h" - -#include "G3D/ReferenceCount.h" -#include "G3D/Array.h" -#include "G3D/BinaryOutput.h" - -namespace G3D { - -class TextOutput; - -class Conduit : public ReferenceCountedObject { -protected: - friend class NetworkDevice; - friend class NetListener; - - uint64 mSent; - uint64 mReceived; - uint64 bSent; - uint64 bReceived; - - SOCKET sock; - - /** - Used for serialization. One per socket - to make this threadsafe. - */ - BinaryOutput binaryOutput; - - Conduit(); - -public: - - virtual ~Conduit(); - uint64 bytesSent() const; - uint64 messagesSent() const; - uint64 bytesReceived() const; - uint64 messagesReceived() const; - - /** - If true, receive will return true. - */ - virtual bool messageWaiting(); - - /** - Returns the type of the waiting message (i.e. the type supplied - with send). The return value is zero when there is no message - waiting. - - One way to use this is to have a Table mapping message types to - pre-allocated subclasses so receiving looks like: - -
-         // My base class for messages.
-         class Message {
-             virtual void serialize(BinaryOutput&) const;
-             virtual void deserialize(BinaryInput&);
-             virtual void process() = 0;
-         };
-
-         Message* m = table[conduit->waitingMessageType()];
-         conduit->receive(m);
-         m->process();
-     
- - Another is to simply switch on the message type: - -
-         switch (conduit->waitingMessageType()) {
-         case 0:
-            // No message
-            break;
-
-         case ENTITY_SPAWN_MSG:
-            {
-               EntitySpawnMsg m;
-               condiut->receive(m);
-               spawnEntity(m.id, m.position, m.modelID);
-            }
-            break;
-            ...
-         }
-      
- */ - virtual uint32 waitingMessageType() = 0; - - /** Returns true if the connection is ok. */ - bool ok() const; -}; - -typedef ReferenceCountedPointer ReliableConduitRef; - -#ifdef __GNUC__ -// Workaround for a known bug in gcc 4.x where htonl produces -// a spurrious warning. -// http://gcc.gnu.org/ml/gcc-bugs/2005-10/msg03270.html -uint32 gcchtonl(uint32); -#endif - -// Messaging and stream APIs must be supported on a single class because -// sometimes an application will switch modes on a single socket. For -// example, when transferring 3D level geometry during handshaking with -// a game server. -/** - A conduit that guarantees messages will arrive, intact and in order. - Create on the client using NetworkDevice::createReliableConduit and - on the server using NetListener::waitForConnection. Set the reference - counted pointer to NULL to disconnect. - - To construct a ReliableConduit: -
    -
  1. Create a G3D::NetworkDevice (if you are using G3D::GApp, it creates - one for you) on the client and on the server. -
  2. On the server, create a G3D::NetListener using - G3D::NetworkDevice::createListener -
  3. On the server, invoke G3D::NetListener::waitForConnection. -
  4. On the client, call G3D::NetworkDevice::createReliableConduit. - You will need the server's G3D::NetAddress. Consider using - G3D::DiscoveryClient to find it via broadcasting. -
- - */ -class ReliableConduit : public Conduit { -private: - friend class NetworkDevice; - friend class NetListener; - - enum State {RECEIVING, HOLDING, NO_MESSAGE} state; - - NetAddress addr; - - /** - Type of the incoming message. - */ - uint32 messageType; - - /** - Total size of the incoming message (read from the header). - */ - uint32 messageSize; - - /** Shared buffer for receiving messages. */ - void* receiveBuffer; - - /** Total size of the receiveBuffer. */ - size_t receiveBufferTotalSize; - - /** Size occupied by the current message... so far. This will be - equal to messageSize when the whole message has arrived. - */ - size_t receiveBufferUsedSize; - - ReliableConduit(const NetAddress& addr); - - ReliableConduit(const SOCKET& sock, - const NetAddress& addr); - - template static void serializeMessage - (uint32 t, const T& m, BinaryOutput& b) { - - b.writeUInt32(t); - - // Reserve space for the 4 byte size header - b.writeUInt32(0); - - size_t L = b.length(); - m.serialize(b); - if ((size_t)b.length() == L) { - // No data was created by serialization. - // We need to send at least one byte because receive assumes that - // a zero length message is an error. - b.writeUInt8(0xFF); - } - - uint32 len = b.size() - 8; - - // We send the length first to tell recv how much data to read. - // Here we abuse BinaryOutput a bit and write directly into - // its buffer, violating the abstraction. - // Note that we write to the second set of 4 bytes, which is - // the size field. - uint32* lenPtr = ((uint32*)b.getCArray()) + 1; - #if defined(__GNUC__) - *lenPtr = gcchtonl(len); - #else - *lenPtr = htonl(len); - #endif - } - - - void sendBuffer(const BinaryOutput& b); - - /** Accumulates whatever part of the message (not the header) is - still waiting on the socket into the receiveBuffer during - state = RECEIVING mode. Closes the socket if anything goes - wrong. When receiveBufferUsedSize == messageSize, the entire - message has arrived. */ - void receiveIntoBuffer(); - - /** Receives the messageType and messageSize from the socket. */ - void receiveHeader(); - -public: - - /** - Client invokes this to connect to a server. The call blocks until the - conduit is opened. The conduit will not be ok() if it fails. - */ - static ReliableConduitRef create(const NetAddress& address); - - /** Closes the socket. */ - ~ReliableConduit(); - - - // The message is actually copied from the socket to an internal buffer during - // this call. Receive only deserializes. - virtual bool messageWaiting(); - - /** - Serializes the message and schedules it to be sent as soon as possible, - and then returns immediately. The message can be any class with - a serialize and deserialize method. On the receiving side, - use G3D::ReliableConduit::waitingMessageType() to detect the incoming - message and then invoke G3D::ReliableConduit::receive(msg) where msg - is of the same class as the message that was sent. - - The actual data sent across the network is preceeded by the - message type and the size of the serialized message as a 32-bit - integer. The size is sent because TCP is a stream protocol and - doesn't have a concept of discrete messages. - */ - template inline void send(uint32 type, const T& message) { - binaryOutput.reset(); - serializeMessage(type, message, binaryOutput); - sendBuffer(binaryOutput); - } - - /** Sends an empty message with the given type. Useful for sending - commands that have no parameters. */ - void send(uint32 type); - - /** Send the same message to a number of conduits. Useful for sending - data from a server to many clients (only serializes once). */ - template - inline static void multisend( - const Array& array, - uint32 type, - const T& m) { - - if (array.size() > 0) { - array[0]->binaryOutput.reset(); - serializeMessage(type, m, array[0]->binaryOutput); - - for (int i = 0; i < array.size(); ++i) { - array[i]->sendBuffer(array[0]->binaryOutput); - } - } - } - - virtual uint32 waitingMessageType(); - - /** - If a message is waiting, deserializes the waiting message into - message and returns true, otherwise returns false. You can - determine the type of the message (and therefore, the class - of message) using G3D::ReliableConduit::waitingMessageType(). - */ - template inline bool receive(T& message) { - if (! messageWaiting()) { - return false; - } - - debugAssert(state == HOLDING); - // Deserialize - BinaryInput b((uint8*)receiveBuffer, receiveBufferUsedSize, G3D_LITTLE_ENDIAN, BinaryInput::NO_COPY); - message.deserialize(b); - - // Don't let anyone read this message again. We leave the buffer - // allocated for the next caller, however. - receiveBufferUsedSize = 0; - state = NO_MESSAGE; - messageType = 0; - messageSize = 0; - - // Potentially read the next message. - messageWaiting(); - - return true; - } - - /** Removes the current message from the queue. */ - inline void receive() { - if (! messageWaiting()) { - return; - } - receiveBufferUsedSize = 0; - state = NO_MESSAGE; - messageType = 0; - messageSize = 0; - - // Potentially read the next message. - messageWaiting(); - } - - NetAddress address() const; -}; - - -typedef ReferenceCountedPointer LightweightConduitRef; - -/** - Provides fast but unreliable transfer of messages. On a LAN, - LightweightConduit will probably never drop messages but you - might get your messages out of order. On an internet - connection it might drop messages altogether. Messages are never - corrupted, however. LightweightConduit requires a little less setup - and overhead than ReliableConduit. ReliableConduit guarantees - message delivery and order but requires a persistent connection. - - To set up a LightweightConduit (assuming you have already made - subclasses of G3D::NetMessage based on your application's - pcommunication protocol): - -[Server Side] -
    -
  1. Call LightweightConduit::create(port, true, false), -where port is the port on which you will receive messages. - -
  2. Poll LightweightConduit::messageWaiting from your main loop. When -it is true (or, equivalently, when LightweightConduit::waitingMessageType -is non-zero) there is an incoming message. - -
  3. To read the incoming message, call LightweightConduit::receive with -the appropriate class type, which mist have a deserialize method. -LightweightConduit::waitingMessageType tells you what class is -needed (you make up your own message constants for your program; numbers -under 1000 are reserved for G3D's internal use). - -
  4. When done, simply set the G3D::LightweightConduitRef to NULL or let -it go out of scope and the conduit cleans itself up automatically. -
- -[Client Side] -
    -
  1. Call G3D::LightweightConduit::create(). If you will -broadcast to all servers on a LAN, set the third optional argument to -true (the default is false for no broadcast). You can also set up the -receive port as if it was a server to send and receive from a single -LightweightConduit. - -
  2. To send, call G3D::LightweightConduit::send with the target address -and a pointer to an instance of the message you want to send. - -
  3. When done, simply set the G3D::LightweightConduitRef to NULL or let -it go out of scope and the conduit cleans itself up automatically. - -
- */ -class LightweightConduit : public Conduit { -private: - friend class NetworkDevice; - - /** - True when waitingForMessageType has read the message - from the network into messageType/messageStream. - */ - bool alreadyReadMessage; - - /** - Origin of the received message. - */ - NetAddress messageSender; - - /** - The type of the last message received. - */ - uint32 messageType; - - /** - The message received (the type has already been read off). - */ - Array messageBuffer; - - LightweightConduit(uint16 receivePort, bool enableReceive, bool enableBroadcast); - - void sendBuffer(const NetAddress& a, BinaryOutput& b); - - /** Maximum transmission unit (packet size in bytes) for this socket. - May vary between sockets. */ - int MTU; - - - template - void serializeMessage( - uint32 type, - const T& m, - BinaryOutput& b) const { - - debugAssert(type != 0); - b.writeUInt32(type); - m.serialize(b); - b.writeUInt32(1); - - debugAssertM(b.size() < MTU, - format("This LightweightConduit is limited to messages of " - "%d bytes (Ethernet hardware limit; this is the " - "'UDP MTU')", maxMessageSize())); - - if (b.size() >= MTU) { - throw LightweightConduit::PacketSizeException( - format("This LightweightConduit is limited to messages of " - "%d bytes (Ethernet hardware limit; this is the " - "'UDP MTU')", maxMessageSize()), - b.size() - 4, // Don't count the type header - maxMessageSize()); - } - } - -public: - - static LightweightConduitRef create(uint16 receivePort, bool enableReceive, bool enableBroadcast); - - class PacketSizeException { - public: - std::string message; - int serializedPacketSize; - int maxMessageSize; - - inline PacketSizeException(const std::string& m, int s, int b) : - message(m), - serializedPacketSize(s), - maxMessageSize(b) {} - }; - - /** Closes the socket. */ - ~LightweightConduit(); - - /** The maximum length of a message that can be sent - (G3D places a small header at the front of each UDP packet; - this is already taken into account by the value returned). - */ - inline int maxMessageSize() const { - return MTU - 4; - } - - - template inline void send(const NetAddress& a, uint32 type, const T& msg) { - binaryOutput.reset(); - serializeMessage(type, msg, binaryOutput); - sendBuffer(a, binaryOutput); - } - - /** Send the same message to multiple addresses (only serializes once). - Useful when server needs to send to a known list of addresses - (unlike direct UDP broadcast to all addresses on the subnet) */ - template inline void send(const Array& a, uint32 type, const T& m) { - binaryOutput.reset(); - serializeMessage(type, m, binaryOutput); - - for (int i = 0; i < a.size(); ++i) { - sendBuffer(a[i], binaryOutput); - } - } - - bool receive(NetAddress& sender); - - template inline bool receive(NetAddress& sender, T& message) { - bool r = receive(sender); - if (r) { - BinaryInput b((messageBuffer.getCArray() + 4), - messageBuffer.size() - 4, - G3D_LITTLE_ENDIAN, BinaryInput::NO_COPY); - message.deserialize(b); - } - - return r; - } - - inline bool receive() { - static NetAddress ignore; - return receive(ignore); - } - - virtual uint32 waitingMessageType(); - - - virtual bool messageWaiting(); -}; - -/////////////////////////////////////////////////////////////////////////////// - -typedef ReferenceCountedPointer NetListenerRef; - -/** - Runs on the server listening for clients trying to make reliable connections. - */ -class NetListener : public ReferenceCountedObject { -private: - - friend class NetworkDevice; - - SOCKET sock; - - /** Port is in host byte order. */ - NetListener(uint16 port); - -public: - - static NetListenerRef create(const uint16 port); - - ~NetListener(); - - /** Block until a connection is received. Returns NULL if - something went wrong. */ - ReliableConduitRef waitForConnection(); - - /** True if a client is waiting (i.e. waitForConnection will - return immediately). */ - bool clientWaiting() const; - - bool ok() const; -}; - - -/////////////////////////////////////////////////////////////////////////////// - -/** - @brief Abstraction of network (socket) functionality. - - An abstraction over sockets that provides a message-based network - infrastructure optimized for sending many small (~500 bytes) messages. - All functions always return immediately. - - Create only one NetworkDevice per process (a WinSock restriction). - - NetworkDevice is technically not thread safe. However, as long as - you use different conduits on different threads (or lock conduits - before sending), you will encounter no problems sharing the single - NetworkDevice across multiple threads. That is, do not invoke the same - Conduit's send or receive method on two threads at once. - - This assumes that the underlying WinSock/BSD sockets implementation - is thread safe. That is not guaranteed, but in practice seems - to always be true (see - http://tangentsoft.net/wskfaq/intermediate.html#threadsafety) - -
- - IP networks use "network byte order" (big-endian) for - communicating integers. "Host byte order" is the endian-ness of - the local machine (typically little-endian; see - System::endian). The C functions htonl() and ntohl() convert 32-bit - values between these formats. G3D only ever exposes host byte order, - so programmers rarely need to be aware of the distinction. - - */ -class NetworkDevice { -public: - - /** @brief Description of an ethernet or wireless ethernet adapter.*/ - class EthernetAdapter { - public: - /** Reverse-DNS of the ip address.*/ - std::string hostname; - - /** Name of the adapter */ - std::string name; - - /** IP address in host byte order.*/ - uint32 ip; - - /** Subnet mask in host byte order.*/ - uint32 subnet; - - /** UDP broadcast address in host byte order.*/ - uint32 broadcast; - - /** MAC (hardware) address, if known */ - uint8 mac[6]; - - EthernetAdapter(); - - /** Produces a text description of this adapter */ - void describe(TextOutput& t) const; - }; - -private: - - friend class Conduit; - friend class LightweightConduit; - friend class ReliableConduit; - friend class NetListener; - - bool initialized; - - Array m_adapterArray; - - /** Broadcast addresses available on this machine, - extracted from m_adapterArray.*/ - Array m_broadcastAddresses; - - /** Utility method. */ - void closesocket(SOCKET& sock) const; - - /** Utility method. Returns true on success.*/ - bool bind(SOCKET sock, const NetAddress& addr) const; - - /** The global instance */ - static NetworkDevice* s_instance; - - NetworkDevice(); - - bool init(); - - void _cleanup(); - - /** Called from init to update m_adapterArray and - m_broadcastAddresses. */ - void addAdapter(const EthernetAdapter& a); - -public: - - /** Prints an IP address to a string. - @param ip In host byte order.*/ - static std::string formatIP(uint32 ip); - - /** Prints a MAC address to a string. */ - static std::string formatMAC(const uint8 mac[6]); - - ~NetworkDevice(); - - /** Returns the available ethernet adapters for the current - machine that are online. Does not include the loopback adapter - for localhost.*/ - inline const Array& adapterArray() const { - return m_adapterArray; - } - - /** Returns the (unique) IP addresses for UDP broadcasting - extracted from adapterArray(). All are in host byte order. */ - inline const Array& broadcastAddressArray() const { - return m_broadcastAddresses; - } - - /** - Returns NULL if there was a problem initializing the network. - */ - static NetworkDevice* instance(); - - /** - Shuts down the network device (destroying the global instance). - */ - static void cleanup(); - - /** - Prints a human-readable description of this machine - to the text output stream. - */ - void describeSystem( - TextOutput& t); - - void describeSystem( - std::string& s); - - /** Returns the name (or one of the names) of this computer */ - std::string localHostName() const; - - /** There is often more than one address for the local host. This - returns all of them. - @deprecated Use adapterArray() - */ - void localHostAddresses(Array& array) const; -}; - - -#ifdef __GNUC__ -inline uint32 gcchtonl(uint32 x) { - // This pragma fools gcc into surpressing all error messages, - // including the bogus one that it creates for htonl -# pragma GCC system_header - return htonl(x); -} -#endif - -} // G3D namespace - -#ifndef _WIN32 -#undef SOCKADDR_IN -#undef SOCKET -#endif - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/PhysicsFrame.h b/externals/g3dlite/G3D.lib/include/G3D/PhysicsFrame.h deleted file mode 100644 index 44eedb6846e..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/PhysicsFrame.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - @file PhysicsFrame.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2002-07-08 - @edited 2006-01-10 -*/ - -#ifndef G3D_PHYSICSFRAME_H -#define G3D_PHYSICSFRAME_H - -#include "G3D/platform.h" -#include "G3D/Vector3.h" -#include "G3D/Matrix3.h" -#include "G3D/Quat.h" -#include "G3D/CoordinateFrame.h" -#include -#include - - -namespace G3D { - -/** - An RT transformation using a quaternion; suitable for - physics integration. - - This interface is in "Beta" and will change in the next release. - */ -class PhysicsFrame { -public: - - Quat rotation; - - /** - Takes object space points to world space. - */ - Vector3 translation; - - /** - Initializes to the identity frame. - */ - PhysicsFrame(); - - /** - Purely translational force - */ - PhysicsFrame(const Vector3& translation) : translation(translation) {} - - PhysicsFrame(const CoordinateFrame& coordinateFrame); - - /** Compose: create the transformation that is other followed by this.*/ - PhysicsFrame operator*(const PhysicsFrame& other) const; - - virtual ~PhysicsFrame() {} - - CoordinateFrame toCoordinateFrame() const; - - /** - Linear interpolation (spherical linear for the rotations). - */ - PhysicsFrame lerp( - const PhysicsFrame& other, - float alpha) const; - - void deserialize(class BinaryInput& b); - - void serialize(class BinaryOutput& b) const; - -}; - -} // namespace - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Plane.h b/externals/g3dlite/G3D.lib/include/G3D/Plane.h deleted file mode 100644 index 1f0b15e0fe4..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Plane.h +++ /dev/null @@ -1,161 +0,0 @@ -/** - @file Plane.h - - Plane class - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2001-06-02 - @edited 2004-07-18 -*/ - -#ifndef G3D_PLANE_H -#define G3D_PLANE_H - -#include "G3D/platform.h" -#include "G3D/Vector3.h" -#include "G3D/Vector4.h" -#include "G3D/debugAssert.h" - -namespace G3D { - -/** - An infinite 2D plane in 3D space. - */ -class Plane { -private: - - /** normal.Dot(x,y,z) = distance */ - Vector3 _normal; - float _distance; - - /** - Assumes the normal has unit length. - */ - Plane(const Vector3& n, float d) : _normal(n), _distance(d) { - } - -public: - - Plane() : _normal(Vector3::unitY()), _distance(0) { - } - - /** - Constructs a plane from three points. - */ - Plane( - const Vector3& point0, - const Vector3& point1, - const Vector3& point2); - - /** - Constructs a plane from three points, where at most two are - at infinity (w = 0, not xyz = inf). - */ - Plane( - Vector4 point0, - Vector4 point1, - Vector4 point2); - - /** - The normal will be unitized. - */ - Plane( - const Vector3& __normal, - const Vector3& point); - - static Plane fromEquation(float a, float b, float c, float d); - - Plane(class BinaryInput& b); - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); - - virtual ~Plane() {} - - /** - Returns true if point is on the side the normal points to or - is in the plane. - */ - inline bool halfSpaceContains(Vector3 point) const { - // Clamp to a finite range for testing - point = point.clamp(Vector3::minFinite(), Vector3::maxFinite()); - - // We can get away with putting values *at* the limits of the float32 range into - // a dot product, since the dot product is carried out on float64. - return _normal.dot(point) >= _distance; - } - - /** - Returns true if point is on the side the normal points to or - is in the plane. - */ - inline bool halfSpaceContains(const Vector4& point) const { - if (point.w == 0) { - return _normal.dot(point.xyz()) > 0; - } else { - return halfSpaceContains(point.xyz() / point.w); - } - } - - /** - Returns true if point is on the side the normal points to or - is in the plane. Only call on finite points. Faster than halfSpaceContains. - */ - inline bool halfSpaceContainsFinite(const Vector3& point) const { - debugAssert(point.isFinite()); - return _normal.dot(point) >= _distance; - } - - /** - Returns true if the point is nearly in the plane. - */ - inline bool fuzzyContains(const Vector3 &point) const { - return fuzzyEq(point.dot(_normal), _distance); - } - - inline const Vector3& normal() const { - return _normal; - } - - /** - Returns distance from point to plane. Distance is negative if point is behind (not in plane in direction opposite normal) the plane. - */ - inline float distance(const Vector3& x) const { - return (_normal.dot(x) - _distance); - } - - inline Vector3 closestPoint(const Vector3& x) const { - return x + (_normal * (-distance(x))); - } - - /** Returns normal * distance from origin */ - Vector3 center() const { - return _normal * _distance; - } - - /** - Inverts the facing direction of the plane so the new normal - is the inverse of the old normal. - */ - void flip(); - - /** - Returns the equation in the form: - - normal.Dot(Vector3(x, y, z)) + d = 0 - */ - void getEquation(Vector3 &normal, double& d) const; - void getEquation(Vector3 &normal, float& d) const; - - /** - ax + by + cz + d = 0 - */ - void getEquation(double& a, double& b, double& c, double& d) const; - void getEquation(float& a, float& b, float& c, float& d) const; - - std::string toString() const; -}; - -} // namespace - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/PointAABSPTree.h b/externals/g3dlite/G3D.lib/include/G3D/PointAABSPTree.h deleted file mode 100644 index c8d527a45c2..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/PointAABSPTree.h +++ /dev/null @@ -1,1207 +0,0 @@ -/** - @file PointAABSPTree.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2004-01-11 - @edited 2008-11-02 - - Copyright 2000-2008, Morgan McGuire. - All rights reserved. - - */ - -#ifndef X_PointKDTree_H -#define X_PointKDTree_H - -#include "G3D/platform.h" -#include "G3D/Array.h" -#include "G3D/Table.h" -#include "G3D/Vector2.h" -#include "G3D/Vector3.h" -#include "G3D/Vector4.h" -#include "G3D/AABox.h" -#include "G3D/Sphere.h" -#include "G3D/Box.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/CollisionDetection.h" -#include "G3D/GCamera.h" -#include "G3D/PositionTrait.h" -#include - - -/////////////////////////////////////////////////////// - -/** @deprecated */ -inline void getPosition(const G3D::Vector3& v, G3D::Vector3& p) { - p = v; -} - -/** @deprecated */ -inline void getPosition(const G3D::Vector4& v, G3D::Vector3& p) { - p = v.xyz(); -} - -/** @deprecated */ -inline void getPosition(const G3D::Vector2& v, G3D::Vector3& p) { - p.x = v.x; - p.y = v.y; - p.z = 0; -} - -namespace G3D { - -/** - A set data structure that supports spatial queries using an axis-aligned - BSP tree for speed. - - PointKDTree allows you to quickly find points in 3D that lie within - a box or sphere. For large sets of objects it is much faster - than testing each object for a collision. See also G3D::KDTree; this class - is optimized for point sets, e.g.,for use in photon mapping and mesh processing. - - Template Parameters - -
- -
The template parameter T must be one for which - the following functions are overloaded: - -
-      T::T(); (public constructor of no arguments)
-
-       template<> struct PositionTrait {
-         static void getPosition(const T& v, G3D::Vector3& p);};
-
-       template <> struct HashTrait {
-         static size_t hashCode(const T& key);};
-
-       template<> struct EqualsTrait {
-           static bool equals(const T& a, const T& b); };
-    
- -

- - G3D provides these for the Vector2, Vector3, and Vector4 classes. - If you use a custom class, or a pointer to a custom class, you will need - to define those functions. - - Moving %Set Members -

It is important that objects do not move without updating the - PointKDTree. If the position of an object is about - to change, PointKDTree::remove it before they change and - PointKDTree::insert it again afterward. For objects - where the hashCode and == operator are invariant with respect - to the 3D position, - you can use the PointKDTree::update method as a shortcut to - insert/remove an object in one step after it has moved. - - - Note: Do not mutate any value once it has been inserted into PointKDTree. Values - are copied interally. All PointKDTree iterators convert to pointers to constant - values to reinforce this. - - If you want to mutate the objects you intend to store in a PointKDTree - simply insert pointers to your objects instead of the objects - themselves, and ensure that the above operations are defined. (And - actually, because values are copied, if your values are large you may - want to insert pointers anyway, to save space and make the balance - operation faster.) - - Dimensions - Although designed as a 3D-data structure, you can use the PointKDTree - for data distributed along 2 or 1 axes by simply returning bounds - that are always zero along one or more dimensions. - -*/ -template, - class HashFunc = HashTrait, - class EqualsFunc = EqualsTrait > -class PointKDTree { -protected: -#define TreeType PointKDTree - - // Unlike the KDTree, the PointKDTree assumes that T elements are - // small and keeps the handle and cached position together instead of - // placing them in separate bounds arrays. Also note that a copy of T - // is kept in the member table and that there is no indirection. - class Handle { - private: - Vector3 m_position; - - public: - T value; - - inline Handle() {} - inline Handle(const T& v) : value(v) { - PositionFunc::getPosition(v, m_position); - } - - /** Used by makeNode to create fake handles for partitioning. */ - void setPosition(const Vector3& v) { - m_position = v; - } - - inline const Vector3& position() const { - return m_position; - } - }; - - /** Returns the bounds of the sub array. Used by makeNode. */ - static AABox computeBounds( - const Array& point) { - - if (point.size() == 0) { - return AABox(Vector3::inf(), Vector3::inf()); - } - - AABox bounds(point[0].position()); - - for (int p = 0; p < point.size(); ++p) { - bounds.merge(point[p].position()); - } - - return bounds; - } - - class Node { - public: - - /** Spatial bounds on all values at this node and its children, based purely on - the parent's splitting planes. May be infinite */ - AABox splitBounds; - - Vector3::Axis splitAxis; - - /** Location along the specified axis */ - float splitLocation; - - /** child[0] contains all values strictly - smaller than splitLocation along splitAxis. - - child[1] contains all values strictly - larger. - - Both may be NULL if there are not enough - values to bother recursing. - */ - Node* child[2]; - - /** Values if this is a leaf node). */ - Array valueArray; - - /** Creates node with NULL children */ - Node() { - splitAxis = Vector3::X_AXIS; - splitLocation = 0; - splitBounds = AABox(-Vector3::inf(), Vector3::inf()); - for (int i = 0; i < 2; ++i) { - child[i] = NULL; - } - } - - /** - Doesn't clone children. - */ - Node(const Node& other) : valueArray(other.valueArray) { - splitAxis = other.splitAxis; - splitLocation = other.splitLocation; - splitBounds = other.splitBounds; - for (int i = 0; i < 2; ++i) { - child[i] = NULL; - } - } - - /** Copies the specified subarray of pt into point, NULLs the children. - Assumes a second pass will set splitBounds. */ - Node(const Array& pt) { - splitAxis = Vector3::X_AXIS; - splitLocation = 0; - for (int i = 0; i < 2; ++i) { - child[i] = NULL; - } - valueArray = pt; - } - - - /** Deletes the children (but not the values) */ - ~Node() { - for (int i = 0; i < 2; ++i) { - delete child[i]; - } - } - - - /** Returns true if this node is a leaf (no children) */ - inline bool isLeaf() const { - return (child[0] == NULL) && (child[1] == NULL); - } - - - /** - Recursively appends all handles and children's handles - to the array. - */ - void getHandles(Array& handleArray) const { - handleArray.append(valueArray); - for (int i = 0; i < 2; ++i) { - if (child[i] != NULL) { - child[i]->getHandles(handleArray); - } - } - } - - - void verifyNode(const Vector3& lo, const Vector3& hi) { - // debugPrintf("Verifying: split %d @ %f [%f, %f, %f], [%f, %f, %f]\n", - // splitAxis, splitLocation, lo.x, lo.y, lo.z, hi.x, hi.y, hi.z); - - debugAssert(lo == splitBounds.low()); - debugAssert(hi == splitBounds.high()); - - for (int i = 0; i < valueArray.length(); ++i) { - const Vector3& b = valueArray[i].position(); - debugAssert(splitBounds.contains(b)); - } - - if (child[0] || child[1]) { - debugAssert(lo[splitAxis] < splitLocation); - debugAssert(hi[splitAxis] > splitLocation); - } - - Vector3 newLo = lo; - newLo[splitAxis] = splitLocation; - Vector3 newHi = hi; - newHi[splitAxis] = splitLocation; - - if (child[0] != NULL) { - child[0]->verifyNode(lo, newHi); - } - - if (child[1] != NULL) { - child[1]->verifyNode(newLo, hi); - } - } - - - /** - Stores the locations of the splitting planes (the structure but not the content) - so that the tree can be quickly rebuilt from a previous configuration without - calling balance. - */ - static void serializeStructure(const Node* n, BinaryOutput& bo) { - if (n == NULL) { - bo.writeUInt8(0); - } else { - bo.writeUInt8(1); - n->splitBounds.serialize(bo); - serialize(n->splitAxis, bo); - bo.writeFloat32(n->splitLocation); - for (int c = 0; c < 2; ++c) { - serializeStructure(n->child[c], bo); - } - } - } - - /** Clears the member table */ - static Node* deserializeStructure(BinaryInput& bi) { - if (bi.readUInt8() == 0) { - return NULL; - } else { - Node* n = new Node(); - n->splitBounds.deserialize(bi); - deserialize(n->splitAxis, bi); - n->splitLocation = bi.readFloat32(); - for (int c = 0; c < 2; ++c) { - n->child[c] = deserializeStructure(bi); - } - } - } - - /** Returns the deepest node that completely contains bounds. */ - Node* findDeepestContainingNode(const Vector3& point) { - - // See which side of the splitting plane the bounds are on - if (point[splitAxis] < splitLocation) { - // Point is on the low side. Recurse into the child - // if it exists. - if (child[0] != NULL) { - return child[0]->findDeepestContainingNode(point); - } - } else if (point[splitAxis] > splitLocation) { - // Point is on the high side, recurse into the child - // if it exists. - if (child[1] != NULL) { - return child[1]->findDeepestContainingNode(point); - } - } - - // There was no containing child, so this node is the - // deepest containing node. - return this; - } - - /** Appends all members that intersect the box. - If useSphere is true, members are tested against the sphere instead. */ - void getIntersectingMembers( - const AABox& sphereBounds, - const Sphere& sphere, - Array& members) const { - - // Test all values at this node. Extract the - // underlying C array for speed - const int N = valueArray.size(); - const Handle* handleArray = valueArray.getCArray(); - - const float r2 = square(sphere.radius); - - // Copy the sphere center so that it is on the stack near the radius - const Vector3 center = sphere.center; - for (int v = 0; v < N; ++v) { - if ((center - handleArray[v].position()).squaredLength() <= r2) { - members.append(handleArray[v].value); - } - } - - // If the left child overlaps the box, recurse into it - if (child[0] && (sphereBounds.low()[splitAxis] < splitLocation)) { - child[0]->getIntersectingMembers(sphereBounds, sphere, members); - } - - // If the right child overlaps the box, recurse into it - if (child[1] && (sphereBounds.high()[splitAxis] > splitLocation)) { - child[1]->getIntersectingMembers(sphereBounds, sphere, members); - } - } - - /** Appends all members that intersect the box. - If useSphere is true, members are tested against the sphere instead. - - Implemented using both box and sphere tests to simplify the implementation - of a future beginSphereInteresection iterator using the same underlying - BoxIterator class. - */ - void getIntersectingMembers( - const AABox& box, - const Sphere& sphere, - Array& members, - bool useSphere) const { - - // Test all values at this node - for (int v = 0; v < valueArray.size(); ++v) { - if ((useSphere && sphere.contains(valueArray[v].position())) || - (! useSphere && box.contains(valueArray[v].position()))) { - members.append(valueArray[v].value); - } - } - - // If the left child overlaps the box, recurse into it - if ((child[0] != NULL) && (box.low()[splitAxis] < splitLocation)) { - child[0]->getIntersectingMembers(box, sphere, members, useSphere); - } - - // If the right child overlaps the box, recurse into it - if ((child[1] != NULL) && (box.high()[splitAxis] > splitLocation)) { - child[1]->getIntersectingMembers(box, sphere, members, useSphere); - } - } - - /** - Recurse through the tree, assigning splitBounds fields. - */ - void assignSplitBounds(const AABox& myBounds) { - splitBounds = myBounds; - -# ifdef G3D_DEBUG - if (child[0] || child[1]) { - debugAssert(splitBounds.high()[splitAxis] > splitLocation); - debugAssert(splitBounds.low()[splitAxis] < splitLocation); - } -# endif - - AABox childBounds[2]; - myBounds.split(splitAxis, splitLocation, childBounds[0], childBounds[1]); - - for (int c = 0; c < 2; ++c) { - if (child[c]) { - child[c]->assignSplitBounds(childBounds[c]); - } - } - } - }; - - class AxisComparator { - private: - Vector3::Axis sortAxis; - - public: - - AxisComparator(Vector3::Axis s) : sortAxis(s) {} - - inline int operator()(const Handle& A, const Handle& B) const { - if (A.position()[sortAxis] > B.position()[sortAxis]) { - return -1; - } else if (A.position()[sortAxis] < B.position()[sortAxis]) { - return 1; - } else { - return 0; - } - } - }; - - /** - Recursively subdivides the subarray. - - The source array will be cleared after it is used - - Call assignSplitBounds() on the root node after making a tree. - */ - Node* makeNode( - Array& source, - Array& temp, - int valuesPerNode, - int numMeanSplits) { - - Node* node = NULL; - - if (source.size() <= valuesPerNode) { - // Make a new leaf node - node = new Node(source); - - // Set the pointers in the memberTable - for (int i = 0; i < source.size(); ++i) { - memberTable.set(source[i].value, node); - } - - } else { - // Make a new internal node - node = new Node(); - - const AABox bounds = computeBounds(source); - const Vector3 extent = bounds.high() - bounds.low(); - - Vector3::Axis splitAxis = extent.primaryAxis(); - - float splitLocation; - - Array lt, gt; - - if (numMeanSplits <= 0) { - source.medianPartition(lt, node->valueArray, gt, temp, AxisComparator(splitAxis)); - splitLocation = node->valueArray[0].position()[splitAxis]; - - if ((node->valueArray.size() > source.size() / 2) && - (source.size() > 10)) { - // Our median split put an awful lot of points on the splitting plane. Try a mean - // split instead - numMeanSplits = 1; - } - } - - if (numMeanSplits > 0) { - // Compute the mean along the axis - - splitLocation = (bounds.high()[splitAxis] + - bounds.low()[splitAxis]) / 2.0; - - Handle splitHandle; - Vector3 v; - v[splitAxis] = splitLocation; - splitHandle.setPosition(v); - - source.partition(splitHandle, lt, node->valueArray, gt, AxisComparator(splitAxis)); - } - -# if defined(G3D_DEBUG) && defined(VERIFY_TREE) - for (int i = 0; i < lt.size(); ++i) { - const Vector3& v = lt[i].position(); - debugAssert(v[splitAxis] < splitLocation); - } - for (int i = 0; i < gt.size(); ++i) { - debugAssert(gt[i].position()[splitAxis] > splitLocation); - } - for (int i = 0; i < node->valueArray.size(); ++i) { - debugAssert(node->valueArray[i].position()[splitAxis] == splitLocation); - } -# endif - - node->splitAxis = splitAxis; - node->splitLocation = splitLocation; - - // Throw away the source array to save memory - source.fastClear(); - - if (lt.size() > 0) { - node->child[0] = makeNode(lt, temp, valuesPerNode, numMeanSplits - 1); - } - - if (gt.size() > 0) { - node->child[1] = makeNode(gt, temp, valuesPerNode, numMeanSplits - 1); - } - - // Add the values stored at this interior node to the member table - for(int i = 0; i < node->valueArray.size(); ++i) { - memberTable.set(node->valueArray[i].value, node); - } - - } - - return node; - } - - /** - Recursively clone the passed in node tree, setting - pointers for members in the memberTable as appropriate. - called by the assignment operator. - */ - Node* cloneTree(Node* src) { - Node* dst = new Node(*src); - - // Make back pointers - for (int i = 0; i < dst->valueArray.size(); ++i) { - memberTable.set(dst->valueArray[i].value, dst); - } - - // Clone children - for (int i = 0; i < 2; ++i) { - if (src->child[i] != NULL) { - dst->child[i] = cloneTree(src->child[i]); - } - } - - return dst; - } - - /** Maps members to the node containing them */ - typedef Table MemberTable; - MemberTable memberTable; - - Node* root; - -public: - - /** To construct a balanced tree, insert the elements and then call - PointKDTree::balance(). */ - PointKDTree() : root(NULL) {} - - - PointKDTree(const PointKDTree& src) : root(NULL) { - *this = src; - } - - - PointKDTree& operator=(const PointKDTree& src) { - delete root; - // Clone tree takes care of filling out the memberTable. - root = cloneTree(src.root); - return *this; - } - - - ~PointKDTree() { - clear(); - } - - /** - Throws out all elements of the set and erases the structure of the tree. - */ - void clear() { - memberTable.clear(); - delete root; - root = NULL; - } - - /** Removes all elements of the set while maintaining the structure of the tree */ - void clearData() { - memberTable.clear(); - Array stack; - stack.push(root); - while (stack.size() > 0) { - Node* node = stack.pop(); - node->valueArray.fastClear(); - - for (int i = 0; i < 2; ++i) { - if (node->child[i] != NULL) { - stack.push(node->child[i]); - } - } - } - } - - - int size() const { - return memberTable.size(); - } - - /** - Inserts an object into the set if it is not - already present. O(log n) time. Does not - cause the tree to be balanced. - */ - void insert(const T& value) { - if (contains(value)) { - // Already in the set - return; - } - - Handle h(value); - - if (root == NULL) { - // This is the first node; create a root node - root = new Node(); - } - - Node* node = root->findDeepestContainingNode(h.position()); - - // Insert into the node - node->valueArray.append(h); - - // Insert into the node table - memberTable.set(value, node); - } - - /** Inserts each elements in the array in turn. If the tree - begins empty (no structure and no elements), this is faster - than inserting each element in turn. You still need to balance - the tree at the end.*/ - void insert(const Array& valueArray) { - // Pre-size the member table to avoid multiple allocations - memberTable.setSizeHint(valueArray.size() + size()); - - if (root == NULL) { - // Optimized case for an empty tree; don't bother - // searching or reallocating the root node's valueArray - // as we incrementally insert. - root = new Node(); - root->valueArray.resize(valueArray.size()); - for (int i = 0; i < valueArray.size(); ++i) { - // Insert in opposite order so that we have the exact same - // data structure as if we inserted each (i.e., order is reversed - // from array). - root->valueArray[valueArray.size() - i - 1] = Handle(valueArray[i]); - memberTable.set(valueArray[i], root); - } - } else { - // Insert at appropriate tree depth. - for (int i = 0; i < valueArray.size(); ++i) { - insert(valueArray[i]); - } - } - } - - - /** - Returns true if this object is in the set, otherwise - returns false. O(1) time. - */ - bool contains(const T& value) { - return memberTable.containsKey(value); - } - - - /** - Removes an object from the set in O(1) time. - It is an error to remove members that are not already - present. May unbalance the tree. - - Removing an element never causes a node (split plane) to be removed... - nodes are only changed when the tree is rebalanced. This behavior - is desirable because it allows the split planes to be serialized, - and then deserialized into an empty tree which can be repopulated. - */ - void remove(const T& value) { - debugAssertM(contains(value), - "Tried to remove an element from a " - "PointKDTree that was not present"); - - Array& list = memberTable[value]->valueArray; - - // Find the element and remove it - for (int i = list.length() - 1; i >= 0; --i) { - if (list[i].value == value) { - list.fastRemove(i); - break; - } - } - memberTable.remove(value); - } - - - /** - If the element is in the set, it is removed. - The element is then inserted. - - This is useful when the == and hashCode methods - on T are independent of the bounds. In - that case, you may call update(v) to insert an - element for the first time and call update(v) - again every time it moves to keep the tree - up to date. - */ - void update(const T& value) { - if (contains(value)) { - remove(value); - } - insert(value); - } - - - /** - Rebalances the tree (slow). Call when objects - have moved substantially from their original positions - (which unbalances the tree and causes the spatial - queries to be slow). - - @param valuesPerNode Maximum number of elements to put at - a node. - - @param numMeanSplits numMeanSplits = 0 gives a - fully axis aligned BSP-tree, where the balance operation attempts to balance - the tree so that every splitting plane has an equal number of left - and right children (i.e. it is a median split along that axis). - This tends to maximize average performance; all querries will return in the same amount of time. - - You can override this behavior by - setting a number of mean (average) splits. numMeanSplits = MAX_INT - creates a full oct-tree, which tends to optimize peak performance (some areas of the scene will terminate after few recursive splits) at the expense of - peak performance. - */ - void balance(int valuesPerNode = 40, int numMeanSplits = 3) { - if (root == NULL) { - // Tree is empty - return; - } - - Array handleArray; - root->getHandles(handleArray); - - // Delete the old tree - clear(); - - Array temp; - root = makeNode(handleArray, temp, valuesPerNode, numMeanSplits); - temp.fastClear(); - - // Walk the tree, assigning splitBounds. We start with unbounded - // space. - root->assignSplitBounds(AABox::maxFinite()); - -# ifdef _DEBUG - root->verifyNode(Vector3::minFinite(), Vector3::maxFinite()); -# endif - } - -private: - - /** - Returns the elements - - @param parentMask The mask that this node returned from culledBy. - */ - static void getIntersectingMembers( - const Array& plane, - Array& members, - Node* node, - uint32 parentMask) { - - int dummy; - - if (parentMask == 0) { - // None of these planes can cull anything - for (int v = node->valueArray.size() - 1; v >= 0; --v) { - members.append(node->valueArray[v].value); - } - - // Iterate through child nodes - for (int c = 0; c < 2; ++c) { - if (node->child[c]) { - getIntersectingMembers(plane, members, node->child[c], 0); - } - } - } else { - - if (node->valueArray.size() > 0) { - // This is a leaf; check the points - debugAssertM(node->child[0] == NULL, "Malformed Point tree"); - debugAssertM(node->child[1] == NULL, "Malformed Point tree"); - - // Test values at this node against remaining planes - for (int p = 0; p < plane.size(); ++p) { - if ((parentMask >> p) & 1 != 0) { - // Test against this plane - const Plane& curPlane = plane[p]; - for (int v = node->valueArray.size() - 1; v >= 0; --v) { - if (curPlane.halfSpaceContains(node->valueArray[v].position())) { - members.append(node->valueArray[v].value); - } - } - } - } - } else { - - uint32 childMask = 0xFFFFFF; - - // Iterate through child nodes - for (int c = 0; c < 2; ++c) { - if (node->child[c] && - ! node->child[c]->splitBounds.culledBy(plane, dummy, parentMask, childMask)) { - // This node was not culled - getIntersectingMembers(plane, members, node->child[c], childMask); - } - } - } - } - } - -public: - - /** - Returns all members inside the set of planes. - @param members The results are appended to this array. - */ - void getIntersectingMembers(const Array& plane, Array& members) const { - if (root == NULL) { - return; - } - - getIntersectingMembers(plane, members, root, 0xFFFFFF); - } - - /** - Typically used to find all visible - objects inside the view frustum (see also GCamera::getClipPlanes)... i.e. all objects - not culled by frustum. - - Example: -
-        Array  visible;
-        tree.getIntersectingMembers(camera.frustum(), visible);
-        // ... Draw all objects in the visible array.
-      
- @param members The results are appended to this array. - */ - void getIntersectingMembers(const GCamera::Frustum& frustum, Array& members) const { - Array plane; - - for (int i = 0; i < frustum.faceArray.size(); ++i) { - plane.append(frustum.faceArray[i].plane); - } - - getIntersectingMembers(plane, members); - } - - /** - C++ STL style iterator variable. See beginBoxIntersection(). - The iterator overloads the -> (dereference) operator, so this - acts like a pointer to the current member. - */ - // This iterator turns Node::getIntersectingMembers into a - // coroutine. It first translates that method from recursive to - // stack based, then captures the system state (analogous to a Scheme - // continuation) after each element is appended to the member array, - // and allowing the computation to be restarted. - class BoxIntersectionIterator { - private: - friend class TreeType; - - /** True if this is the "end" iterator instance */ - bool isEnd; - - /** The box that we're testing against. */ - AABox box; - - /** Node that we're currently looking at. Undefined if isEnd - is true. */ - Node* node; - - /** Nodes waiting to be processed */ - // We could use backpointers within the tree and careful - // state management to avoid ever storing the stack-- but - // it is much easier this way and only inefficient if the - // caller uses post increment (which they shouldn't!). - Array stack; - - /** The next index of current->valueArray to return. - Undefined when isEnd is true.*/ - int nextValueArrayIndex; - - BoxIntersectionIterator() : isEnd(true) {} - - BoxIntersectionIterator(const AABox& b, const Node* root) : - isEnd(root == NULL), box(b), - node(const_cast(root)), nextValueArrayIndex(-1) { - - // We intentionally start at the "-1" index of the current - // node so we can use the preincrement operator to move - // ourselves to element 0 instead of repeating all of the - // code from the preincrement method. Note that this might - // cause us to become the "end" instance. - ++(*this); - } - - public: - - inline bool operator!=(const BoxIntersectionIterator& other) const { - return ! (*this == other); - } - - bool operator==(const BoxIntersectionIterator& other) const { - if (isEnd) { - return other.isEnd; - } else if (other.isEnd) { - return false; - } else { - // Two non-end iterators; see if they match. This is kind of - // silly; users shouldn't call == on iterators in general unless - // one of them is the end iterator. - if ((box != other.box) || (node != other.node) || - (nextValueArrayIndex != other.nextValueArrayIndex) || - (stack.length() != other.stack.length())) { - return false; - } - - // See if the stacks are the same - for (int i = 0; i < stack.length(); ++i) { - if (stack[i] != other.stack[i]) { - return false; - } - } - - // We failed to find a difference; they must be the same - return true; - } - } - - /** - Pre increment. - */ - BoxIntersectionIterator& operator++() { - ++nextValueArrayIndex; - - bool foundIntersection = false; - while (! isEnd && ! foundIntersection) { - - // Search for the next node if we've exhausted this one - while ((! isEnd) && (nextValueArrayIndex >= node->valueArray.length())) { - // If we entered this loop, then the iterator has exhausted the elements at - // node (possibly because it just switched to a child node with no members). - // This loop continues until it finds a node with members or reaches - // the end of the whole intersection search. - - // If the right child overlaps the box, push it onto the stack for - // processing. - if ((node->child[1] != NULL) && - (box.high()[node->splitAxis] > node->splitLocation)) { - stack.push(node->child[1]); - } - - // If the left child overlaps the box, push it onto the stack for - // processing. - if ((node->child[0] != NULL) && - (box.low()[node->splitAxis] < node->splitLocation)) { - stack.push(node->child[0]); - } - - if (stack.length() > 0) { - // Go on to the next node (which may be either one of the ones we - // just pushed, or one from farther back the tree). - node = stack.pop(); - nextValueArrayIndex = 0; - } else { - // That was the last node; we're done iterating - isEnd = true; - } - } - - // Search for the next intersection at this node until we run out of children - while (! isEnd && ! foundIntersection && (nextValueArrayIndex < node->valueArray.length())) { - if (box.intersects(node->valueArray[nextValueArrayIndex].bounds)) { - foundIntersection = true; - } else { - ++nextValueArrayIndex; - // If we exhaust this node, we'll loop around the master loop - // to find a new node. - } - } - } - - return *this; - } - - /** - Post increment (much slower than preincrement!). - */ - BoxIntersectionIterator operator++(int) { - BoxIntersectionIterator old = *this; - ++this; - return old; - } - - /** Overloaded dereference operator so the iterator can masquerade as a pointer - to a member */ - const T& operator*() const { - alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); - return node->valueArray[nextValueArrayIndex].value; - } - - /** Overloaded dereference operator so the iterator can masquerade as a pointer - to a member */ - T const * operator->() const { - alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); - return &(stack.last()->valueArray[nextValueArrayIndex].value); - } - - /** Overloaded cast operator so the iterator can masquerade as a pointer - to a member */ - operator T*() const { - alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); - return &(stack.last()->valueArray[nextValueArrayIndex].value); - } - }; - - - /** - Iterates through the members that intersect the box - */ - BoxIntersectionIterator beginBoxIntersection(const AABox& box) const { - return BoxIntersectionIterator(box, root); - } - - BoxIntersectionIterator endBoxIntersection() const { - // The "end" iterator instance - return BoxIntersectionIterator(); - } - - /** - Appends all members whose bounds intersect the box. - See also PointKDTree::beginBoxIntersection. - */ - void getIntersectingMembers(const AABox& box, Array& members) const { - if (root == NULL) { - return; - } - root->getIntersectingMembers(box, Sphere(Vector3::zero(), 0), members, false); - } - - - /** - @param members The results are appended to this array. - */ - void getIntersectingMembers(const Sphere& sphere, Array& members) const { - if (root == NULL) { - return; - } - - AABox box; - sphere.getBounds(box); - root->getIntersectingMembers(box, sphere, members); - - } - - - /** - Stores the locations of the splitting planes (the structure but not the content) - so that the tree can be quickly rebuilt from a previous configuration without - calling balance. - */ - void serializeStructure(BinaryOutput& bo) const { - Node::serializeStructure(root, bo); - } - - /** Clears the member table */ - void deserializeStructure(BinaryInput& bi) { - clear(); - root = Node::deserializeStructure(bi); - } - - /** - Returns an array of all members of the set. See also PointKDTree::begin. - */ - void getMembers(Array& members) const { - memberTable.getKeys(members); - } - - - /** - C++ STL style iterator variable. See begin(). - Overloads the -> (dereference) operator, so this acts like a pointer - to the current member. - */ - class Iterator { - private: - friend class TreeType; - - // Note: this is a Table iterator, we are currently defining - // Set iterator - typename MemberTable::Iterator it; - - Iterator(const typename MemberTable::Iterator& it) : it(it) {} - - public: - inline bool operator!=(const Iterator& other) const { - return !(*this == other); - } - - bool operator==(const Iterator& other) const { - return it == other.it; - } - - /** - Pre increment. - */ - Iterator& operator++() { - ++it; - return *this; - } - - /** - Post increment (slower than preincrement). - */ - Iterator operator++(int) { - Iterator old = *this; - ++(*this); - return old; - } - - const T& operator*() const { - return it->key; - } - - T* operator->() const { - return &(it->key); - } - - operator T*() const { - return &(it->key); - } - }; - - - /** - C++ STL style iterator method. Returns the first member. - Use preincrement (++entry) to get to the next element (iteration - order is arbitrary). - Do not modify the set while iterating. - */ - Iterator begin() const { - return Iterator(memberTable.begin()); - } - - - /** - C++ STL style iterator method. Returns one after the last iterator - element. - */ - Iterator end() const { - return Iterator(memberTable.end()); - } -#undef TreeType -}; - -#define PointAABSPTree PointKDTree - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/PointHashGrid.h b/externals/g3dlite/G3D.lib/include/G3D/PointHashGrid.h deleted file mode 100644 index 8e9726e82da..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/PointHashGrid.h +++ /dev/null @@ -1,894 +0,0 @@ -/** - @file PointHashGrid.h - - @maintainer Morgan McGuire, morgan@cs.williams.edu - @created 2008-07-01 - @edited 2008-11-02 - - Copyright 2000-2008, Morgan McGuire. - All rights reserved. -*/ -#ifndef G3D_POINTHASHGRID_H -#define G3D_POINTHASHGRID_H - -#include "G3D/platform.h" -#include "G3D/EqualsTrait.h" -#include "G3D/HashTrait.h" -#include "G3D/Vector3.h" -#include "G3D/Vector3int32.h" -#include "G3D/Array.h" -#include "G3D/Table.h" -#include "G3D/AABox.h" -#include "G3D/Sphere.h" - -namespace G3D { - -/** - Storage of data in a sparse 3D grid of point-based data. The - space cost for n elements is O(n). For data with - approximately uniform density (with respect to the radius hint), - the time cost of searching for neighbors is O(1). - - Value must be supported by a G3D::PositionTrait, - G3D::EqualsTrait, and G3D::HashFunc. overrides are provided for - common G3D classes like G3D::Vector3. -*/ -template, - class EqualsFunc = EqualsTrait, - class HashFunc = HashTrait > -class PointHashGrid { -private: - -#define ThisType PointHashGrid - - /** A value annotated with precomputed position and hash code.*/ - class Entry { - public: - Vector3 position; - Value value; - }; - - /** One cell of the grid. */ - typedef Array Cell; - typedef Table CellTable; - - /** The cube of +/-1 along each dimension. Initialized by initOffsetArray.*/ - Vector3int32 m_offsetArray[3*3*3]; - - /** Incremented every time the data structure is mutated. - Used by the iterators to determine if the data structure - has changed since iteration began. */ - int m_epoch; - - /** Extent of a cell along one dimension. */ - float m_cellWidth; - - /** Conservative bounds; the actual data may be smaller. */ - AABox m_bounds; - - /** Number of elements. */ - int m_size; - - /** Non-empty cells indexed by grid position. Actual 3D position is - position * m_cellWidth*/ - CellTable m_data; - - - /** Intentionally unimplemented: prevent copy construction. */ - PointHashGrid(const ThisType&); - - - /** Intentionally unimplemented: prevent assignment. */ - PointHashGrid& operator=(const ThisType&); - - - /** Locate the cell and index within that cell containing v. Called by - remove() and contains(). */ - bool find( - const Value& v, - Vector3int32& foundCellCoord, - Cell*& foundCell, - int& index) { - - Vector3 pos; - PosFunc::getPosition(v, pos); - - Vector3int32 cellCoord; - getCellCoord(pos, cellCoord); - for (int i = 0; i < 27; ++i) { - Vector3int32 c = cellCoord + m_offsetArray[i]; - Cell* cell = m_data.getPointer(c); - if (cell != NULL) { - // The cell exists - for (int j = 0; j < cell->size(); ++j) { - if (EqualsFunc::equals((*cell)[j].value, v)) { - foundCell = cell; - index = j; - foundCellCoord = c; - return true; - } - } - } - } - - // Not found - return false; - } - - /** Given a real-space position, returns the cell coord - containing it.*/ - void getCellCoord(const Vector3& pos, Vector3int32& cellCoord) const { - for (int a = 0; a < 3; ++a) { - cellCoord[a] = iFloor(pos[a] / m_cellWidth); - } - } - - /** Initializes m_offsetArray. */ - void initOffsetArray() { - int i = 0; - Vector3int32 d; - for (d.x = -1; d.x <= +1; ++d.x) { - for (d.y = -1; d.y <= +1; ++d.y) { - for (d.z = -1; d.z <= +1; ++d.z) { - m_offsetArray[i] = d; - ++i; - } - } - } - - // Put (0, 0, 0) first, so that contains() is most likely to find - // the value quickly. - i = (1 * 3 + 1) * 3 + 1; - debugAssert(m_offsetArray[i] == Vector3int32(0,0,0)); - Vector3int32 temp = m_offsetArray[0]; - m_offsetArray[0] = m_offsetArray[i]; - m_offsetArray[i] = temp; - } - -public: - - /** - @param radiusHint the radius that will typically be used with - beginSphereIntersection and beginBoxIntersection. If two Values are equal, - their positions must be within this radius as well. - */ - PointHashGrid(float radiusHint) : m_size(0) { - initOffsetArray(); - - debugAssertM(radiusHint > 0, "Cell radius must be positive"); - m_cellWidth = radiusHint; - } - - /** - If radiusHint is negative, it is automatically chosen to put - about 5 values in each grid cell (which means about 27 * 5 - values for each beginIntersection call). - */ - PointHashGrid(const Array& init, float radiusHint = -1.0f) : m_size(0) { - initOffsetArray(); - - Vector3 lo(Vector3::inf()); - Vector3 hi(-lo); - - // Compute bounds - Array entry(init.size()); - for (int i = 0; i < entry.size(); ++i) { - const Value& value = init[i]; - Vector3 pos = m_posFunc(value); - - entry[i].value = value; - entry[i].hashCode = m_hashFunc(value); - entry[i].position = pos; - - lo = lo.min(pos); - hi = hi.max(pos); - } - - m_bounds = AABox(lo, hi); - - if (radiusHint <= 0) { - // Compute a good cell width based on the bounds. - // - // N numPerCell - // ----- = --------- - // volume r^3 - - float numPerCell = 5; - radiusHint = - (float)pow(numPerCell * m_bounds.volume() / init.size(), 1.0 / 3.0); - - if (radiusHint == 0) { - // Volume must have been zero because all points were colocated. - radiusHint = 0.1f; - } - } - - insert(init); - } - - /** Returns the number of elements. */ - inline int size() const { - return m_size; - } - - /** Returns a conservative bounding box around the contents. This is - conservative because it is not updated when elements are removed. */ - const AABox& conservativeBoxBounds() const { - return m_bounds; - } - - /** Insert @a v at position @a p given by getPosition(v, p). - Multiple elements that are equal may be inserted; all copies will be - in the data structure. */ - void insert(const Value& v) { - Vector3 pos; - PosFunc::getPosition(v, pos); - Vector3int32 cellCoord; - getCellCoord(pos, cellCoord); - - // See if the cell already exists - Cell* cell = m_data.getPointer(cellCoord); - - if (cell == NULL) { - // The cell did not exist; create it - m_data.set(cellCoord, Cell()); - cell = m_data.getPointer(cellCoord); - } - debugAssert(cell != NULL); - - Entry& entry = cell->next(); - entry.value = v; - entry.position = pos; - - // Update the bounds - if (size() == 0) { - m_bounds = AABox(pos); - } else { - m_bounds.merge(pos); - } - - ++m_size; - ++m_epoch; - } - - - /** Inserts all elements of the array. */ - void insert(const Array& v) { - for (int i = 0; i < v.size(); ++i) { - insert(v[i]); - } - } - - - /** If there are multiple copies of an element, you must - delete them multiple times. - - @param shrinkAsNeeded If true, deallocate underlying data - structures as they are emptied. False increases performace at - the cost of memory overhead for dynamic structures. - - @return true if the element was found. - */ - bool remove(const Value& v, bool shrinkIfNecessary = true) { - Cell* cell = NULL; - int index = 0; - Vector3int32 cellCoord; - - if (find(v, cellCoord, cell, index)) { - cell->fastRemove(index, shrinkIfNecessary); - --m_size; - ++m_epoch; - - if ((cell->size() == 0) && shrinkIfNecessary) { - // Remove the cell itself - - // Drop our pointer, which is about to dangle - cell = NULL; - bool success = m_data.remove(cellCoord); - debugAssertM(success, "Data structure corrupt: " - "tried to remove a cell that doesn't exist."); - } - - return true; - - } else { - return false; - } - } - - /** Removes all elements of @v. */ - void remove(const Array& v, bool shrink = true) { - for (int i = 0; i < v.size(); ++i) { - remove(v[i], shrink); - } - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - class Iterator { - private: - friend class ThisType; - - bool m_isEnd; - - const ThisType* m_grid; - - typename CellTable::Iterator m_tableIterator; - - /** Index within m_tableIterator->value of the current value. */ - int m_arrayIndex; - - const int m_epoch; - - /** End iterator. Note that the m_tableIterator is initialized to the end iterator - of a temporary value! This is ok because we'll never look at the value of the - m_tableIterator, since we're initializing the "end" Iterator.*/ - Iterator() : m_isEnd(true), m_grid(NULL), m_tableIterator(CellTable().end()), - m_arrayIndex(0), m_epoch(0) {} - - Iterator(const ThisType* grid) : - m_isEnd(false), - m_grid(grid), - m_tableIterator( grid->m_data.begin() ), - m_arrayIndex(0), - m_epoch(grid->m_epoch) { } - - private: - - const Value& value() const { - debugAssert(! m_isEnd); - debugAssertM(m_tableIterator->value.size() > m_arrayIndex, - "No more elements"); - return m_tableIterator->value[m_arrayIndex].value; - } - - public: - - inline bool operator!=(const Iterator& other) const { - if (other.m_isEnd && m_isEnd) { - return false; - } else { - return (m_isEnd != other.m_isEnd) || - (m_tableIterator != other.m_tableIterator) || - (m_arrayIndex != other.m_arrayIndex); - } - } - - bool operator==(const Iterator& other) const { - return !(*this != other); - } - - /** Preincrement */ - Iterator& operator++() { - debugAssert(! m_isEnd); - debugAssertM(m_epoch == m_grid->m_epoch, - "It is illegal to mutate the HashGrid " - "while iterating through it."); - - ++m_arrayIndex; - - if (m_arrayIndex >= m_tableIterator->value.size()) { - // Move on to the next cell - ++m_tableIterator; - m_arrayIndex = 0; - - // Check to see if we're at the end - m_isEnd = (m_tableIterator == m_grid->m_data.end()); - } - - return *this; - } - - /** Post increment (slower) */ - Iterator operator++(int) { - debugAssert(! m_isEnd); - Iterator old = *this; - ++(*this); - return old; - } - - const Value& operator*() const { return value(); } - const Value* operator->() const { return &value(); } - operator Value*() const { return &value(); } - }; // Iterator - - - /** Iterate through all members. It is an error to mutate the HashGrid - while iterating through it. Each member can be accessed by "dereferencing" - the iterator: - -
-        for (Grid::Iterator i = grid.begin(); i != grid.end(), ++i) {
-        const Value& = *i;
-        ...
-        }
-        
- */ - Iterator begin() const { - return Iterator(this); - } - - const Iterator& end() const { - static const Iterator it; - return it; - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - // Forward declaration required by older gcc versions for friend declaration in BoxIterator - class SphereIterator; - class BoxIterator { - private: - friend class ThisType; - friend class SphereIterator; - - bool m_isEnd; - - const ThisType* m_grid; - - /** Lower bound on the boxes covered, inclusive. */ - Vector3int32 m_lo; - - /** Upper bound on the boxes covered, inclusive.*/ - Vector3int32 m_hi; - - /** If true, test values against m_box before returning them.*/ - bool m_exact; - - /** The underlying box in 3D space */ - AABox m_box; - - /** The iterator winds through the 3D grid between m_lo and (m_lo + m_extent) in - Z,Y,X-major order. This is the index keeping track of how - far it has come */ - Vector3int32 m_current; - - /** The current cell. */ - Cell* m_cell; - - /** Index within m_cell of the current value */ - int m_arrayIndex; - - const int m_epoch; - - - /** Called from advance() */ - void advanceCell() { - do { - ++m_current.x; - if (m_current.x > m_hi.x) { - m_current.x = m_lo.x; - ++m_current.y; - if (m_current.y > m_hi.y) { - m_current.y = m_lo.y; - ++m_current.z; - if (m_current.z > m_hi.z) { - m_isEnd = true; - return; - } - } - } - - // Pick up the new cell - m_cell = m_grid->m_data.getPointer(m_current); - // Keep advancing if the cell does not exist - } while ((m_cell == NULL) || (m_cell->size() == 0)); - } - - /** Advance to the next value */ - void advance() { - debugAssert(! m_isEnd); - - do { - ++m_arrayIndex; - bool inConstructor = (m_cell == NULL); - if (inConstructor || m_arrayIndex >= m_cell->size()) { - advanceCell(); - m_arrayIndex = 0; - - if (m_isEnd) { - // Ran out of values - return; - } - debugAssert(m_cell != NULL); - } - - // Advance until we have a value that can be returned, either - // because we don't care about exactness or because it is - // guaranteed to be within the box. - } while (m_exact && ! m_box.contains(position())); - } - - - /** End iterator */ - BoxIterator() : m_isEnd(true), m_grid(NULL), m_exact(true), m_current(0,0,0), m_cell(NULL), m_arrayIndex(0), m_epoch(0) {} - - /** Begin iterator */ - BoxIterator(const ThisType* grid, bool exact, const AABox& box) : - m_isEnd(false), - m_grid(grid), - m_exact(exact), - m_box(box), - m_current(-1, 0 ,0), - m_cell(NULL), - m_arrayIndex(0), - m_epoch(grid->m_epoch) { - - m_grid->getCellCoord(box.low(), m_lo); - m_grid->getCellCoord(box.high(), m_hi); - - // Get to the first value - m_current = m_lo; - // Back up one so that advancing takes us to the first - --m_current.x; - advance(); - } - - const Value& value() const { - debugAssert(! m_isEnd); - return (*m_cell)[m_arrayIndex].value; - } - - /** Used by SphereIterator::advance() */ - const Vector3& position() const { - debugAssert(! m_isEnd); - return (*m_cell)[m_arrayIndex].position; - } - - public: - - inline bool operator!=(const BoxIterator& other) const { - if (other.m_isEnd && m_isEnd) { - return false; - } else { - return (m_isEnd != other.m_isEnd) || - (m_cell != other.m_cell) || - (m_arrayIndex != other.m_arrayIndex); - } - } - - bool operator==(const BoxIterator& other) const { - return !(*this != other); - } - - /** Preincrement */ - BoxIterator& operator++() { - debugAssert(! m_isEnd); - debugAssertM(m_epoch == m_grid->m_epoch, - "It is illegal to mutate the HashGrid " - "while iterating through it."); - - advance(); - - return *this; - } - - /** Post increment (slower) */ - BoxIterator operator++(int) { - Iterator old = *this; - ++(*this); - return old; - } - - const Value& operator*() const { return value(); } - const Value* operator->() const { return &value(); } - operator Value*() const { return &value(); } - - bool hasMore() const { - return ! m_isEnd; - } - }; // BoxIterator - - /** - Finds all values whose positions are within @a box. It is an error to - mutate the PointHashGrid while iterating through it. - - @param exact If false, the iterator will execute more quickly but will likely return some - values that lie outside the box. Set exact = false if you are going to test the - results against the yourself box anyway. - */ - BoxIterator beginBoxIntersection(const AABox& box, bool exact = true) const { - return BoxIterator(this, exact, box); - } - - const BoxIterator& endBoxIntersection() const { - static const BoxIterator it; - return it; - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - class SphereIterator { - private: - - friend class ThisType; - - bool m_isEnd; - Sphere m_sphere; - BoxIterator m_boxIterator; - - SphereIterator() : m_isEnd(true) {} - - void advance() { - if (! m_boxIterator.hasMore()) { - m_isEnd = true; - return; - } - - while (! m_sphere.contains(m_boxIterator.position())) { - ++m_boxIterator; - - if (! m_boxIterator.hasMore()) { - m_isEnd = true; - return; - } - } - } - - static AABox getBoundingBox(const Sphere& s) { - AABox box; - s.getBounds(box); - return box; - } - - SphereIterator(const ThisType* grid, const Sphere& sphere) : - m_isEnd(false), - m_sphere(sphere), - m_boxIterator(grid, false, getBoundingBox(sphere)) { - - // Find the first element that is actually in the sphere, - // not just the box. - advance(); - } - - const Value& value() const { - return *m_boxIterator; - } - - // TODO: if the sphere is very big compared to radius, check each - // cell's box to see if the cell itself is actually inside the sphere - // before iterating through it, since there may be many boxes outside the sphere. - - public: - - inline bool operator!=(const SphereIterator& other) const { - if (other.m_isEnd && m_isEnd) { - return false; - } else { - return - (m_isEnd != other.m_isEnd) || - (m_sphere != other.m_sphere) || - (m_boxIterator != other.m_boxIterator); - } - } - - bool operator==(const SphereIterator& other) const { - return !(*this != other); - } - - - - /** Preincrement */ - SphereIterator& operator++() { - debugAssert(! m_isEnd); - - ++m_boxIterator; - advance(); - - return *this; - } - - /** Post increment (slower) */ - SphereIterator operator++(int) { - Iterator old = *this; - ++(*this); - return old; - } - - const Value& operator*() const { return value(); } - const Value* operator->() const { return &value(); } - operator Value*() const { return &value(); } - - bool hasMore() const { - return ! m_isEnd; - } - }; // SphereIterator - - /** - Finds all values whose positions are within @a sphere. It is an error - to mutate the HashGrid while iterating through it. - */ - SphereIterator beginSphereIntersection(const Sphere& sphere) const { - return SphereIterator(this, sphere); - } - - const SphereIterator& endSphereIntersection() const { - static const SphereIterator it; - return it; - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - /** - Dereference to access the bounds() and size() [element count] of the underlying - cell objet. - - Example: -
-       for(PointHashGrid::CellIterator iter = grid.beginCells(); iter != grid.endCells(); ++iter) {	
-       entriesFound += iter->size();
-       }
-    */
-    class CellIterator {
-    private:
-        friend class ThisType;
-
-        bool                                    m_isEnd;
-        const ThisType*                         m_grid;
-        typename CellTable::Iterator            m_tableIterator;
-        const int                               m_epoch;
-
-
-        Cell& cell() {
-            return m_tableIterator->value;
-        }
-
-    public:
-        
-        class CellObject {
-            friend class CellIterator;
-        private:
-            const CellIterator* m_parent;
-
-            CellObject() : m_parent(NULL) {}
-
-        public:
-
-            /** Returns the bounds on this cell */
-            AABox bounds() const {
-                const Vector3int32& k = m_parent->m_tableIterator->key;
-                return AABox(Vector3(k) * m_parent->m_cellWidth, 
-                             Vector3(k + Vector3int32(1, 1, 1)) * m_parent->m_cellWidth);
-            }
-
-            /** Number of elements inside this cell */
-            int size() const {
-                debugAssert(! m_parent->m_isEnd);
-                return m_parent->m_tableIterator->value.size();
-            }
-        };
-
-    private:
-        /** Used to make the indirection work.*/
-        CellObject m_indirection;
-
-        /** End iterator. Note that the m_tableIterator is initialized to the end iterator
-            of a temporary value!  This is ok because we'll never look at the value of the 
-            m_tableIterator, since we're initializing the "end" Iterator.*/
-        CellIterator() : 
-            m_isEnd(true),
-            m_grid(NULL),
-            m_tableIterator( CellTable().end() ),
-            m_epoch(0) {}
-        
-        CellIterator(const ThisType* grid) : 
-            m_isEnd(false),
-            m_grid(grid),
-            m_tableIterator( grid->m_data.begin()),
-            m_epoch(grid->m_epoch) {
-            m_indirection.m_parent = this;
-            m_isEnd = ! m_tableIterator.hasMore();
-        }
-        
-    public:
-
-        const CellObject& operator*()  const { return  m_indirection; }
-        const CellObject* operator->() const { return &m_indirection; }
-        operator CellObject*()         const { return &m_indirection; }
-
-        inline bool operator!=(const CellIterator& other) const {
-            // != is called more often than == during iteration
-            return !(
-                     (m_isEnd && other.m_isEnd) ||
-                     ((m_isEnd == other.m_isEnd) && 
-                      (m_tableIterator != other.m_tableIterator)));
-        }
-
-        bool operator==(const CellIterator& other) const {
-            return !(*this != other);
-        }
-
-        /** Preincrement */
-        CellIterator& operator++() {
-            debugAssertM(m_epoch == m_grid->m_epoch, 
-                         "It is illegal to mutate the HashGrid while "
-                         "iterating through it.");
-            ++m_tableIterator;
-            m_isEnd = ! m_tableIterator.hasMore();
-            return *this;
-        }
-
-        /** Post increment (slower) */
-        CellIterator operator++(int) {
-            Iterator old = *this;
-            ++(*this);
-            return old;
-        }
-
-        bool hasMore() const {
-            return ! m_isEnd;
-        }
-    }; // CellIterator
-
-    /** Iterates through the non-empty cells.  This is intended primarily for
-        debugging and visualizing the data structure.*/
-    CellIterator beginCells() const {
-        return CellIterator(this);
-    }
-
-    const CellIterator& endCells() const {
-        static const CellIterator it;
-        return it;
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    ///////////////////////////////////////////////////////////////////////////
-
-    /** Returns true if there is a value that is exactly equal to @a. This will 
-        check all neighboring cells to avoid roundoff error at cell boundaries. 
-    */
-    bool contains(const Value& v) const {
-        Cell* cell = NULL;
-        int   index = 0;
-        Vector3int32 cellCoord;
-        return const_cast(this)->find(v, cellCoord, cell, index);
-    }
-
-    /** Calls delete on all of the values, which are assumed to be pointers. 
-        This is a helper to avoid requiring you to iterate through the data 
-        structure, removing and deleting each one. Clears the PointHashGrid at the
-        end.
-		
-        Using objects (instead of pointers) or reference counted pointers is 
-        recommended over using pointers and this deleteAll method.*/
-    void deleteAll() {
-        for (Iterator it = begin(); it.hasMore(); ++it) {
-            delete *it;
-        }
-        clear();
-    }
-
-    /** Removes all data. 
-        @param shrink If true, underlying structures are deallocated as
-        they are freed.*/
-    void clear(bool shrink = true) {
-        m_size = 0;
-        m_bounds = AABox();
-        if (! shrink) {
-            // Remove all data
-            for (CellIterator it = beginCells(); it.hasMore(); ++it) {
-                it.cell().clear(true);
-            }
-        } else {
-            m_data.clear();
-        }
-        ++m_epoch;
-    }
-
-    int debugGetDeepestBucketSize() const {
-        return m_data.debugGetDeepestBucketSize();
-    }
-
-    float debugGetAverageBucketSize() const {
-        return m_data.debugGetAverageBucketSize();
-    }
-#undef ThisType 
-};
-
-} // G3D
-#endif
diff --git a/externals/g3dlite/G3D.lib/include/G3D/Pointer.h b/externals/g3dlite/G3D.lib/include/G3D/Pointer.h
deleted file mode 100644
index 2b80187bae5..00000000000
--- a/externals/g3dlite/G3D.lib/include/G3D/Pointer.h
+++ /dev/null
@@ -1,275 +0,0 @@
-/** 
-  @file Pointer.h
- 
-  @maintainer Morgan McGuire, graphics3d.com
- 
-  @created 2007-05-16
-  @edited  2007-06-22
-
-  Copyright 2000-2007, Morgan McGuire.
-  All rights reserved.
- */
-#ifndef G3D_POINTER_H
-#define G3D_POINTER_H
-
-#include "G3D/debugAssert.h"
-#include "G3D/ReferenceCount.h"
-
-namespace G3D {
-
-/**
-   Acts like a pointer to a value of type ValueType (i.e.,
-   ValueType*), but can operate through accessor methods as well as on
-   a value in memory.  This is useful for implementing scripting
-   languages and other applications that need to connect existing APIs
-   by reference.
-
-   Because the accessors require values to be passed by value (instead of by reference)
-   this is primarily useful for objects whose memory size is small.
-
-   
-   class Foo {
-   public:
-      void setEnabled(bool b);
-      bool getEnabled() const;
-   };
-
-   Foo  f;
-   bool b;
-   
-   Pointer p1(&b);
-   Pointer p2(&f, &Foo::getEnabled, &Foo::setEnabled);
-
-   *p1 = true;
-   *p2 = false;
-   *p2 = *p1; \/\/ Value assignment
-   p2 = p1; \/\/ Pointer aliasing
-
-   \/\/ Or, equivalently:
-   p1.setValue(true);
-   p2.setValue(false);
-
-   p2.setValue(p1.getValue());
-   p2 = p1;
-   
- - Note: Because of the way that dereference is implemented, you cannot pass *p through a function - that takes varargs (...), e.g., printf("%d", *p) will produce a compile-time error. Instead use - printf("%d",(bool)*p) or printf("%d", p.getValue()). - - */ -template -class Pointer { -private: - - class Interface { - public: - virtual ~Interface() {}; - virtual void set(ValueType b) = 0; - virtual ValueType get() const = 0; - virtual Interface* clone() const = 0; - }; - - class Memory : public Interface { - private: - - ValueType* value; - - public: - - Memory(ValueType* value) : value(value) { - debugAssert(value != NULL); - } - - virtual void set(ValueType v) { - *value = v; - } - - virtual ValueType get() const { - return *value; - } - - virtual Interface* clone() const { - return new Memory(value); - } - }; - - template - class Accessor : public Interface { - private: - - T* object; - GetMethod getMethod; - SetMethod setMethod; - - public: - - Accessor(T* object, - GetMethod getMethod, - SetMethod setMethod) : object(object), getMethod(getMethod), setMethod(setMethod) { - debugAssert(object != NULL); - } - - virtual void set(ValueType v) { - (object->*setMethod)(v); - } - - virtual ValueType get() const { - return (object->*getMethod)(); - } - - virtual Interface* clone() const { - return new Accessor(object, getMethod, setMethod); - } - }; - - - template - class RefAccessor : public Interface { - private: - - ReferenceCountedPointer object; - GetMethod getMethod; - SetMethod setMethod; - - public: - - RefAccessor( - const ReferenceCountedPointer& object, - GetMethod getMethod, - SetMethod setMethod) : object(object), getMethod(getMethod), setMethod(setMethod) { - - debugAssert(object != NULL); - } - - virtual void set(ValueType v) { - (object.pointer()->*setMethod)(v); - } - - virtual ValueType get() const { - return (object.pointer()->*getMethod)(); - } - - virtual Interface* clone() const { - return new RefAccessor(object, getMethod, setMethod); - } - }; - - - Interface* interface; - -public: - - Pointer() : interface(NULL) {}; - - /** Allows implicit cast from real pointer */ - Pointer(ValueType* v) : interface(new Memory(v)) {} - - // Assignment - inline Pointer& operator=(const Pointer& r) { - delete interface; - if (r.interface != NULL) { - interface = r.interface->clone(); - } else { - interface = NULL; - } - return this[0]; - } - - Pointer(const Pointer& p) : interface(NULL) { - this[0] = p; - } - - template - Pointer(const ReferenceCountedPointer& object, - ValueType (Class::*getMethod)() const, - void (Class::*setMethod)(ValueType)) : - interface(new RefAccessor(object, getMethod, setMethod)) {} - - template - Pointer(const ReferenceCountedPointer& object, - const ValueType& (Class::*getMethod)() const, - void (Class::*setMethod)(ValueType)) : - interface(new RefAccessor(object, getMethod, setMethod)) {} - - template - Pointer(const ReferenceCountedPointer& object, - ValueType (Class::*getMethod)() const, - void (Class::*setMethod)(const ValueType&)) : - interface(new RefAccessor(object, getMethod, setMethod)) {} - - template - Pointer(const ReferenceCountedPointer& object, - const ValueType& (Class::*getMethod)() const, - void (Class::*setMethod)(const ValueType&)) : - interface(new RefAccessor(object, getMethod, setMethod)) {} - - template - Pointer(Class* object, - const ValueType& (Class::*getMethod)() const, - void (Class::*setMethod)(const ValueType&)) : - interface(new Accessor(object, getMethod, setMethod)) {} - - template - Pointer(Class* object, - ValueType (Class::*getMethod)() const, - void (Class::*setMethod)(const ValueType&)) : - interface(new Accessor(object, getMethod, setMethod)) {} - - template - Pointer(Class* object, - const ValueType& (Class::*getMethod)() const, - void (Class::*setMethod)(ValueType)) : - interface(new Accessor(object, getMethod, setMethod)) {} - - template - Pointer(Class* object, - ValueType (Class::*getMethod)() const, - void (Class::*setMethod)(ValueType)) : - interface(new Accessor(object, getMethod, setMethod)) {} - - ~Pointer() { - delete interface; - } - - inline const ValueType getValue() const { - debugAssert(interface != NULL); - return interface->get(); - } - - inline void setValue(const ValueType& v) { - debugAssert(interface != NULL); - interface->set(v); - } - - class IndirectValue { - private: - - friend class Pointer; - Pointer* pointer; - IndirectValue(Pointer* p) : pointer(p) {} - - public: - - void operator=(const ValueType& v) { - pointer->setValue(v); - } - - operator ValueType() const { - return pointer->getValue(); - } - - }; - - inline IndirectValue operator*() { - return IndirectValue(this); - } - - inline const ValueType operator*() const { - return getValue(); - } -}; - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/PositionTrait.h b/externals/g3dlite/G3D.lib/include/G3D/PositionTrait.h deleted file mode 100644 index 67a4f64138a..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/PositionTrait.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef G3D_POSITIONTRAIT_H -#define G3D_POSITIONTRAIT_H - -template -struct PositionTrait{}; - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Quat.h b/externals/g3dlite/G3D.lib/include/G3D/Quat.h deleted file mode 100644 index d4b892623d8..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Quat.h +++ /dev/null @@ -1,725 +0,0 @@ -/** - @file Quat.h - - Quaternion - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2002-01-23 - @edited 2006-05-10 - */ - -#ifndef G3D_QUAT_H -#define G3D_QUAT_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Vector3.h" -#include "G3D/Matrix3.h" -#include - -namespace G3D { - -/** - Unit quaternions are used in computer graphics to represent - rotation about an axis. Any 3x3 rotation matrix can - be stored as a quaternion. - - A quaternion represents the sum of a real scalar and - an imaginary vector: ix + jy + kz + w. A unit quaternion - representing a rotation by A about axis v has the form - [sin(A/2)*v, cos(A/2)]. For a unit quaternion, q.conj() == q.inverse() - is a rotation by -A about v. -q is the same rotation as q - (negate both the axis and angle). - - A non-unit quaterion q represents the same rotation as - q.unitize() (Dam98 pg 28). - - Although quaternion-vector operations (eg. Quat + Vector3) are - well defined, they are not supported by this class because - they typically are bugs when they appear in code. - - Do not subclass. - - BETA API -- subject to change - @cite Erik B. Dam, Martin Koch, Martin Lillholm, Quaternions, Interpolation and Animation. Technical Report DIKU-TR-98/5, Department of Computer Science, University of Copenhagen, Denmark. 1998. - */ -class Quat { -private: - // Hidden operators - bool operator<(const Quat&) const; - bool operator>(const Quat&) const; - bool operator<=(const Quat&) const; - bool operator>=(const Quat&) const; - -public: - - /** - q = [sin(angle / 2) * axis, cos(angle / 2)] - - In Watt & Watt's notation, s = w, v = (x, y, z) - In the Real-Time Rendering notation, u = (x, y, z), w = w - */ - float x, y, z, w; - - /** - Initializes to a zero degree rotation. - */ - inline Quat() : x(0), y(0), z(0), w(1) {} - - Quat( - const Matrix3& rot); - - inline Quat(float _x, float _y, float _z, float _w) : - x(_x), y(_y), z(_z), w(_w) {} - - /** Defaults to a pure vector quaternion */ - inline Quat(const Vector3& v, float _w = 0) : x(v.x), y(v.y), z(v.z), w(_w) { - } - - /** - The real part of the quaternion. - */ - inline const float& real() const { - return w; - } - - inline float& real() { - return w; - } - - /** Note: two quats can represent the Quat::sameRotation and not be equal. */ - bool fuzzyEq(const Quat& q) { - return G3D::fuzzyEq(x, q.x) && G3D::fuzzyEq(y, q.y) && G3D::fuzzyEq(z, q.z) && G3D::fuzzyEq(w, q.w); - } - - /** True if these quaternions represent the same rotation (note that every rotation is - represented by two values; q and -q). - */ - bool sameRotation(const Quat& q) { - return fuzzyEq(q) || fuzzyEq(-q); - } - - inline Quat operator-() const { - return Quat(-x, -y, -z, -w); - } - - /** - Returns the imaginary part (x, y, z) - */ - inline const Vector3& imag() const { - return *(reinterpret_cast(this)); - } - - inline Vector3& imag() { - return *(reinterpret_cast(this)); - } - - /** q = [sin(angle/2)*axis, cos(angle/2)] */ - static Quat fromAxisAngleRotation( - const Vector3& axis, - float angle); - - /** Returns the axis and angle of rotation represented - by this quaternion (i.e. q = [sin(angle/2)*axis, cos(angle/2)]) */ - void toAxisAngleRotation( - Vector3& axis, - double& angle) const; - - void toAxisAngleRotation( - Vector3& axis, - float& angle) const { - double d; - toAxisAngleRotation(axis, d); - angle = (float)d; - } - - Matrix3 toRotationMatrix() const; - - void toRotationMatrix( - Matrix3& rot) const; - - /** - Spherical linear interpolation: linear interpolation along the - shortest (3D) great-circle route between two quaternions. - - Note: Correct rotations are expected between 0 and PI in the right order. - - @cite Based on Game Physics -- David Eberly pg 538-540 - @param threshold Critical angle between between rotations at which - the algorithm switches to normalized lerp, which is more - numerically stable in those situations. 0.0 will always slerp. - */ - Quat slerp( - const Quat& other, - float alpha, - float threshold = 0.05f) const; - - /** Normalized linear interpolation of quaternion components. */ - Quat nlerp(const Quat& other, float alpha) const; - - /** - Negates the imaginary part. - */ - inline Quat conj() const { - return Quat(-x, -y, -z, w); - } - - inline float sum() const { - return x + y + z + w; - } - - inline float average() const { - return sum() / 4.0f; - } - - inline Quat operator*(float s) const { - return Quat(x * s, y * s, z * s, w * s); - } - - inline Quat& operator*=(float s) { - x *= s; - y *= s; - z *= s; - w *= s; - return *this; - } - - /** @cite Based on Watt & Watt, page 360 */ - friend Quat operator* (float s, const Quat& q); - - inline Quat operator/(float s) const { - return Quat(x / s, y / s, z / s, w / s); - } - - inline float dot(const Quat& other) const { - return (x * other.x) + (y * other.y) + (z * other.z) + (w * other.w); - } - - /** Note that q-1 = q.conj() for a unit quaternion. - @cite Dam99 page 13 */ - inline Quat inverse() const { - return conj() / dot(*this); - } - - Quat operator-(const Quat& other) const; - - Quat operator+(const Quat& other) const; - - /** - Quaternion multiplication (composition of rotations). - Note that this does not commute. - */ - Quat operator*(const Quat& other) const; - - /* (*this) * other.inverse() */ - Quat operator/(const Quat& other) const { - return (*this) * other.inverse(); - } - - - /** Is the magnitude nearly 1.0? */ - inline bool isUnit(float tolerance = 1e-5) const { - return abs(dot(*this) - 1.0f) < tolerance; - } - - - inline float magnitude() const { - return sqrtf(dot(*this)); - } - - inline Quat log() const { - if ((x == 0) && (y == 0) && (z == 0)) { - if (w > 0) { - return Quat(0, 0, 0, ::logf(w)); - } else if (w < 0) { - // Log of a negative number. Multivalued, any number of the form - // (PI * v, ln(-q.w)) - return Quat((float)pi(), 0, 0, ::logf(-w)); - } else { - // log of zero! - return Quat((float)nan(), (float)nan(), (float)nan(), (float)nan()); - } - } else { - // Partly imaginary. - float imagLen = sqrtf(x * x + y * y + z * z); - float len = sqrtf(imagLen * imagLen + w * w); - float theta = atan2f(imagLen, (float)w); - float t = theta / imagLen; - return Quat(t * x, t * y, t * z, ::logf(len)); - } - } - /** log q = [Av, 0] where q = [sin(A) * v, cos(A)]. - Only for unit quaternions - debugAssertM(isUnit(), "Log only defined for unit quaternions"); - // Solve for A in q = [sin(A)*v, cos(A)] - Vector3 u(x, y, z); - double len = u.magnitude(); - - if (len == 0.0) { - return - } - double A = atan2((double)w, len); - Vector3 v = u / len; - - return Quat(v * A, 0); - } - */ - - /** exp q = [sin(A) * v, cos(A)] where q = [Av, 0]. - Only defined for pure-vector quaternions */ - inline Quat exp() const { - debugAssertM(w == 0, "exp only defined for vector quaternions"); - Vector3 u(x, y, z); - float A = u.magnitude(); - Vector3 v = u / A; - return Quat(sinf(A) * v, cosf(A)); - } - - - /** - Raise this quaternion to a power. For a rotation, this is - the effect of rotating x times as much as the original - quaterion. - - Note that q.pow(a).pow(b) == q.pow(a + b) - @cite Dam98 pg 21 - */ - inline Quat pow(float x) const { - return (log() * x).exp(); - } - - inline void unitize() { - float mag2 = dot(*this); - if (! G3D::fuzzyEq(mag2, 1.0f)) { - *this *= rsq(mag2); - } - } - - /** - Returns a unit quaterion obtained by dividing through by - the magnitude. - */ - inline Quat toUnit() const { - Quat x = *this; - x.unitize(); - return x; - } - - /** - The linear algebra 2-norm, sqrt(q dot q). This matches - the value used in Dam's 1998 tech report but differs from the - n(q) value used in Eberly's 1999 paper, which is the square of the - norm. - */ - inline float norm() const { - return magnitude(); - } - - // access quaternion as q[0] = q.x, q[1] = q.y, q[2] = q.z, q[3] = q.w - // - // WARNING. These member functions rely on - // (1) Quat not having virtual functions - // (2) the data packed in a 4*sizeof(float) memory block - const float& operator[] (int i) const; - float& operator[] (int i); - - /** Generate uniform random unit quaternion (i.e. random "direction") - @cite From "Uniform Random Rotations", Ken Shoemake, Graphics Gems III. - */ - static Quat unitRandom(); - - void deserialize(class BinaryInput& b); - void serialize(class BinaryOutput& b) const; - - // 2-char swizzles - - Vector2 xx() const; - Vector2 yx() const; - Vector2 zx() const; - Vector2 wx() const; - Vector2 xy() const; - Vector2 yy() const; - Vector2 zy() const; - Vector2 wy() const; - Vector2 xz() const; - Vector2 yz() const; - Vector2 zz() const; - Vector2 wz() const; - Vector2 xw() const; - Vector2 yw() const; - Vector2 zw() const; - Vector2 ww() const; - - // 3-char swizzles - - Vector3 xxx() const; - Vector3 yxx() const; - Vector3 zxx() const; - Vector3 wxx() const; - Vector3 xyx() const; - Vector3 yyx() const; - Vector3 zyx() const; - Vector3 wyx() const; - Vector3 xzx() const; - Vector3 yzx() const; - Vector3 zzx() const; - Vector3 wzx() const; - Vector3 xwx() const; - Vector3 ywx() const; - Vector3 zwx() const; - Vector3 wwx() const; - Vector3 xxy() const; - Vector3 yxy() const; - Vector3 zxy() const; - Vector3 wxy() const; - Vector3 xyy() const; - Vector3 yyy() const; - Vector3 zyy() const; - Vector3 wyy() const; - Vector3 xzy() const; - Vector3 yzy() const; - Vector3 zzy() const; - Vector3 wzy() const; - Vector3 xwy() const; - Vector3 ywy() const; - Vector3 zwy() const; - Vector3 wwy() const; - Vector3 xxz() const; - Vector3 yxz() const; - Vector3 zxz() const; - Vector3 wxz() const; - Vector3 xyz() const; - Vector3 yyz() const; - Vector3 zyz() const; - Vector3 wyz() const; - Vector3 xzz() const; - Vector3 yzz() const; - Vector3 zzz() const; - Vector3 wzz() const; - Vector3 xwz() const; - Vector3 ywz() const; - Vector3 zwz() const; - Vector3 wwz() const; - Vector3 xxw() const; - Vector3 yxw() const; - Vector3 zxw() const; - Vector3 wxw() const; - Vector3 xyw() const; - Vector3 yyw() const; - Vector3 zyw() const; - Vector3 wyw() const; - Vector3 xzw() const; - Vector3 yzw() const; - Vector3 zzw() const; - Vector3 wzw() const; - Vector3 xww() const; - Vector3 yww() const; - Vector3 zww() const; - Vector3 www() const; - - // 4-char swizzles - - Vector4 xxxx() const; - Vector4 yxxx() const; - Vector4 zxxx() const; - Vector4 wxxx() const; - Vector4 xyxx() const; - Vector4 yyxx() const; - Vector4 zyxx() const; - Vector4 wyxx() const; - Vector4 xzxx() const; - Vector4 yzxx() const; - Vector4 zzxx() const; - Vector4 wzxx() const; - Vector4 xwxx() const; - Vector4 ywxx() const; - Vector4 zwxx() const; - Vector4 wwxx() const; - Vector4 xxyx() const; - Vector4 yxyx() const; - Vector4 zxyx() const; - Vector4 wxyx() const; - Vector4 xyyx() const; - Vector4 yyyx() const; - Vector4 zyyx() const; - Vector4 wyyx() const; - Vector4 xzyx() const; - Vector4 yzyx() const; - Vector4 zzyx() const; - Vector4 wzyx() const; - Vector4 xwyx() const; - Vector4 ywyx() const; - Vector4 zwyx() const; - Vector4 wwyx() const; - Vector4 xxzx() const; - Vector4 yxzx() const; - Vector4 zxzx() const; - Vector4 wxzx() const; - Vector4 xyzx() const; - Vector4 yyzx() const; - Vector4 zyzx() const; - Vector4 wyzx() const; - Vector4 xzzx() const; - Vector4 yzzx() const; - Vector4 zzzx() const; - Vector4 wzzx() const; - Vector4 xwzx() const; - Vector4 ywzx() const; - Vector4 zwzx() const; - Vector4 wwzx() const; - Vector4 xxwx() const; - Vector4 yxwx() const; - Vector4 zxwx() const; - Vector4 wxwx() const; - Vector4 xywx() const; - Vector4 yywx() const; - Vector4 zywx() const; - Vector4 wywx() const; - Vector4 xzwx() const; - Vector4 yzwx() const; - Vector4 zzwx() const; - Vector4 wzwx() const; - Vector4 xwwx() const; - Vector4 ywwx() const; - Vector4 zwwx() const; - Vector4 wwwx() const; - Vector4 xxxy() const; - Vector4 yxxy() const; - Vector4 zxxy() const; - Vector4 wxxy() const; - Vector4 xyxy() const; - Vector4 yyxy() const; - Vector4 zyxy() const; - Vector4 wyxy() const; - Vector4 xzxy() const; - Vector4 yzxy() const; - Vector4 zzxy() const; - Vector4 wzxy() const; - Vector4 xwxy() const; - Vector4 ywxy() const; - Vector4 zwxy() const; - Vector4 wwxy() const; - Vector4 xxyy() const; - Vector4 yxyy() const; - Vector4 zxyy() const; - Vector4 wxyy() const; - Vector4 xyyy() const; - Vector4 yyyy() const; - Vector4 zyyy() const; - Vector4 wyyy() const; - Vector4 xzyy() const; - Vector4 yzyy() const; - Vector4 zzyy() const; - Vector4 wzyy() const; - Vector4 xwyy() const; - Vector4 ywyy() const; - Vector4 zwyy() const; - Vector4 wwyy() const; - Vector4 xxzy() const; - Vector4 yxzy() const; - Vector4 zxzy() const; - Vector4 wxzy() const; - Vector4 xyzy() const; - Vector4 yyzy() const; - Vector4 zyzy() const; - Vector4 wyzy() const; - Vector4 xzzy() const; - Vector4 yzzy() const; - Vector4 zzzy() const; - Vector4 wzzy() const; - Vector4 xwzy() const; - Vector4 ywzy() const; - Vector4 zwzy() const; - Vector4 wwzy() const; - Vector4 xxwy() const; - Vector4 yxwy() const; - Vector4 zxwy() const; - Vector4 wxwy() const; - Vector4 xywy() const; - Vector4 yywy() const; - Vector4 zywy() const; - Vector4 wywy() const; - Vector4 xzwy() const; - Vector4 yzwy() const; - Vector4 zzwy() const; - Vector4 wzwy() const; - Vector4 xwwy() const; - Vector4 ywwy() const; - Vector4 zwwy() const; - Vector4 wwwy() const; - Vector4 xxxz() const; - Vector4 yxxz() const; - Vector4 zxxz() const; - Vector4 wxxz() const; - Vector4 xyxz() const; - Vector4 yyxz() const; - Vector4 zyxz() const; - Vector4 wyxz() const; - Vector4 xzxz() const; - Vector4 yzxz() const; - Vector4 zzxz() const; - Vector4 wzxz() const; - Vector4 xwxz() const; - Vector4 ywxz() const; - Vector4 zwxz() const; - Vector4 wwxz() const; - Vector4 xxyz() const; - Vector4 yxyz() const; - Vector4 zxyz() const; - Vector4 wxyz() const; - Vector4 xyyz() const; - Vector4 yyyz() const; - Vector4 zyyz() const; - Vector4 wyyz() const; - Vector4 xzyz() const; - Vector4 yzyz() const; - Vector4 zzyz() const; - Vector4 wzyz() const; - Vector4 xwyz() const; - Vector4 ywyz() const; - Vector4 zwyz() const; - Vector4 wwyz() const; - Vector4 xxzz() const; - Vector4 yxzz() const; - Vector4 zxzz() const; - Vector4 wxzz() const; - Vector4 xyzz() const; - Vector4 yyzz() const; - Vector4 zyzz() const; - Vector4 wyzz() const; - Vector4 xzzz() const; - Vector4 yzzz() const; - Vector4 zzzz() const; - Vector4 wzzz() const; - Vector4 xwzz() const; - Vector4 ywzz() const; - Vector4 zwzz() const; - Vector4 wwzz() const; - Vector4 xxwz() const; - Vector4 yxwz() const; - Vector4 zxwz() const; - Vector4 wxwz() const; - Vector4 xywz() const; - Vector4 yywz() const; - Vector4 zywz() const; - Vector4 wywz() const; - Vector4 xzwz() const; - Vector4 yzwz() const; - Vector4 zzwz() const; - Vector4 wzwz() const; - Vector4 xwwz() const; - Vector4 ywwz() const; - Vector4 zwwz() const; - Vector4 wwwz() const; - Vector4 xxxw() const; - Vector4 yxxw() const; - Vector4 zxxw() const; - Vector4 wxxw() const; - Vector4 xyxw() const; - Vector4 yyxw() const; - Vector4 zyxw() const; - Vector4 wyxw() const; - Vector4 xzxw() const; - Vector4 yzxw() const; - Vector4 zzxw() const; - Vector4 wzxw() const; - Vector4 xwxw() const; - Vector4 ywxw() const; - Vector4 zwxw() const; - Vector4 wwxw() const; - Vector4 xxyw() const; - Vector4 yxyw() const; - Vector4 zxyw() const; - Vector4 wxyw() const; - Vector4 xyyw() const; - Vector4 yyyw() const; - Vector4 zyyw() const; - Vector4 wyyw() const; - Vector4 xzyw() const; - Vector4 yzyw() const; - Vector4 zzyw() const; - Vector4 wzyw() const; - Vector4 xwyw() const; - Vector4 ywyw() const; - Vector4 zwyw() const; - Vector4 wwyw() const; - Vector4 xxzw() const; - Vector4 yxzw() const; - Vector4 zxzw() const; - Vector4 wxzw() const; - Vector4 xyzw() const; - Vector4 yyzw() const; - Vector4 zyzw() const; - Vector4 wyzw() const; - Vector4 xzzw() const; - Vector4 yzzw() const; - Vector4 zzzw() const; - Vector4 wzzw() const; - Vector4 xwzw() const; - Vector4 ywzw() const; - Vector4 zwzw() const; - Vector4 wwzw() const; - Vector4 xxww() const; - Vector4 yxww() const; - Vector4 zxww() const; - Vector4 wxww() const; - Vector4 xyww() const; - Vector4 yyww() const; - Vector4 zyww() const; - Vector4 wyww() const; - Vector4 xzww() const; - Vector4 yzww() const; - Vector4 zzww() const; - Vector4 wzww() const; - Vector4 xwww() const; - Vector4 ywww() const; - Vector4 zwww() const; - Vector4 wwww() const; -}; - -inline Quat exp(const Quat& q) { - return q.exp(); -} - -inline Quat log(const Quat& q) { - return q.log(); -} - -inline G3D::Quat operator*(double s, const G3D::Quat& q) { - return q * (float)s; -} - -inline G3D::Quat operator*(float s, const G3D::Quat& q) { - return q * s; -} - -inline float& Quat::operator[] (int i) { - debugAssert(i >= 0); - debugAssert(i < 4); - return ((float*)this)[i]; -} - -inline const float& Quat::operator[] (int i) const { - debugAssert(i >= 0); - debugAssert(i < 4); - return ((float*)this)[i]; -} - -inline Quat Quat::operator-(const Quat& other) const { - return Quat(x - other.x, y - other.y, z - other.z, w - other.w); -} - -inline Quat Quat::operator+(const Quat& other) const { - return Quat(x + other.x, y + other.y, z + other.z, w + other.w); -} - -} // Namespace G3D - -// Outside the namespace to avoid overloading confusion for C++ -inline G3D::Quat pow(const G3D::Quat& q, double x) { - return q.pow((float)x); -} - - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Queue.h b/externals/g3dlite/G3D.lib/include/G3D/Queue.h deleted file mode 100644 index b64eced820a..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Queue.h +++ /dev/null @@ -1,355 +0,0 @@ -/** - @file Queue.h - - @maintainer Morgan McGuire, graphics3d.com - - @created 2002-07-09 - @edited 2005-08-20 - */ - -#ifndef G3D_QUEUE_H -#define G3D_QUEUE_H - -#include "G3D/platform.h" -#include "G3D/System.h" -#include "G3D/debug.h" - -namespace G3D { - -/** - Locate the indices of the break between of the two - sections of the circular queue. These are used to - construct two for loops that iterate over the whole - sequence without using the modulo operator. - - [0 ... secondEnd) [head .... firstEnd) - */ -#define FIND_ENDS \ - int firstEnd = head + num;\ - int secondEnd = 0;\ - if (firstEnd > numAllocated) {\ - secondEnd = firstEnd - numAllocated;\ - firstEnd = numAllocated;\ - } - - -/** - Dynamic queue that uses a circular buffer for performance. - - Faster than std::deque for objects with constructors. - */ -template -class Queue { -private: - // - // |<---- num ---->| - // [ | | | | | | | | | | | | | ] - // ^ - // | - // head - // - // - - /** - Only num elements are initialized. - */ - T* data; - - /** - Index of the next element to be dequeue-d in data. - */ - int head; - - /** - Number of elements (including head) that are visible and initialized. - */ - int num; - - /** - Size of data array in elements. - */ - int numAllocated; - - /** If a clear was needed, assumes it already occured */ - void _copy(const Queue& other) { - debugAssert(data == NULL); - data = (T*)System::malloc(sizeof(T) * other.numAllocated); - debugAssert(data); - head = other.head; - num = other.num; - numAllocated = other.numAllocated; - - FIND_ENDS; - - for (int i = head; i < firstEnd; ++i) { - new (data + i)T(other.data[i]); - } - - for (int i = 0; i < secondEnd; ++i) { - new (data + i)T(other.data[i]); - } - } - - - /** - Computes a data array index from a queue position. The queue position - may be negative. - */ - inline int index(int i) const { - return (head + i + numAllocated) % numAllocated; - } - - /** - Allocates newSize elements and repacks the array. - */ - void repackAndRealloc(int newSize) { - // TODO: shrink queue - T* old = data; - data = (T*)System::malloc(newSize * sizeof(T)); - debugAssert(data != NULL); - - FIND_ENDS; - - int j = 0; - for (int i = head; i < firstEnd; ++i, ++j) { - new (data + j)T(old[i]); - (old + i)->~T(); - } - - for (int i = 0; i < secondEnd; ++i, ++j) { - new (data + j)T(old[i]); - (old + i)->~T(); - } - - head = 0; - System::free(old); - numAllocated = newSize; - } - - /** - Ensure that there is at least one element between - the tail and head, wrapping around in the circular - buffer. - */ - inline void reserveSpace() { - if (num == numAllocated) { - repackAndRealloc(numAllocated * 3 + 20); - } - } - -public: - - Queue() : - data(NULL), - head(0), - num(0), - numAllocated(0) { - } - - - /** - Copy constructor - */ - Queue(const Queue& other) : data(NULL) { - _copy(other); - } - - - /** - Destructor does not delete() the objects if T is a pointer type - (e.g. T = int*) instead, it deletes the pointers themselves and - leaves the objects. Call deleteAll if you want to dealocate - the objects referenced. - */ - virtual ~Queue() { - clear(); - } - - /** - Insert a new element into the front of the queue - (a traditional queue only uses pushBack). - */ - inline void pushFront(const T& e) { - reserveSpace(); - - // Get the index of head-1 - int i = index(-1); - - // Call the constructor on the newly exposed element. - new (data + i)T(e); - - // Reassign the head to point to this index - head = i; - ++num; - } - - /** - Insert a new element at the end of the queue. - */ - inline void pushBack(const T& e) { - reserveSpace(); - - // Get the index of 1+tail - int i = index(num); - - // Initialize that element - new (data + i)T(e); - ++num; - } - - /** - pushBack - */ - inline void enqueue(const T& e) { - pushBack(e); - } - - - /** - Remove the last element from the queue. The queue will never - shrink in size. (A typical queue only uses popFront). - */ - inline T popBack() { - int tail = index(num - 1); - T result(data[tail]); - - // Call the destructor - (data + tail)->~T(); - --num; - - return result; - } - - /** - Remove the next element from the head of the queue. The queue will never - shrink in size. */ - inline T popFront() { - T result(data[head]); - // Call the destructor - (data + head)->~T(); - head = (head + 1) % numAllocated; - --num; - return result; - } - - - /** - popFront - */ - inline T dequeue() { - return popFront(); - } - - /** - Removes all elements (invoking their destructors). - - @param freeStorage If false, the underlying array is not deallocated - (allowing fast push in the future), however, the size of the Queue - is reported as zero. - - */ - void clear(bool freeStorage = true) { - - FIND_ENDS; - - // Invoke the destructors on the elements - int i; - for (i = head; i < firstEnd; ++i) { - (data + i)->~T(); - } - - for (i = 0; i < secondEnd; ++i) { - (data + i)->~T(); - } - - num = 0; - head = 0; - if (freeStorage) { - numAllocated = 0; - System::free(data); - data = NULL; - } - } - - /** Clear without freeing the underlying array. */ - void fastClear() { - clear(false); - } - - /** - Assignment operator. - */ - Queue& operator=(const Queue& other) { - clear(); - _copy(other); - return *this; - } - - /** - Number of elements in the queue. - */ - inline int size() const { - return num; - } - - /** - Number of elements in the queue. - */ - inline int length() const { - return size(); - } - - /** - Performs bounds checks in debug mode - */ - inline T& operator[](int n) { - debugAssert((n >= 0) && (n < num)); - return data[index(n)]; - } - - /** - Performs bounds checks in debug mode - */ - inline const T& operator[](int n) const { - debugAssert((n >= 0) && (n < num)); - return data[index(n)]; - } - - - /** - Returns true if the given element is in the queue. - */ - bool contains(const T& e) const { - for (int i = 0; i < size(); ++i) { - if ((*this)[i] == e) { - return true; - } - } - - return false; - } - - /** - Calls delete on all objects[0...size-1] - and sets the queue size to zero. - */ - void deleteAll() { - FIND_ENDS; - - int i; - for (i = 0; i < secondEnd; ++i) { - delete data[i]; - } - - for (i = head; i < firstEnd; ++i) { - delete data[i]; - } - clear(); - } -}; - -#undef FIND_ENDS - -}; // namespace - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Ray.h b/externals/g3dlite/G3D.lib/include/G3D/Ray.h deleted file mode 100644 index ab43c82933a..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Ray.h +++ /dev/null @@ -1,329 +0,0 @@ -/** - @file Ray.h - - Ray class - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2002-07-12 - @edited 2006-02-21 - */ - -#ifndef G3D_RAY_H -#define G3D_RAY_H - -#include "G3D/platform.h" -#include "G3D/Vector3.h" -#include "G3D/Triangle.h" - -namespace G3D { - -/** - A 3D Ray. - */ -class Ray { -private: - Ray(const Vector3& origin, const Vector3& direction) { - this->origin = origin; - this->direction = direction; - } - -public: - Vector3 origin; - - /** - Not unit length - */ - Vector3 direction; - - Ray() : origin(Vector3::zero()), direction(Vector3::zero()) {} - - Ray(class BinaryInput& b); - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); - - /** - Creates a Ray from a origin and a (nonzero) direction. - */ - static Ray fromOriginAndDirection(const Vector3& point, const Vector3& direction) { - return Ray(point, direction); - } - - Ray unit() const { - return Ray(origin, direction.unit()); - } - - /** - Returns the closest point on the Ray to point. - */ - Vector3 closestPoint(const Vector3& point) const { - float t = direction.dot(point - this->origin); - if (t < 0) { - return this->origin; - } else { - return this->origin + direction * t; - } - } - - /** - Returns the closest distance between point and the Ray - */ - float distance(const Vector3& point) const { - return (closestPoint(point) - point).magnitude(); - } - - /** - Returns the point where the Ray and plane intersect. If there - is no intersection, returns a point at infinity. - - Planes are considered one-sided, so the ray will not intersect - a plane where the normal faces in the traveling direction. - */ - Vector3 intersection(const class Plane& plane) const; - - /** - Returns the distance until intersection with the (solid) sphere. - Will be 0 if inside the sphere, inf if there is no intersection. - - The ray direction is not normalized. If the ray direction - has unit length, the distance from the origin to intersection - is equal to the time. If the direction does not have unit length, - the distance = time * direction.length(). - - See also the G3D::CollisionDetection "movingPoint" methods, - which give more information about the intersection. - */ - float intersectionTime(const class Sphere& sphere) const; - - float intersectionTime(const class Plane& plane) const; - - float intersectionTime(const class Box& box) const; - - float intersectionTime(const class AABox& box) const; - - /** - The three extra arguments are the weights of vertices 0, 1, and 2 - at the intersection point; they are useful for texture mapping - and interpolated normals. - */ - float intersectionTime( - const Vector3& v0, const Vector3& v1, const Vector3& v2, - const Vector3& edge01, const Vector3& edge02, - double& w0, double& w1, double& w2) const; - - /** - Ray-triangle intersection for a 1-sided triangle. Fastest version. - @cite http://www.acm.org/jgt/papers/MollerTrumbore97/ - http://www.graphics.cornell.edu/pubs/1997/MT97.html - */ - inline float intersectionTime( - const Vector3& vert0, - const Vector3& vert1, - const Vector3& vert2, - const Vector3& edge01, - const Vector3& edge02) const; - - - inline float intersectionTime( - const Vector3& vert0, - const Vector3& vert1, - const Vector3& vert2) const { - - return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0); - } - - - inline float intersectionTime( - const Vector3& vert0, - const Vector3& vert1, - const Vector3& vert2, - double& w0, - double& w1, - double& w2) const { - - return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0, w0, w1, w2); - } - - /* One-sided triangle - */ - inline float intersectionTime(const Triangle& triangle) const { - return intersectionTime( - triangle.vertex(0), triangle.vertex(1), triangle.vertex(2), - triangle.edge01(), triangle.edge02()); - } - - inline float intersectionTime( - const Triangle& triangle, - double& w0, - double& w1, - double& w2) const { - return intersectionTime(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2), - triangle.edge01(), triangle.edge02(), w0, w1, w2); - } - - /** Refracts about the normal - using G3D::Vector3::refractionDirection - and bumps the ray slightly from the newOrigin. */ - Ray refract( - const Vector3& newOrigin, - const Vector3& normal, - float iInside, - float iOutside) const; - - /** Reflects about the normal - using G3D::Vector3::reflectionDirection - and bumps the ray slightly from - the newOrigin. */ - Ray reflect( - const Vector3& newOrigin, - const Vector3& normal) const; -}; - - -#define EPSILON 0.000001 -#define CROSS(dest,v1,v2) \ - dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \ - dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \ - dest[2]=v1[0]*v2[1]-v1[1]*v2[0]; - -#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]) - -#define SUB(dest,v1,v2) \ - dest[0]=v1[0]-v2[0]; \ - dest[1]=v1[1]-v2[1]; \ - dest[2]=v1[2]-v2[2]; - -inline float Ray::intersectionTime( - const Vector3& vert0, - const Vector3& vert1, - const Vector3& vert2, - const Vector3& edge1, - const Vector3& edge2) const { - - (void)vert1; - (void)vert2; - - // Barycenteric coords - float u, v; - - float tvec[3], pvec[3], qvec[3]; - - // begin calculating determinant - also used to calculate U parameter - CROSS(pvec, direction, edge2); - - // if determinant is near zero, ray lies in plane of triangle - const float det = DOT(edge1, pvec); - - if (det < EPSILON) { - return (float)inf(); - } - - // calculate distance from vert0 to ray origin - SUB(tvec, origin, vert0); - - // calculate U parameter and test bounds - u = DOT(tvec, pvec); - if ((u < 0.0f) || (u > det)) { - // Hit the plane outside the triangle - return (float)inf(); - } - - // prepare to test V parameter - CROSS(qvec, tvec, edge1); - - // calculate V parameter and test bounds - v = DOT(direction, qvec); - if ((v < 0.0f) || (u + v > det)) { - // Hit the plane outside the triangle - return (float)inf(); - } - - - // Case where we don't need correct (u, v): - const float t = DOT(edge2, qvec); - - if (t >= 0.0f) { - // Note that det must be positive - return t / det; - } else { - // We had to travel backwards in time to intersect - return (float)inf(); - } -} - - -inline float Ray::intersectionTime( - const Vector3& vert0, - const Vector3& vert1, - const Vector3& vert2, - const Vector3& edge1, - const Vector3& edge2, - double& w0, - double& w1, - double& w2) const { - - (void)vert1; - (void)vert2; - - // Barycenteric coords - float u, v; - - float tvec[3], pvec[3], qvec[3]; - - // begin calculating determinant - also used to calculate U parameter - CROSS(pvec, direction, edge2); - - // if determinant is near zero, ray lies in plane of triangle - const float det = DOT(edge1, pvec); - - if (det < EPSILON) { - return (float)inf(); - } - - // calculate distance from vert0 to ray origin - SUB(tvec, origin, vert0); - - // calculate U parameter and test bounds - u = DOT(tvec, pvec); - if ((u < 0.0f) || (u > det)) { - // Hit the plane outside the triangle - return (float)inf(); - } - - // prepare to test V parameter - CROSS(qvec, tvec, edge1); - - // calculate V parameter and test bounds - v = DOT(direction, qvec); - if ((v < 0.0f) || (u + v > det)) { - // Hit the plane outside the triangle - return (float)inf(); - } - - float t = DOT(edge2, qvec); - - if (t >= 0) { - const float inv_det = 1.0f / det; - t *= inv_det; - u *= inv_det; - v *= inv_det; - - w0 = (1.0f - u - v); - w1 = u; - w2 = v; - - return t; - } else { - // We had to travel backwards in time to intersect - return (float)inf(); - } -} - -#undef EPSILON -#undef CROSS -#undef DOT -#undef SUB - -}// namespace - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Rect2D.h b/externals/g3dlite/G3D.lib/include/G3D/Rect2D.h deleted file mode 100644 index a6c0b7cd0cb..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Rect2D.h +++ /dev/null @@ -1,391 +0,0 @@ -/** - @file Rect2D.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-11-13 - @created 2008-11-16 - - Copyright 2000-2008, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_RECT2D_H -#define G3D_RECT2D_H - -// Linux defines this as a macro -#ifdef border -#undef border -#endif - -#include "G3D/platform.h" -#include "G3D/Array.h" -#include "G3D/Vector2.h" - -namespace G3D { - -/** - If you are using this class for pixel rectangles, keep in mind that the last - pixel you can draw to is at x0() + width() - 1. - */ -class Rect2D { -private: - Vector2 min, max; - - /** - Returns true if the whole polygon is clipped. - @param p Value of the point - @param axis Index [0 or 1] of the axis to clip along? - @param clipGreater Are we clipping greater than or less than the line? - @param inPoly Polygon being clipped - @param outPoly The clipped polygon - */ - template - static bool clipSide2D( - const float p, bool clipGreater, int axis, - const Array& inPoly, Array& outPoly) { - - outPoly.clear(); - int i0 = -1; - - Vector2 pt1; - bool c1 = true; - - float negate = clipGreater ? -1 : 1; - - // Find a point that is not clipped - for (i0 = 0; (i0 < inPoly.length()) && c1; ++i0) { - pt1 = inPoly[i0]; - c1 = (negate * pt1[axis]) < (negate * p); - } - - // We incremented i0 one time to many - --i0; - - if (c1) { - // We could not find an unclipped point - return true; - } - - outPoly.append(pt1); - - // for each point in inPoly, - // if the point is outside the side and the previous one was also outside, continue - // if the point is outside the side and the previous one was inside, cut the line - // if the point is inside the side and the previous one was also inside, append the points - // if the point is inside the side and the previous one was outside, cut the line - for (int i = 1; i <= inPoly.length(); ++i) { - T pt2 = inPoly[(i + i0) % inPoly.length()]; - bool c2 = (negate * pt2[axis]) < (negate * p); - - if (c1 ^ c2) { - - if (!c1 && c2 && (i > 1)) { - // Unclipped to clipped trasition and not the first iteration - outPoly.append(pt1); - } - - // only one point is clipped, find where the line crosses the clipping plane - - - float alpha; - if (pt2[axis] == pt1[axis]) { - alpha = 0; - } else { - alpha = (p - pt1[axis]) / (pt2[axis] - pt1[axis]); - } - outPoly.append(pt1.lerp(pt2, alpha)); - } else if (! (c1 || c2) && (i != 1)) { - // neither point is clipped (don't do this the first time - // because we appended the first pt before the loop) - outPoly.append(pt1); - } - - pt1 = pt2; - c1 = c2; - } - - return false; - } - -public: - - inline Rect2D() : min(0, 0), max(0, 0) {} - - /** Creates a rectangle at 0,0 with the given width and height*/ - inline Rect2D(const Vector2& wh) : min(0, 0), max(wh.x, wh.y) {} - - /** Computes a rectangle that contains both @a a and @a b. - Note that even if @a or @b has zero area, its origin will be included.*/ - inline Rect2D(const Rect2D& a, const Rect2D& b) { - min = a.min.min(b.min); - max = a.max.max(b.max); - } - - /** @brief Uniformly random point on the interior */ - inline Vector2 randomPoint() const { - return Vector2(uniformRandom(0, max.x - min.x) + min.x, - uniformRandom(0, max.y - min.y) + min.y); - } - - inline float width() const { - return max.x - min.x; - } - - inline float height() const { - return max.y - min.y; - } - - inline float x0() const { - return min.x; - } - - inline float x1() const { - return max.x; - } - - inline float y0() const { - return min.y; - } - - inline float y1() const { - return max.y; - } - - /** Min, min corner */ - inline Vector2 x0y0() const { - return min; - } - - inline Vector2 x1y0() const { - return Vector2(max.x, min.y); - } - - inline Vector2 x0y1() const { - return Vector2(min.x, max.y); - } - - /** Max,max corner */ - inline Vector2 x1y1() const { - return max; - } - - /** Width and height */ - inline Vector2 wh() const { - return max - min; - } - - inline Vector2 center() const { - return (max + min) * 0.5; - } - - inline static Rect2D xyxy(float x0, float y0, float x1, float y1) { - Rect2D r; - - r.min.x = G3D::min(x0, x1); - r.min.y = G3D::min(y0, y1); - r.max.x = G3D::max(x0, x1); - r.max.y = G3D::max(y0, y1); - - return r; - } - - Rect2D lerp(const Rect2D& other, float alpha) const { - Rect2D out; - - out.min = min.lerp(other.min, alpha); - out.max = max.lerp(other.max, alpha); - - return out; - } - - inline static Rect2D xyxy(const Vector2& v0, const Vector2& v1) { - Rect2D r; - - r.min = v0.min(v1); - r.max = v0.max(v1); - - return r; - } - - inline static Rect2D xywh(float x, float y, float w, float h) { - return xyxy(x, y, x + w, y + h); - } - - inline static Rect2D xywh(const Vector2& v, const Vector2& w) { - return xyxy(v.x, v.y, v.x + w.x, v.y + w.y); - } - - inline bool contains(const Vector2& v) const { - return (v.x >= min.x) && (v.y >= min.y) && (v.x <= max.x) && (v.y <= max.y); - } - - inline bool contains(const Rect2D& r) const { - return (min.x <= r.min.x) && (min.y <= r.min.y) && - (max.x >= r.max.x) && (max.y >= r.max.y); - } - - /** True if there is non-zero area to the intersection between @a this and @a r. - Note that two rectangles that are adjacent do not intersect because there is - zero area to the overlap, even though one of them "contains" the corners of the other.*/ - inline bool intersects(const Rect2D& r) const { - return (min.x < r.max.x) && (min.y < r.max.y) && - (max.x > r.min.x) && (max.y > r.min.y); - } - - /** Like intersection, but counts the adjacent case as touching. */ - inline bool intersectsOrTouches(const Rect2D& r) const { - return (min.x <= r.max.x) && (min.y <= r.max.y) && - (max.x >= r.min.x) && (max.y >= r.min.y); - } - - inline Rect2D operator*(float s) const { - return xyxy(min.x * s, min.y * s, max.x * s, max.y * s); - } - - inline Rect2D operator/(float s) const { - return xyxy(min / s, max / s); - } - - inline Rect2D operator/(const Vector2& s) const { - return xyxy(min / s, max / s); - } - - inline Rect2D operator+(const Vector2& v) const { - return xyxy(min + v, max + v); - } - - inline Rect2D operator-(const Vector2& v) const { - return xyxy(min - v, max - v); - } - - inline bool operator==(const Rect2D& other) const { - return (min == other.min) && (max == other.max); - } - - inline bool operator!=(const Rect2D& other) const { - return (min != other.min) || (max != other.max); - } - - /** Returns the corners in the order: (min,min), (max,min), (max,max), (min,max). */ - inline Vector2 corner(int i) const { - debugAssert(i >= 0 && i < 4); - switch (i & 3) { - case 0: - return Vector2(min.x, min.y); - case 1: - return Vector2(max.x, min.y); - case 2: - return Vector2(max.x, max.y); - case 3: - return Vector2(min.x, max.y); - default: - // Should never get here - return Vector2(0, 0); - } - } - - - /** @deprecated - @sa expand() */ - inline Rect2D border(float delta) const { - return Rect2D::xywh(x0() + delta, - y0() + delta, - width() - 2.0f * delta, - height() - 2.0f * delta); - } - - /** Returns a new Rect2D that is bigger/smaller by the specified amount - (negative is shrink.) */ - inline Rect2D expand(float delta) const { - float newX = x0() - delta; - float newY = y0() - delta; - float newW = width() + 2.0f * delta; - float newH = height() + 2.0f * delta; - - if (newW < 0.0f) { - newX = (x0() + width()) / 2.0f; - newW = 0.0f; - } - - if (newH < 0.0f) { - newY = (y0() + height()) / 2.0f; - newH = 0.0f; - } - return Rect2D::xywh(newX, newY, newW, newH); - } - - /** - Clips so that the rightmost point of the outPoly is at rect.x1 (e.g. a 800x600 window produces - rightmost point 799, not 800). The results are suitable for pixel rendering if iRounded. - Templated so that it will work for Vector2,3,4 (the z and w components are interpolated linearly). - The template parameter must define T.lerp and contain x and y components. - - If the entire polygon is clipped by a single side, the result will be empty. - The result might also have zero area but not be empty. - */ - template - void clip(const Array& inPoly, Array& outPoly) const { - - const bool greaterThan = true; - const bool lessThan = false; - const int X = 0; - const int Y = 1; - - Array temp; - - bool entirelyClipped = - clipSide2D(x0(), lessThan, X, inPoly, temp) || - clipSide2D(x1(), greaterThan, X, temp, outPoly) || - clipSide2D(y0(), lessThan, Y, outPoly, temp) || - clipSide2D(y1(), greaterThan, Y, temp, outPoly); - - if (entirelyClipped) { - outPoly.clear(); - } - } - - - /** Returns the largest, centered Rect2D that can fit inside this - while maintaining the aspect ratio of x:y. Convenient for - displaying images in odd-shaped windows. - */ - Rect2D largestCenteredSubRect(float ww, float hh) const { - float textureAspect = hh / ww; - float viewAspect = height() / width(); - - if (viewAspect > textureAspect) { - // The view is too tall - float h = width() * textureAspect; - float y = (height() - h) / 2; - return Rect2D::xywh(0, y, width(), h) + corner(0); - } else { - // The view is too wide - float w = height() / textureAspect; - float x = (width() - w) / 2; - return Rect2D::xywh(x, 0, w, height()) + corner(0); - } - } - - /** - Returns the overlap region between the two rectangles. This may have zero area - if they do not intersect. See the two-Rect2D constructor for a way to compute - a union-like rectangle. - */ - Rect2D intersect(const Rect2D& other) const { - if (intersects(other)) { - return Rect2D::xyxy(min.max(other.min), max.min(other.max)); - }else{ - return Rect2D::xywh(0, 0, 0, 0); - } - } - - float area() const { - return width() * height(); - } -}; - -typedef Rect2D AABox2D; -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/ReferenceCount.h b/externals/g3dlite/G3D.lib/include/G3D/ReferenceCount.h deleted file mode 100644 index f55a22be0e1..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/ReferenceCount.h +++ /dev/null @@ -1,597 +0,0 @@ -/** - @file ReferenceCount.h - - Reference Counting Garbage Collector for C++ - - @maintainer Morgan McGuire, matrix@graphics3d.com - @cite Adapted and extended from Justin Miller's "RGC" class that appeared in BYTE magazine. - @cite See also http://www.jelovic.com/articles/cpp_without_memory_errors_slides.htm - - @created 2001-10-23 - @edited 2008-09-25 -*/ - -#ifndef G3D_RGC_H -#define G3D_RGC_H - -#include "G3D/platform.h" -#include "G3D/debug.h" -#include "G3D/AtomicInt32.h" - -namespace G3D { - -/** Base class for WeakReferenceCountedPointer */ -class _WeakPtr { -public: - inline virtual ~_WeakPtr() {} - -protected: - friend class ReferenceCountedObject; - - /** Called by ReferenceCountedObject to tell a weak pointer that its underlying object was collected. */ - virtual void objectCollected() = 0; -}; - -/** Used internally by ReferenceCountedObject */ -class _WeakPtrLinkedList { -public: - _WeakPtr* weakPtr; - _WeakPtrLinkedList* next; - - inline _WeakPtrLinkedList() : weakPtr(NULL), next(NULL) {} - - /** Inserts this node into the head of the list that previously had n as its head. */ - inline _WeakPtrLinkedList(_WeakPtr* p, _WeakPtrLinkedList* n) : weakPtr(p), next(n) {} -}; - -/** - Objects that are reference counted inherit from this. Subclasses - must have a public destructor (the default destructor is fine) - and publicly inherit ReferenceCountedObject. - - Multiple inheritance from a reference counted object is dangerous-- use - at your own risk. - - ReferenceCountedPointer and ReferenceCountedObject are threadsafe. - You can create and drop references on multiple threads without - violating integrity. WeakReferenceCountedPointer is not - threadsafe. Introducing a weak pointer destroys all thread safety, - even for strong pointers to the same object (this is inherent in the - design of the class; we cannot fix it without slowing down the - performance of reference counted objects.) - - Usage Example - -
-
-class Foo : public G3D::ReferenceCountedObject {
-public:
-    int x;
-};
-
-class Bar : public Foo {};
-
-typedef G3D::ReferenceCountedPointer FooRef;
-typedef G3D::WeakReferenceCountedPointer WeakFooRef;
-typedef G3D::ReferenceCountedPointer BarRef;
-
-
-int main(int argc, char *argv[]) {
-
-    WeakFooRef x;
-
-    {
-        FooRef a = new Foo();
-
-        // Reference count == 1
-
-        x = a;
-        // Weak references do not increase count
-
-        {
-            FooRef b = a;
-            // Reference count == 2
-        }
-
-        // Reference count == 1
-    }
-    // No more strong references; object automatically deleted.
-    // x is set to NULL automatically.
-
-    // Example of using dynamic cast on reference counted objects
-    BarRef b = new Bar();
-
-    // No cast needed to go down the heirarchy.
-    FooRef f = b;
-
-    // We can't cast the reference object because it is a class.
-    // Instead we must extract the pointer and cast that:
-    b = dynamic_cast(&*f);
-
-    return 0;
-}
-
- -@deprecated To be replaced by boost::shared_ptr in 7.0 - */ -class ReferenceCountedObject { -public: - - /** - The long name is to keep this from accidentally conflicting with - a subclass's variable name. Do not use or explicitly manipulate - this value--its type may change in the future and is not part - of the supported API. - */ - AtomicInt32 ReferenceCountedObject_refCount; - - /** - Linked list of all weak pointers that reference this (some may be - on the stack!). Do not use or explicitly manipulate this value. - */ - _WeakPtrLinkedList* ReferenceCountedObject_weakPointer; - -protected: - - ReferenceCountedObject() : - ReferenceCountedObject_refCount(0), - ReferenceCountedObject_weakPointer(0) { - - debugAssertM(isValidHeapPointer(this), - "Reference counted objects must be allocated on the heap."); - } - -public: - - /** Automatically called immediately before the object is deleted. - This is not called from the destructor because it needs to be invoked - before the subclass destructor. - */ - void ReferenceCountedObject_zeroWeakPointers() { - // Tell all of my weak pointers that I'm gone. - - _WeakPtrLinkedList* node = ReferenceCountedObject_weakPointer; - - while (node != 0) { - - // Notify the weak pointer that it is going away - node->weakPtr->objectCollected(); - - // Free the node and advance - _WeakPtrLinkedList* tmp = node; - node = node->next; - delete tmp; - } - } - - virtual ~ReferenceCountedObject() {} - - - /** - Note: copies will initially start out with 0 - references and 0 weak references like any other object. - */ - ReferenceCountedObject(const ReferenceCountedObject& notUsed) : - ReferenceCountedObject_refCount(0), - ReferenceCountedObject_weakPointer(0) { - (void)notUsed; - debugAssertM(G3D::isValidHeapPointer(this), - "Reference counted objects must be allocated on the heap."); - } - - ReferenceCountedObject& operator=(const ReferenceCountedObject& other) { - (void)other; - // Nothing changes when I am assigned; the reference count on - // both objects is the same (although my super-class probably - // changes). - return *this; - } -}; - - - -/** - Use ReferenceCountedPointer in place of T* in your program. - T must subclass ReferenceCountedObject. -@deprecated To be replaced by boost::shared_ptr in 7.0 - */ -template -class ReferenceCountedPointer { -private: - - T* m_pointer; - -public: - typedef T element_type; - - inline T* pointer() const { - return m_pointer; - } - -private: - - /** Nulls out the pointer and drops a reference. If the reference - count hits zero. */ - void zeroPointer() { - if (m_pointer != NULL) { - - debugAssert(G3D::isValidHeapPointer(m_pointer)); - debugAssertM(m_pointer->ReferenceCountedObject_refCount.value() > 0, - "Dangling reference detected."); - - // Only delete if this instance caused the count to hit - // exactly zero. If there is a race condition, the value - // may be zero after decrement returns, but only one of - // the instances will get a zero return value. - if (m_pointer->ReferenceCountedObject_refCount.decrement() == 0) { - // We held the last reference, so delete the object. - // This test is threadsafe because there is no way for - // the reference count to increase after the last - // reference was dropped (assuming the application does - // not voilate the class abstraction). - //debugPrintf(" delete 0x%x\n", m_pointer); - - // We must zero the weak pointers *before* deletion in case there - // are cycles of weak references. - // Note that since there are no strong references at this point, - // it is perfectly fair to zero the weak pointers anyway. - m_pointer->ReferenceCountedObject_zeroWeakPointers(); - delete m_pointer; - } - - m_pointer = NULL; - } - } - - /** Non-atomic (except for the referencec increment). Can only be - called in contexts like the copy constructor or initial - constructor where it is known that the reference count will - not hit zero on some other thread. */ - void setPointer(T* x) { - if (x != m_pointer) { - zeroPointer(); - - if (x != NULL) { - debugAssert(G3D::isValidHeapPointer(x)); - - m_pointer = x; - - // Note that the ref count can be zero if this is the - // first pointer to it - debugAssertM(m_pointer->ReferenceCountedObject_refCount.value() >= 0, - "Negative reference count detected."); - m_pointer->ReferenceCountedObject_refCount.increment(); - } - } - } - -public: - - inline ReferenceCountedPointer() : m_pointer(NULL) {} - - /** - Allow silent cast to the base class. - -
-        SubRef  s = new Sub();
-        BaseRef b = s;
-      
- - i.e., compile-time subtyping rule - RCP<T> <: RCP<S> if T <: S - */ - template - inline ReferenceCountedPointer(const ReferenceCountedPointer& p) : - m_pointer(NULL) { - setPointer(p.pointer()); - } - -# if (! defined(MSC_VER) || (MSC_VER >= 1300)) - /** - Explicit cast to a subclass. Acts like dynamic cast; the result will be NULL if - the cast cannot succeed. Not supported on VC6. -
-        SubRef  s = new Sub();
-        BaseRef b = s;
-        s = b.downcast();   // Note that the template argument is the object type, not the pointer type.
-      
- */ - template - ReferenceCountedPointer downcast() { - return ReferenceCountedPointer(dynamic_cast(m_pointer)); - } - - template - const ReferenceCountedPointer downcast() const { - return ReferenceCountedPointer(dynamic_cast(m_pointer)); - } -# endif - - // We need an explicit version of the copy constructor as well or - // the default copy constructor will be used. - inline ReferenceCountedPointer(const ReferenceCountedPointer& p) : m_pointer(NULL) { - setPointer(p.m_pointer); - } - - /** Allows construction from a raw pointer. That object will thereafter be - reference counted -- do not call delete on it. */ - inline ReferenceCountedPointer(T* p) : m_pointer(NULL) { - setPointer(p); - } - - inline ~ReferenceCountedPointer() { - zeroPointer(); - } - - inline size_t hashCode() const { - return reinterpret_cast(m_pointer);; - } - - inline const ReferenceCountedPointer& operator=(const ReferenceCountedPointer& p) { - setPointer(p.m_pointer); - return *this; - } - - inline ReferenceCountedPointer& operator=(T* p) { - setPointer(p); - return *this; - } - - inline bool operator==(const ReferenceCountedPointer& y) const { - return (m_pointer == y.m_pointer); - } - - inline bool operator!=(const ReferenceCountedPointer& y) const { - return (m_pointer != y.m_pointer); - } - - bool operator < (const ReferenceCountedPointer& y) const { - return (m_pointer < y.m_pointer); - } - - bool operator > (const ReferenceCountedPointer& y) const { - return (m_pointer > y.m_pointer); - } - - bool operator <= (const ReferenceCountedPointer& y) const { - return (m_pointer <= y.m_pointer); - } - - bool operator >= (const ReferenceCountedPointer& y) const { - return (m_pointer >= y.m_pointer); - } - - inline T& operator*() const { - debugAssertM(m_pointer != NULL, "Dereferenced a NULL ReferenceCountedPointer"); - return (*m_pointer); - } - - inline T* operator->() const { - debugAssertM(m_pointer != NULL, "Dereferenced a NULL ReferenceCountedPointer"); - return m_pointer; - } - - inline bool isNull() const { - return (m_pointer == NULL); - } - - inline bool notNull() const { - return (m_pointer != NULL); - } - - // TODO: distinguish between last strong and last any pointer - /** - Returns true if this is the last reference to an object. - Useful for flushing memoization caches-- a cache that holds the last - reference is unnecessarily keeping an object alive. - - Not threadsafe. - - @deprecated Use WeakReferenceCountedPointer for caches - */ - inline int isLastReference() const { - return (m_pointer->ReferenceCountedObject_refCount.value() == 1); - } -}; - - -/** - A weak pointer allows the object it references to be garbage collected. - Weak pointers are commonly used in caches, where it is important to hold - a pointer to an object without keeping that object alive solely for the - cache's benefit (i.e., the object can be collected as soon as all - pointers to it outside the cache are gone). They are also convenient - for adding back-pointers in tree and list structures. - - Weak pointers may become NULL at any point (when their target is collected). - Therefore the only way to reference the target is to convert to a strong - pointer and then check that it is not NULL. - -@deprecated To be replaced by boost::weak_ptr in 7.0 - */ -template -class WeakReferenceCountedPointer : public _WeakPtr { -private: - - /** NULL if the object has been collected. */ - T* pointer; - -public: - /** - Creates a strong pointer, which prevents the object from being - garbage collected. The strong pointer may be NULL, which means - that the underlying. - */ - // There is intentionally no way to check if the - // WeakReferenceCountedPointer has a null reference without - // creating a strong pointer since there is no safe way to use - // that information-- the pointer could be collected by a - // subsequent statement. - ReferenceCountedPointer createStrongPtr() const { - // TODO: What if the object's destructor is called while we - // are in this method? - return ReferenceCountedPointer(pointer); - } - - -private: - - /** - Thread issues: safe because this is only called when another - object is guaranteed to keep p alive for the duration of this - call. - */ - void setPointer(T* p) { - // TODO: must prevent the object from being collected while in - // this method - - zeroPointer(); - pointer = p; - - if (pointer != 0) { - // TODO: threadsafe: must update the list atomically - - // Add myself to the head of my target's list of weak pointers - _WeakPtrLinkedList* head = - new _WeakPtrLinkedList - (this, - pointer->ReferenceCountedObject_weakPointer); - - pointer->ReferenceCountedObject_weakPointer = head; - } else { - - } - } - - - /** - Removes this from its target's list of weak pointers. Called - when the weak pointer goes out of scope. - - Thread issues: depends on the thread safety of createStrongPtr. - */ - void zeroPointer() { - // Grab a strong reference to prevent the object from being collected while we - // are traversing its list. - ReferenceCountedPointer strong = createStrongPtr(); - - // If the following test fails then the object was collected before we - // reached it. - if (strong.notNull()) { - debugAssertM(pointer->ReferenceCountedObject_weakPointer != NULL, - "Weak pointer exists without a backpointer from the object."); - - // Remove myself from my target's list of weak pointers - _WeakPtrLinkedList** node = &pointer->ReferenceCountedObject_weakPointer; - while ((*node)->weakPtr != this) { - node = &((*node)->next); - debugAssertM(*node != NULL, - "Weak pointer exists without a backpointer from the object (2)."); - } - - // Node must now point at the node for me. Remove node and - // close the linked list behind it. - _WeakPtrLinkedList* temp = *node; - *node = temp->next; - - // Now delete the node corresponding to me - delete temp; - } - - pointer = NULL; - } - -public: - - WeakReferenceCountedPointer() : pointer(0) {} - - /** - Allow compile time subtyping rule - RCP<T> <: RCP<S> if T <: S - */ - template - inline WeakReferenceCountedPointer(const WeakReferenceCountedPointer& p) : pointer(0) { - // Threadsafe: the object cannot be collected while the other pointer exists. - setPointer(p.pointer); - } - - template - inline WeakReferenceCountedPointer(const ReferenceCountedPointer& p) : pointer(0) { - // Threadsafe: the object cannot be collected while the other - // pointer exists. - setPointer(p.pointer()); - } - - // Gets called a *lot* when weak pointers are on the stack - WeakReferenceCountedPointer( - const WeakReferenceCountedPointer& weakPtr) : pointer(0) { - setPointer(weakPtr.pointer); - } - - WeakReferenceCountedPointer( - const ReferenceCountedPointer& strongPtr) : pointer(0) { - setPointer(strongPtr.pointer()); - } - - ~WeakReferenceCountedPointer() { - zeroPointer(); - } - - WeakReferenceCountedPointer& operator=(const WeakReferenceCountedPointer& other) { - // Threadsafe: the object cannot be collected while the other pointer exists. - - // I now point at other's target - setPointer(other.pointer); - - return *this; - } - - WeakReferenceCountedPointer& operator=(const ReferenceCountedPointer& other) { - - // Threadsafe: the object cannot be collected while the other pointer exists. - - // I now point at other's target - setPointer(other.pointer()); - - return *this; - } - - bool operator==(const WeakReferenceCountedPointer& other) const { - return pointer == other.pointer; - } - - bool operator!=(const WeakReferenceCountedPointer& other) const { - return pointer != other.pointer; - } - - bool operator < (const WeakReferenceCountedPointer& y) const { - return (pointer < y.pointer); - } - - bool operator > (const WeakReferenceCountedPointer& y) const { - return (pointer > y.pointer); - } - - bool operator <= (const WeakReferenceCountedPointer& y) const { - return (pointer <= y.pointer); - } - - bool operator >= (const ReferenceCountedPointer& y) const { - return (pointer >= y.pointer); - } - -protected: - - /** Invoked by the destructor on ReferenceCountedPointer. */ - virtual void objectCollected() { - debugAssertM(pointer != NULL, - "Removed a weak pointer twice."); - pointer = NULL; - } - -}; - -} // namespace - -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/RegistryUtil.h b/externals/g3dlite/G3D.lib/include/G3D/RegistryUtil.h deleted file mode 100644 index 4b47be5f4bd..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/RegistryUtil.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - @file RegistryUtil.h - - @created 2006-04-06 - @edited 2006-04-06 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. -*/ - -#ifndef G3D_REGISTRYUTIL_H -#define G3D_REGISTRYUTIL_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" - -// This file is only used on Windows -#ifdef G3D_WIN32 - -#include - -namespace G3D { - -/** - Provides generalized Windows registry querying. - - All key names are one string in the format: - "[base key]\[sub-keys]" - - A value must now be provided for every query. - An empty value string will use the (Default) value. - - [base key] can be any of the following: - HKEY_CLASSES_ROOT - HKEY_CURRENT_CONFIG - HKEY_CURRENT_USER - HKEY_LOCAL_MACHINE - HKEY_PERFORMANCE_DATA - HKEY_PERFORMANCE_NLSTEXT - HKEY_PERFORMANCE_TEXT - HKEY_USERS - - valueExists() should be used to validate a key+value before reading or writing - to ensure that a debug assert or false return is for a different error during - reads and writes. - - All read and write calls will assert when a key will not open for reasons other - that it does not exist. All read and write calls will assert when the value cannot - be read or written for any reason. -*/ -class RegistryUtil { - -public: - /** returns true if the key exists and the current user has permission to read */ - static bool keyExists(const std::string& key); - - /** returns true if the key exists and the current user has permission to read */ - static bool valueExists(const std::string& key, const std::string& value); - - /** returns false if the key could not be read for any reason. */ - static bool readInt32(const std::string& key, const std::string& value, int32& data); - - /** - Reads an arbitrary amount of data from a binary registry key. - returns false if the key could not be read for any reason. - - @beta - @param data pointer to the output buffer of sufficient size. Pass NULL as data in order to have available data size returned in dataSize. - @param dataSize size of the output buffer. When NULL is passed for data, contains the size of available data on successful return. - */ - static bool readBytes(const std::string& key, const std::string& value, uint8* data, uint32& dataSize); - - /** returns false if the key could not be read for any reason. */ - static bool readString(const std::string& key, const std::string& value, std::string& data); - - /** returns false if the key could not be written for any reason. */ - static bool writeInt32(const std::string& key, const std::string& value, int32 data); - - /** - Writes an arbitrary amount of data to a binary registry key. - returns false if the key could not be written for any reason. - - @param data pointer to the input buffer - @param dataSize size of the input buffer that should be written - */ - static bool writeBytes(const std::string& key, const std::string& value, const uint8* data, uint32 dataSize); - - /** returns false if the key could not be written for any reason. */ - static bool writeString(const std::string& key, const std::string& value, const std::string& data); - -}; - -} // namespace G3D - -#endif // G3D_WIN32 - -#endif // G3D_REGISTRYTUIL_H diff --git a/externals/g3dlite/G3D.lib/include/G3D/Set.h b/externals/g3dlite/G3D.lib/include/G3D/Set.h deleted file mode 100644 index 629d802cdd4..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Set.h +++ /dev/null @@ -1,160 +0,0 @@ -/** - @file Set.h - - Hash set - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2001-12-09 - @edited 2006-02-20 - */ - -#ifndef G3D_SET_H -#define G3D_SET_H - -#include "G3D/platform.h" -#include "G3D/Table.h" -#include -#include - -namespace G3D { - -/** - An unordered data structure that has at most one of each element. - Provides O(1) time insert, remove, and member test (contains). - - Set uses G3D::Table internally, which means that the template type T - must define a hashCode and operator== function. See G3D::Table for - a discussion of these functions. - */ -// There is not copy constructor or assignment operator defined because -// the default ones are correct for Set. -template -class Set { - - /** - If an object is a member, it is contained in - this table. - */ - Table memberTable; - -public: - - virtual ~Set() {} - - int size() const { - return (int)memberTable.size(); - } - - bool contains(const T& member) const { - return memberTable.containsKey(member); - } - - /** - Inserts into the table if not already present. - */ - void insert(const T& member) { - memberTable.set(member, true); - } - - /** - It is an error to remove members that are not already - present. - */ - void remove(const T& member) { - memberTable.remove(member); - } - - Array getMembers() const { - return memberTable.getKeys(); - } - - void getMembers(Array& keyArray) const { - memberTable.getKeys(keyArray); - } - - void clear() { - memberTable.clear(); - } - - void deleteAll() { - getMembers().deleteAll(); - clear(); - } - - /** - C++ STL style iterator variable. See begin(). - */ - class Iterator { - private: - friend class Set; - - // Note: this is a Table iterator, we are currently defining - // Set iterator - typename Table::Iterator it; - - Iterator(const typename Table::Iterator& it) : it(it) {} - - public: - inline bool operator!=(const Iterator& other) const { - return !(*this == other); - } - - bool operator==(const Iterator& other) const { - return it == other.it; - } - - /** - Pre increment. - */ - Iterator& operator++() { - ++it; - return *this; - } - - /** - Post increment (slower than preincrement). - */ - Iterator operator++(int) { - Iterator old = *this; - ++(*this); - return old; - } - - const T& operator*() const { - return it->key; - } - - T* operator->() const { - return &(it->key); - } - - operator T*() const { - return &(it->key); - } - }; - - - /** - C++ STL style iterator method. Returns the first member. - Use preincrement (++entry) to get to the next element. - Do not modify the set while iterating. - */ - Iterator begin() const { - return Iterator(memberTable.begin()); - } - - - /** - C++ STL style iterator method. Returns one after the last iterator - element. - */ - const Iterator end() const { - return Iterator(memberTable.end()); - } -}; - -} - -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/Sphere.h b/externals/g3dlite/G3D.lib/include/G3D/Sphere.h deleted file mode 100644 index 7d4c412185d..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Sphere.h +++ /dev/null @@ -1,143 +0,0 @@ -/** - @file Sphere.h - - Sphere class - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2001-06-02 - @edited 2008-10-07 - */ - -#ifndef G3D_SPHERE_H -#define G3D_SPHERE_H - -#include "G3D/platform.h" -#include "G3D/Vector3.h" -#include "G3D/Array.h" -#include "G3D/Sphere.h" - -namespace G3D { - -/** - Sphere. - */ -class Sphere { -private: - - static int32 dummy; - -public: - Vector3 center; - float radius; - - Sphere() { - center = Vector3::zero(); - radius = 0; - } - - Sphere(class BinaryInput& b); - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); - - Sphere( - const Vector3& center, - float radius) { - - this->center = center; - this->radius = radius; - } - - virtual ~Sphere() {} - - bool operator==(const Sphere& other) const { - return (center == other.center) && (radius == other.radius); - } - - bool operator!=(const Sphere& other) const { - return !((center == other.center) && (radius == other.radius)); - } - - /** - Returns true if point is less than or equal to radius away from - the center. - */ - bool contains(const Vector3& point) const; - - /** - @deprecated Use culledBy(Array&) - */ - bool culledBy( - const class Plane* plane, - int numPlanes, - int32& cullingPlaneIndex, - const uint32 testMask, - uint32& childMask) const; - - /** - @deprecated Use culledBy(Array&) - */ - bool culledBy( - const class Plane* plane, - int numPlanes, - int32& cullingPlaneIndex = dummy, - const uint32 testMask = 0xFFFFFFFF) const; - - /** - See AABox::culledBy - */ - bool culledBy( - const Array& plane, - int32& cullingPlaneIndex, - const uint32 testMask, - uint32& childMask) const; - - /** - Conservative culling test that does not produce a mask for children. - */ - bool culledBy( - const Array& plane, - int32& cullingPlaneIndex = dummy, - const uint32 testMask = 0xFFFFFFFF) const; - - virtual std::string toString() const; - - float volume() const; - - float area() const; - - /** - Uniformly distributed on the surface. - */ - Vector3 randomSurfacePoint() const; - - /** - Uniformly distributed on the interior (includes surface) - */ - Vector3 randomInteriorPoint() const; - - void getBounds(class AABox& out) const; - - bool intersects(const Sphere& other) const; - - /** Translates the sphere */ - Sphere operator+(const Vector3& v) const { - return Sphere(center + v, radius); - } - - /** Translates the sphere */ - Sphere operator-(const Vector3& v) const { - return Sphere(center - v, radius); - } -}; - -} - -template <> struct HashTrait { - static size_t hashCode(const G3D::Sphere& key) { - return static_cast(key.center.hashCode() + (key.radius * 13)); - } -}; - - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Spline.h b/externals/g3dlite/G3D.lib/include/G3D/Spline.h deleted file mode 100644 index af9b08230b8..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Spline.h +++ /dev/null @@ -1,367 +0,0 @@ -/** - @file Spline.h - - @author Morgan McGuire, morgan@cs.williams.edu - */ - -#ifndef G3D_SPLINE_H -#define G3D_SPLINE_H - -#include "G3D/platform.h" -#include "G3D/Array.h" -#include "G3D/g3dmath.h" -#include "G3D/Matrix4.h" -#include "G3D/Vector4.h" - -namespace G3D { - -/** Common implementation code for all G3D::Spline template parameters */ -class SplineBase { -public: - - /** Times at which control points occur. Must have the same - number of elements as Spline::control. */ - Array time; - - /** If cyclic, then the control points will be assumed to wrap around. - If not cyclic, then the tangents at the ends of the spline - point to the final control points.*/ - bool cyclic; - - /** For a cyclic spline, this is the time elapsed between the last - control point and the first. If less than or equal to zero this is - assumed to be: - - (time[0] - time[1] + . - time[time.size() - 1] - time[time.size() - 2]) / 2. - */ - float finalInterval; - - SplineBase() : cyclic(true), finalInterval(-1) {} - - virtual ~SplineBase() {} - - /** See specification for Spline::finalInterval; this handles the - non-positive case. Returns 0 if not cyclic. */ - float getFinalInterval() const; - - /** Returns the amount of time covered by this spline in one - period. For a cyclic spline, this contains the final - interval.*/ - float duration() const; - - /** Computes the derivative spline basis from the control point version. */ - static Matrix4 computeBasis(); - -protected: - - /** Assumes that t0 <= s < tn. called by computeIndex. */ - void computeIndexInBounds(float s, int& i, float& u) const; - -public: - - /** - Given a time @a s, finds @a i and 0 <= @a u < 1 such that - @s = time[@a i] * @a u + time[@a i + 1] * (1 - @a u). Note that - @i may be outside the bounds of the time and control arrays; - use getControl to handle wraparound and extrapolation issues. - - This function takes expected O(1) time for control points with - uniform time sampled control points or for uniformly - distributed random time samples, but may take O( log time.size() ) time - in the worst case. - - Called from evaluate(). - */ - void computeIndex(float s, int& i, float& u) const; -}; - - -/** - Smooth parameteric curve implemented using a piecewise 3rd-order - Catmull-Rom spline curve. The spline is considered infinite and may - either continue linearly from the specified control points or cycle - through them. Control points are spaced uniformly in time at unit - intervals by default, but irregular spacing may be explicitly - specified. - - The dimension of the spline can be set by varying the Control - template parameter. For a 1D function, use Spline. For a - curve in the plane, Spline. Note that any template - parameter that supports operator+(Control) and operator*(float) can - be used; you can make splines out of G3D::Vector4, G3D::Matrix3, or - your own classes. - - To provide shortest-path interpolation, subclass G3D::Spline and - override ensureShortestPath(). To provide normalization of - interpolated points (e.g., projecting Quats onto the unit - hypersphere) override correct(). - - See Real Time Rendering, 2nd edition, ch 12 for a general discussion - of splines and their properties. - - @sa G3D::UprightSpline, G3D::QuatSpline - */ -template -class Spline : public SplineBase { -protected: - /** The additive identity control point. */ - Control zero; - -public: - - /** Control points. Must have the same number of elements as - Spline::time.*/ - Array control; - - Spline() { - static Control x; - // Hide the fact from C++ that we are using an - // uninitialized variable here by pointer arithmetic. - // This is ok because any type that is a legal control - // point also supports multiplication by float. - zero = *(&x) * 0.0f; - } - - /** Appends a control point at a specific time that must be - greater than that of the previous point. */ - void append(float t, const Control& c) { - debugAssertM((time.size() == 0) || (t > time.last()), - "Control points must have monotonically increasing times."); - time.append(t); - control.append(c); - debugAssert(control.size() == time.size()); - } - - - /** Appends control point spaced in time based on the previous - control point, or spaced at unit intervals if this is the - first control point. */ - void append(const Control& c) { - switch (time.size()) { - case 0: - append(0, c); - break; - - case 1: - if (time[0] == 0) { - append(1, c); - } else { - append(time[0], c); - } - break; - - default: - append(2 * time[time.size() - 1] - time[time.size() - 2], c); - } - debugAssert(control.size() == time.size()); - } - - /** Erases all control points and times, but retains the state of - cyclic and finalInterval. - */ - void clear() { - control.clear(); - time.clear(); - } - - - /** Number of control points */ - int size() const { - debugAssert(time.size() == control.size()); - return control.size(); - } - - - /** Returns the requested control point and time sample based on - array index. If the array index is out of bounds, wraps (for - a cyclic spline) or linearly extrapolates (for a non-cyclic - spline), assuming time intervals follow the first or last - sample recorded. - - Calls correct() on the control point if it was extrapolated. - - Returns 0 if there are no control points. - - @sa Spline::control and Spline::time for the underlying - control point array; Spline::computeIndex to find the index - given a time. - */ - void getControl(int i, float& t, Control& c) const { - int N = control.size(); - if (N == 0) { - c = zero; - t = 0; - } else if (cyclic) { - c = control[iWrap(i, N)]; - - if (i < 0) { - // Wrapped around bottom - - // Number of times we wrapped around the cyclic array - int wraps = (N + 1 - i) / N; - int j = (i + wraps * N) % N; - t = time[j] - wraps * duration(); - - } else if (i < N) { - - t = time[i]; - - } else { - // Wrapped around top - - // Number of times we wrapped around the cyclic array - int wraps = i / N; - int j = i % N; - t = time[j] + wraps * duration(); - } - - } else if (i < 0) { - // Are there enough points to extrapolate? - if (N >= 2) { - // Step away from control point 0 - float dt = time[1] - time[0]; - - // Extrapolate (note; i is negative) - c = control[1] * float(i) + control[0] * float(1 - i); - correct(c); - t = dt * i + time[0]; - - } else { - // Just clamp - c = control[0]; - - // Only 1 time; assume 1s intervals - t = time[0] + i; - } - - } else if (i >= N) { - if (N >= 2) { - float dt = time[N - 1] - time[N - 2]; - - // Extrapolate - c = control[N - 1] * float(i - N + 2) + control[N - 2] * -float(i - N + 1); - correct(c); - t = time[N - 1] + dt * (i - N + 1); - - } else { - // Return the last, clamping - c = control.last(); - // Only 1 time; assume 1s intervals - t = time[0] + i; - } - } else { - // In bounds - c = control[i]; - t = time[i]; - } - } - -protected: - - /** Returns a series of N control points and times, fixing - boundary issues. The indices may be assumed to be treated - cyclically. */ - void getControls(int i, float* T, Control* A, int N) const { - for (int j = 0; j < N; ++j) { - getControl(i + j, T[j], A[j]); - } - ensureShortestPath(A, N); - } - - /** - Mutates the array of N control points. It is useful to override this - method by one that wraps the values if they are angles or quaternions - for which "shortest path" interpolation is significant. - */ - virtual void ensureShortestPath(Control* A, int N) const {} - - /** Normalize or otherwise adjust this interpolated Control. */ - virtual void correct(Control& A) const {} - -public: - - - /** - Return the position at time s. The spline is defined outside - of the time samples by extrapolation or cycling. - */ - Control evaluate(float s) const { - debugAssertM(control.size() == time.size(), "Corrupt spline: wrong number of control points."); - - /* - @cite http://www.gamedev.net/reference/articles/article1497.asp - Derivation of basis matrix follows. - - Given control points with positions p[i] at times t[i], 0 <= i <= 3, find the position - at time t[1] <= s <= t[2]. - - Let u = s - t[0] - Let U = [u^0 u^1 u^2 u^3] = [1 u u^2 u^3] - Let dt0 = t[0] - t[-1] - Let dt1 = t[1] - t[0] - Let dt2 = t[2] - t[1] - */ - - // Index of the first control point (i.e., the u = 0 point) - int i = 0; - // Fractional part of the time - float u = 0; - - computeIndex(s, i, u); - - Control p[4]; - float t[4]; - getControls(i - 1, t, p, 4); - float dt0 = t[1] - t[0]; - float dt1 = t[2] - t[1]; - float dt2 = t[3] - t[2]; - - static const Matrix4 basis = computeBasis(); - - // Powers of u - Vector4 uvec((float)(u*u*u), (float)(u*u), (float)u, 1.0f); - - // Compute the weights on each of the control points. - const Vector4& weights = uvec * basis; - - // Compute the weighted sum of the neighboring control points. - Control sum; - - const Control& p0 = p[0]; - const Control& p1 = p[1]; - const Control& p2 = p[2]; - const Control& p3 = p[3]; - - const Control& dp0 = p1 + (p0*-1.0f); - const Control& dp1 = p2 + (p1*-1.0f); - const Control& dp2 = p3 + (p2*-1.0f); - - // The factor of 1/2 from averaging two time intervals is - // already factored into the basis - - // tan1 = (dp0 / dt0 + dp1 / dt1) * ((dt0 + dt1) * 0.5); - // The last term normalizes for unequal time intervals - float x = (dt0 + dt1) * 0.5f; - float n0 = x / dt0; - float n1 = x / dt1; - float n2 = x / dt2; - const Control& dp1n1 = dp1 * n1; - const Control& tan1 = dp0 * n0 + dp1n1; - const Control& tan2 = dp1n1 + dp2 * n2; - - sum = - tan1 * weights[0]+ - p1 * weights[1] + - p2 * weights[2] + - tan2 * weights[3]; - - - correct(sum); - return sum; - } -}; - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Stopwatch.h b/externals/g3dlite/G3D.lib/include/G3D/Stopwatch.h deleted file mode 100644 index aee3b0f69c9..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Stopwatch.h +++ /dev/null @@ -1,108 +0,0 @@ -/** - @file Stopwatch.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2005-10-05 - @edited 2005-10-05 - - Copyright 2000-2003, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_STOPWATCH_H -#define G3D_STOPWATCH_H - -#include "G3D/platform.h" -#include "G3D/Queue.h" -#include "G3D/G3DGameUnits.h" -#include "G3D/g3dmath.h" - -namespace G3D { - -/** - Utility class for profiling duration and frame rates. - */ -class Stopwatch { -private: - /** True between tick and tock */ - bool inBetween; - - /** The initial cycle count. */ - uint64 cycleStart; - - /** The time at which tick was called. */ - RealTime timeStart; - - /** The time at which the previous tock was called, -1 if never. */ - RealTime lastTockTime; - - RealTime lastDuration; - int64 lastCycleCount; - - /** Frames per second. */ - double m_fps; - - /** Weighted fps */ - double emwaFPS; - double m_smoothFPS; - - /** Weighted duration */ - RealTime emwaDuration; - - /** The overhead for calling into the class. */ - int64 cycleOverhead; - - /** Called from the constructor. */ - void computeOverhead(); - -public: - - Stopwatch(); - - /** Returns the number of times that tick was called per wall-clock second; - e.g. frames-per-second. */ - double FPS() const { - return m_fps; - } - - /** Amount of time between the most recent tick and tock calls. 0 if tick has - never been called. */ - RealTime elapsedTime() const { - return lastDuration; - } - - /** Time-smoothed value that is stable to the nearest 1%. - This is useful if you are displaying elapsed time in real-time - and want a stable number.*/ - RealTime smoothElapsedTime() const { - return emwaDuration; - } - - /** Time-smoothed value of fps that is stable to the nearest integer for fps > 10 and - to the first decimal place for fps <= 10. - This is useful if you - are displaying the frame rate in real-time and want a stable (readable) number.*/ - double smoothFPS() const { - return m_smoothFPS; - } - - /** The elapsed cycle time between tick and tock. An attempt is made to factor out all - tick/tock overhead, so that back-to-back calls should return zero. - Unreliable on non-x86 platforms.*/ - uint64 elapsedCycles() const { - return lastCycleCount; - } - - /** Call at the beginning of the period that you want timed. */ - void tick(); - - /** Call at the end of the period that you want timed. */ - void tock(); -}; - - -} - -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/System.h b/externals/g3dlite/G3D.lib/include/G3D/System.h deleted file mode 100644 index 3755dc5e36f..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/System.h +++ /dev/null @@ -1,390 +0,0 @@ -/** - @file System.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @cite Rob Wyatt http://www.gamasutra.com/features/wyatts_world/19990709/processor_detection_01.htm - @cite Benjamin Jurke http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-ProcessorDetectionClass&forum=cotd&id=-1 - @cite Michael Herf http://www.stereopsis.com/memcpy.html - - @created 2003-01-25 - @edited 2008-10-14 - */ - -#ifndef G3D_SYSTEM_H -#define G3D_SYSTEM_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/G3DGameUnits.h" -#include "G3D/BinaryFormat.h" -#include - -#ifdef G3D_OSX -# include -#endif - -namespace G3D { - -/** - Routine used by the demos to find the data. Searches in - ../data, ../../data, etc. up to 5 levels back. Checks - common locations like c:\libraries\g3d-\data - and some hard-coded paths on the Brown University file - system. - */ -std::string demoFindData(bool errorIfNotFound = true); - -/** G3D, SDL, and IJG libraries require license documentation - to be distributed with your program. This generates the - string that must appear in your documentation. - Your program can be commercial, closed-source under - any license you want.*/ -std::string license(); - -/** -The order in which the bytes of an integer are stored on a machine. Intel/AMD chips tend to be G3D_LITTLE_ENDIAN, Mac PPC's and Suns are G3D_BIG_ENDIAN. However, this is primarily used to specify the byte order of file formats, which are fixed. -*/ -enum G3DEndian { - G3D_BIG_ENDIAN, G3D_LITTLE_ENDIAN -}; - -/** - OS and processor abstraction. The first time any method is called the processor - will be analyzed. Future calls are then fast. - - Timing function overview: - System::getCycleCount - - actual cycle count - - System::getTick - - High-resolution time in seconds since program started - - System::getLocalTime - - High-resolution time in seconds since Jan 1, 1970 - (because it is stored in a double, this may be less - accurate than getTick) - - */ -class System { -public: - - /** Called automatically by the other System routines.*/ - static void init(); - - /** */ - static bool hasMMX(); - - /** */ - static bool hasCPUID(); - - /** */ - static bool hasSSE(); - - /** */ - static bool hasSSE2(); - - /** */ - static bool hasSSE3(); - - /** */ - static bool has3DNow(); - - - /** */ - static bool hasRDTSC(); - - static const std::string& cpuVendor(); - - /** e.g. "Windows", "GNU/Linux" */ - static const std::string& operatingSystem(); - - /** */ - static const std::string& cpuArchitecture(); - - /** - Returns the endianness of this machine. - */ - static G3DEndian machineEndian(); - - /** - Returns the current date as a string in the form YYYY-MM-DD - */ - static std::string currentDateString(); - - /** - Guarantees that the start of the array is aligned to the - specified number of bytes. - */ - static void* alignedMalloc(size_t bytes, size_t alignment); - - /** - Uses pooled storage to optimize small allocations (1 byte to 5 kilobytes). - Can be 10x to 100x faster than calling ::malloc or new. - - The result must be freed with free. - - Threadsafe on Win32. - - @sa calloc realloc OutOfMemoryCallback free - */ - static void* malloc(size_t bytes); - - static void* calloc(size_t n, size_t x); - - /** - @param size Size of memory that the system was trying to allocate - @param recoverable If true, the system will attempt to allocate again - if the callback returns true. If false, malloc is going to return - NULL and this invocation is just to notify the application. - @return Return true to force malloc to attempt allocation again if the - error was recoverable. - */ - typedef bool (*OutOfMemoryCallback)(size_t size, bool recoverable); - - /** - When System::malloc fails to allocate memory because the system is - out of memory, it invokes this handler (if it is not NULL). - The argument to the callback is the amount of memory that malloc - was trying to allocate when it ran out. If the callback returns - true, System::malloc will attempt to allocate the memory again. - If the callback returns false, then System::malloc will return NULL. - - You can use outOfMemoryCallback to free data structures or to - register the failure. - */ - static OutOfMemoryCallback outOfMemoryCallback; - - /** - Version of realloc that works with System::malloc. - */ - static void* realloc(void* block, size_t bytes); - - /** Returns a string describing how well System::malloc is using its internal pooled storage. - "heap" memory was slow to allocate; the other data sizes are comparatively fast.*/ - static std::string mallocPerformance(); - static void resetMallocPerformanceCounters(); - - /** - Returns a string describing the current usage of the buffer pools used for - optimizing System::malloc. - */ - static std::string mallocStatus(); - - /** - Free data allocated with System::malloc. - - Threadsafe on Win32. - */ - static void free(void* p); - - /** - Frees memory allocated with alignedMalloc. - */ - static void alignedFree(void* ptr); - - /** An implementation of memcpy that may be up to 2x as fast as the C library - one on some processors. Guaranteed to have the same behavior as memcpy - in all cases. */ - static void memcpy(void* dst, const void* src, size_t numBytes); - - /** An implementation of memset that may be up to 2x as fast as the C library - one on some processors. Guaranteed to have the same behavior as memset - in all cases. */ - static void memset(void* dst, uint8 value, size_t numBytes); - - /** - Returns the fully qualified filename for the currently running executable. - - This is more reliable than arg[0], which may be intentionally set - to an incorrect value by a calling program, relative to a now - non-current directory, or obfuscated by sym-links. - - @cite Linux version written by Nicolai Haehnle , http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-getexename&forum=cotd&id=-1 - */ - static std::string currentProgramFilename(); - - /** Name of this program. Note that you can mutate this string to set your app name explicitly.*/ - static std::string& appName(); - - /** G3D Version string */ - static const std::string& version(); - - /** - Either Debug or Release, depending on whether _DEBUG was defined at compile-time for the library. - */ - static const std::string& build(); - - /** - Causes the current thread to yield for the specified duration - and consume almost no CPU. - The sleep will be extremely precise; it uses System::time() - to calibrate the exact yeild time. - */ - static void sleep(RealTime t); - - /** - Clears the console. - Console programs only. - */ - static void consoleClearScreen(); - - /** - Returns true if a key is waiting. - Console programs only. - */ - static bool consoleKeyPressed(); - - /** - Blocks until a key is read (use consoleKeyPressed to determine if - a key is waiting to be read) then returns the character code for - that key. - */ - static int consoleReadKey(); - - /** - The actual time (measured in seconds since - Jan 1 1970 midnight). - - Adjusted for local timezone and daylight savings - time. This is as accurate and fast as getCycleCount(). - */ - static RealTime time(); - - /** - To count the number of cycles a given operation takes: - -
-     unsigned long count;
-     System::beginCycleCount(count);
-     ...
-     System::endCycleCount(count);
-     // count now contains the cycle count for the intervening operation.
-
-     */
-    static void beginCycleCount(uint64& cycleCount);
-    static void endCycleCount(uint64& cycleCount);
-
-    static uint64 getCycleCount();
-
-    /** Set an environment variable for the current process */
-    static void setEnv(const std::string& name, const std::string& value);
-	
-    /** Get an environment variable for the current process.  Returns NULL if the variable doesn't exist. */
-    static const char* getEnv(const std::string& name);
-
-    /**
-     Prints a human-readable description of this machine
-     to the text output stream.  Either argument may be NULL.
-     */
-    static void describeSystem(
-        class TextOutput& t);
-
-    static void describeSystem(
-        std::string&        s);
-
-    /** Returns the speed of processor 0 in MHz. 
-        Always returns 0 on linux.*/
-    static int cpuSpeedMHz();
-
-
-    /** On Win32, returns the clipboard text contents.  Does nothing on other
-       platforms (yet) */
-    static std::string getClipboardText();
-
-    /** Copies the text to the clipboard on Win32. */
-    static void setClipboardText(const std::string& s);
-
-    /**
-     Tries to locate the resource by looking in related directories.
-     If found, returns the full path to the resource, otherwise
-     returns the empty string.
-     */    
-    static std::string findDataFile(const std::string& full, bool errorIfNotFound = true);
-
-    /**
-        Sets the path that the application is using as its data directory.
-        Used by findDataDir as an initial search location.  GApp sets this
-        upon constrution.
-    */
-    static void setAppDataDir(const std::string& path);
-
-private:
-    /**
-	 (CKO) Note: Not sure why these are specifically needed
-	 for OS X. I made them private though.
-	*/
-#   ifdef G3D_OSX
-    static long m_OSXCPUSpeed; //In Cycles/Second
-    static double m_secondsPerNS;
-#   endif
-};
-
-
-#ifdef _MSC_VER
-    inline uint64 System::getCycleCount() {
-        uint32 timehi, timelo;
-
-        // Use the assembly instruction rdtsc, which gets the current
-        // cycle count (since the process started) and puts it in edx:eax.
-        __asm
-            {
-                rdtsc;
-                mov timehi, edx;
-                mov timelo, eax;
-            }
-
-        return ((uint64)timehi << 32) + (uint64)timelo;
-    }
-
-#elif defined(G3D_LINUX)
-
-    inline uint64 System::getCycleCount() {
-        uint32 timehi, timelo;
-
-        __asm__ __volatile__ (
-            "rdtsc            "
-            : "=a" (timelo),
-              "=d" (timehi)
-            : );
-
-        return ((uint64)timehi << 32) + (uint64)timelo;
-    }
-
-#elif defined(G3D_OSX)
-
-    inline uint64 System::getCycleCount() {
-		//Note:  To put off extra processing until the end, this does not 
-		//return the actual clock cycle count.  It is a bus cycle count.
-		//When endCycleCount() is called, it converts the two into a difference
-		//of clock cycles
-		
-        return (uint64) UnsignedWideToUInt64(UpTime());
-		//return (uint64) mach_absolute_time();
-    }
-
-#endif
-
-inline void System::beginCycleCount(uint64& cycleCount) {
-    cycleCount = getCycleCount();
-}
-
-
-inline void System::endCycleCount(uint64& cycleCount) {
-	#ifndef G3D_OSX
-		cycleCount = getCycleCount() - cycleCount;
-	#else
-		AbsoluteTime end = UpTime();
-		init();
-		Nanoseconds diffNS = 
-            AbsoluteDeltaToNanoseconds(end, UInt64ToUnsignedWide(cycleCount));
-		cycleCount = 
-            (uint64) ((double) (System::m_OSXCPUSpeed) * 
-                      (double) UnsignedWideToUInt64(diffNS) * m_secondsPerNS);
-	#endif
-}
-
-
-} // namespace
-
-#endif
diff --git a/externals/g3dlite/G3D.lib/include/G3D/Table.h b/externals/g3dlite/G3D.lib/include/G3D/Table.h
deleted file mode 100644
index 9ccd4f5c101..00000000000
--- a/externals/g3dlite/G3D.lib/include/G3D/Table.h
+++ /dev/null
@@ -1,770 +0,0 @@
-/**
-  @file Table.h
-
-  Templated hash table class.
-
-  @maintainer Morgan McGuire, morgan@cs.williams.edu
-  @created 2001-04-22
-  @edited  2008-07-01
-  Copyright 2000-2008, Morgan McGuire.
-  All rights reserved.
- */
-
-#ifndef G3D_TABLE_H
-#define G3D_TABLE_H
-
-#include 
-#include 
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include "G3D/debug.h"
-#include "G3D/System.h"
-#include "G3D/g3dmath.h"
-#include "G3D/EqualsTrait.h"
-#include "G3D/HashTrait.h"
-
-#ifdef _MSC_VER
-#   pragma warning (push)
-    // Debug name too long warning
-#   pragma warning (disable : 4786)
-#endif
-
-namespace G3D {
-
-/**
- An unordered data structure mapping keys to values.
-
- Key must be a pointer, an int, a std::string or provide overloads for: 
-
-  
-    template<> struct HashTrait {
-        static size_t hashCode(const Key& key) { return reinterpret_cast( ... ); }
-    }; 
-  
- - and one of - -
-    template<> struct EqualsTrait{
-         static bool equals(const Key& a, const Key& b) { return ... ; }
-    };
-
-
-    bool operator==(const Key&, const Key&);
-  
- - G3D pre-defines HashTrait specializations for common types (like int and std::string). - If you use a Table with a different type you must write those functions yourself. For example, - an enum would use: - -
-    template<> struct HashTrait {
-        static size_t equals(const MyEnum& key) const { return reinterpret_cast( key ); }
-    };
-  
- - And rely on the default enum operator==. - - - Periodically check that debugGetLoad() is low (> 0.1). When it gets near - 1.0 your hash function is badly designed and maps too many inputs to - the same output. - */ -template, class EqualsFunc = EqualsTrait > -class Table { -public: - - /** - The pairs returned by iterator. - */ - class Entry { - public: - Key key; - Value value; - Entry() {} - Entry(const Key& k, const Value& v) : key(k), value(v) {} - }; - -private: - - typedef Table ThisType; - - /** - Linked list nodes used internally by HashTable. - */ - class Node { - public: - Entry entry; - size_t hashCode; - Node* next; - - /** Provide pooled allocation for speed. */ - inline void* operator new (size_t size) { - return System::malloc(size); - } - - inline void operator delete (void* p) { - System::free(p); - } - - Node(const Key& k, const Value& v, size_t h, Node* n) - : entry(k, v), hashCode(h), next(n) { - } - - /** - Clones a whole chain; - */ - Node* clone() { - return new Node(this->entry.key, this->entry.value, hashCode, (next == NULL) ? NULL : next->clone()); - } - }; - - void checkIntegrity() const { -# ifdef G3D_DEBUG - debugAssert(bucket == NULL || isValidHeapPointer(bucket)); - for (size_t b = 0; b < numBuckets; ++b) { - Node* node = bucket[b]; - debugAssert(node == NULL || isValidHeapPointer(node)); - while (node != NULL) { - debugAssert(node == NULL || isValidHeapPointer(node)); - node = node->next; - } - } -# endif - } - - /** - Number of elements in the table. - */ - size_t _size; - - /** - Array of Node*. - We don't use Array because Table is lower level. - Some elements may be NULL. - */ - Node** bucket; - - /** - Length of the bucket array. - */ - size_t numBuckets; - - /** - Re-hashes for a larger bucket size. - */ - void resize(size_t newSize) { - - // Hang onto the old bucket array - Node** oldBucket = bucket; - - // Allocate a new bucket array with the new size - bucket = (Node**)System::calloc(sizeof(Node*), newSize); - debugAssertM(bucket != NULL, "System::calloc returned NULL. Out of memory."); - // Move each node to its new hash location - for (size_t b = 0; b < numBuckets; ++b) { - Node* node = oldBucket[b]; - - // There is a linked list of nodes at this bucket - while (node != NULL) { - // Hang onto the old next pointer - Node* nextNode = node->next; - - // Insert at the head of the list for bucket[i] - size_t i = node->hashCode % newSize; - node->next = bucket[i]; - bucket[i] = node; - - // Move on to the next node - node = nextNode; - } - - // Drop the old pointer for cleanliness when debugging - oldBucket[b] = NULL; - } - - // Delete the old storage - System::free(oldBucket); - this->numBuckets = newSize; - - checkIntegrity(); - } - - - void copyFrom(const ThisType& h) { - if (&h == this) { - return; - } - - debugAssert(bucket == NULL); - _size = h._size; - numBuckets = h.numBuckets; - bucket = (Node**)System::calloc(sizeof(Node*), numBuckets); - - for (size_t b = 0; b < numBuckets; b++) { - if (h.bucket[b] != NULL) { - bucket[b] = h.bucket[b]->clone(); - } - } - - checkIntegrity(); - } - - /** - Frees the heap structures for the nodes. - */ - void freeMemory() { - checkIntegrity(); - - for (size_t b = 0; b < numBuckets; b++) { - Node* node = bucket[b]; - while (node != NULL) { - Node* next = node->next; - delete node; - node = next; - } - bucket[b] = NULL; - } - System::free(bucket); - bucket = NULL; - numBuckets = 0; - _size = 0; - } - - -public: - - /** - Creates an empty hash table. This causes some heap allocation to occur. - */ - Table() : bucket(NULL) { - numBuckets = 10; - _size = 0; - bucket = (Node**)System::calloc(sizeof(Node*), numBuckets); - checkIntegrity(); - } - - /** - Recommends that the table resize to anticipate at least this number of elements. - */ - void setSizeHint(size_t n) { - size_t s = n * 3; - if (s > numBuckets) { - resize(s); - } - } - - /** - Destroys all of the memory allocated by the table, but does not - call delete on keys or values if they are pointers. If you want to - deallocate things that the table points at, use getKeys() and Array::deleteAll() - to delete them. - */ - virtual ~Table() { - freeMemory(); - } - - Table(const ThisType& h) { - numBuckets = 0; - _size = 0; - bucket = NULL; - this->copyFrom(h); - checkIntegrity(); - } - - - Table& operator=(const ThisType& h) { - // No need to copy if the argument is this - if (this != &h) { - // Free the existing nodes - freeMemory(); - this->copyFrom(h); - checkIntegrity(); - } - return *this; - } - - /** - Returns the length of the deepest bucket. - */ - size_t debugGetDeepestBucketSize() const { - size_t deepest = 0; - - for (size_t b = 0; b < numBuckets; b++) { - size_t count = 0; - Node* node = bucket[b]; - while (node != NULL) { - node = node->next; - ++count; - } - - if (count > deepest) { - deepest = count; - } - } - - return deepest; - } - - /** - Returns the average size of non-empty buckets. - */ - float debugGetAverageBucketSize() const { - size_t num = 0; - size_t count = 0; - - for (size_t b = 0; b < numBuckets; b++) { - Node* node = bucket[b]; - if (node != NULL) { - ++num; - while (node != NULL) { - node = node->next; - ++count; - } - } - } - - return (float)((double)count / num); - } - - /** - A small load (close to zero) means the hash table is acting very - efficiently most of the time. A large load (close to 1) means - the hash table is acting poorly-- all operations will be very slow. - A large load will result from a bad hash function that maps too - many keys to the same code. - */ - double debugGetLoad() const { - return debugGetDeepestBucketSize() / (double)size(); - } - - /** - Returns the number of buckets. - */ - size_t debugGetNumBuckets() const { - return numBuckets; - } - - /** - C++ STL style iterator variable. See begin(). - */ - class Iterator { - private: - friend class Table; - - /** - Bucket index. - */ - size_t index; - - /** - Linked list node. - */ - Node* node; - ThisType* table; - size_t numBuckets; - Node** bucket; - bool isDone; - - /** - Creates the end iterator. - */ - Iterator(const ThisType* table) : table(const_cast(table)) { - isDone = true; - } - - Iterator(const ThisType* table, size_t numBuckets, Node** bucket) : - table(const_cast(table)), - numBuckets(numBuckets), - bucket(bucket) { - - if (numBuckets == 0) { - // Empty table - isDone = true; - return; - } - - index = 0; - node = bucket[index]; - isDone = false; - findNext(); - } - - /** - Finds the next element, setting isDone if one can't be found. - Looks at the current element first. - */ - void findNext() { - while (node == NULL) { - index++; - if (index >= numBuckets) { - isDone = true; - break; - } else { - node = bucket[index]; - } - } - } - - public: - inline bool operator!=(const Iterator& other) const { - return !(*this == other); - } - - bool operator==(const Iterator& other) const { - if (other.isDone || isDone) { - // Common case; check against isDone. - return (isDone == other.isDone) && (other.table == table); - } else { - return - (table == other.table) && - (node == other.node) && - (index == other.index); - } - } - - /** - Pre increment. - */ - Iterator& operator++() { - node = node->next; - findNext(); - return *this; - } - - /** - Post increment (slower than preincrement). - */ - Iterator operator++(int) { - Iterator old = *this; - ++(*this); - return old; - } - - const Entry& operator*() const { - return node->entry; - } - - Entry* operator->() const { - return &(node->entry); - } - - operator Entry*() const { - return &(node->entry); - } - - bool hasMore() const { - return ! isDone; - } - }; - - - /** - C++ STL style iterator method. Returns the first Entry, which - contains a key and value. Use preincrement (++entry) to get to - the next element. Do not modify the table while iterating. - */ - Iterator begin() const { - return Iterator(this, numBuckets, bucket); - } - - /** - C++ STL style iterator method. Returns one after the last iterator - element. - */ - const Iterator end() const { - return Iterator(this); - } - - /** - Removes all elements - */ - void clear() { - freeMemory(); - numBuckets = 10; - _size = 0; - bucket = (Node**)System::calloc(sizeof(Node*), numBuckets); - } - - - /** - Returns the number of keys. - */ - size_t size() const { - return _size; - } - - - /** - If you insert a pointer into the key or value of a table, you are - responsible for deallocating the object eventually. Inserting - key into a table is O(1), but may cause a potentially slow rehashing. - */ - void set(const Key& key, const Value& value) { - size_t code = HashFunc::hashCode(key); - size_t b = code % numBuckets; - - // Go to the bucket - Node* n = bucket[b]; - - // No bucket, so this must be the first - if (n == NULL) { - bucket[b] = new Node(key, value, code, NULL); - ++_size; - return; - } - - size_t bucketLength = 1; - - // Sometimes a bad hash code will cause all elements - // to collide. Detect this case and don't rehash when - // it occurs; nothing good will come from the rehashing. - bool allSameCode = true; - - // Try to find the node - do { - allSameCode = allSameCode && (code == n->hashCode); - - if ((code == n->hashCode) && EqualsFunc::equals(n->entry.key, key)) { - // Replace the existing node. - n->entry.value = value; - return; - } - - n = n->next; - ++bucketLength; - } while (n != NULL); - - const size_t maxBucketLength = 3; - // (Don't bother changing the size of the table if all entries - // have the same hashcode--they'll still collide) - if ((bucketLength > maxBucketLength) && - ! allSameCode && - (numBuckets < _size * 15)) { - - // This bucket was really large; rehash if all elements - // don't have the same hashcode the number of buckets is - // reasonable. - - // Back off the scale factor as the number of buckets gets - // large - float f = 3.0f; - if (numBuckets > 1000000) { - f = 1.5f; - } else if (numBuckets > 100000) { - f = 2.0f; - } - int newSize = iMax((int)(numBuckets * f) + 1, (int)(_size * f)); - resize(newSize); - } - - // Not found; insert at the head. - b = code % numBuckets; - bucket[b] = new Node(key, value, code, bucket[b]); - ++_size; - } - - /** - Removes an element from the table if it is present. - @return true if the element was found and removed, otherwise false - */ - bool remove(const Key& key) { - - size_t code = HashFunc::hashCode(key); - size_t b = code % numBuckets; - - // Go to the bucket - Node* n = bucket[b]; - - if (n == NULL) { - return false; - } - - Node* previous = NULL; - - // Try to find the node - do { - if ((code == n->hashCode) && EqualsFunc::equals(n->entry.key, key)) { - // This is the node; remove it - - // Replace the previous's next pointer - if (previous == NULL) { - bucket[b] = n->next; - } else { - previous->next = n->next; - } - - // Delete the node - delete n; - --_size; - return true; - } - - previous = n; - n = n->next; - } while (n != NULL); - - - return false; - //alwaysAssertM(false, "Tried to remove a key that was not in the table."); - } - - /** - Returns the value associated with key. - @deprecated Use get(key, val) or getPointer(key) - */ - Value& get(const Key& key) const { - - size_t code = HashFunc::hashCode(key); - size_t b = code % numBuckets; - - Node* node = bucket[b]; - - while (node != NULL) { - if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) { - return node->entry.value; - } - node = node->next; - } - - debugAssertM(false, "Key not found"); - // The next line is here just to make - // a compiler warning go away. - return node->entry.value; - } - - - /** Returns a pointer to the element if it exists, or NULL if it does not. - Note that if your value type is a pointer, the return value is - a pointer to a pointer. Do not remove the element while holding this - pointer. - - It is easy to accidentally mis-use this method. Consider making - a Table and using get(key, val) instead, which makes you manage - the memory for the values yourself and is less likely to result in - pointer errors. - */ - Value* getPointer(const Key& key) const { - size_t code = HashFunc::hashCode(key); - size_t b = code % numBuckets; - - Node* node = bucket[b]; - - while (node != NULL) { - if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) { - // found key - return &(node->entry.value); - } - node = node->next; - } - - // Failed to find key - return NULL; - } - - /** - If the key is present in the table, val is set to the associated value and returns true. - If the key is not present, returns false. - */ - bool get(const Key& key, Value& val) const { - Value* v = getPointer(key); - if (v != NULL) { - val = *v; - return true; - } else { - return false; - } - } - - /** - Returns true if key is in the table. - */ - bool containsKey(const Key& key) const { - size_t code = HashFunc::hashCode(key); - size_t b = code % numBuckets; - - Node* node = bucket[b]; - - while (node != NULL) { - if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) { - return true; - } - node = node->next; - } while (node != NULL); - - return false; - } - - - /** - Short syntax for get. - */ - inline Value& operator[](const Key &key) const { - return get(key); - } - - - /** - Returns an array of all of the keys in the table. - You can iterate over the keys to get the values. - @deprecated - */ - Array getKeys() const { - Array keyArray; - getKeys(keyArray); - return keyArray; - } - - void getKeys(Array& keyArray) const { - keyArray.resize(0, DONT_SHRINK_UNDERLYING_ARRAY); - for (size_t i = 0; i < numBuckets; i++) { - Node* node = bucket[i]; - while (node != NULL) { - keyArray.append(node->entry.key); - node = node->next; - } - } - } - - /** - Calls delete on all of the keys and then clears the table. - */ - void deleteKeys() { - for (size_t i = 0; i < numBuckets; i++) { - Node* node = bucket[i]; - while (node != NULL) { - delete node->entry.key; - node = node->next; - } - } - clear(); - } - - /** - Calls delete on all of the values. This is unsafe-- - do not call unless you know that each value appears - at most once. - - Does not clear the table, so you are left with a table - of NULL pointers. - */ - void deleteValues() { - for (size_t i = 0; i < numBuckets; ++i) { - Node* node = bucket[i]; - while (node != NULL) { - delete node->entry.value; - node->entry.value = NULL; - node = node->next; - } - } - } -}; - -} // namespace - -#ifdef _MSC_VER -# pragma warning (pop) -#endif - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/TextInput.h b/externals/g3dlite/G3D.lib/include/G3D/TextInput.h deleted file mode 100644 index b6dcad39b8b..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/TextInput.h +++ /dev/null @@ -1,693 +0,0 @@ -/** - @file TextInput.h - - Simple text lexer/tokenizer. - - @maintainer Morgan McGuire, morgan@graphics3d.com - - @cite Based on a lexer written by Aaron Orenstein. - - @created 2002-11-27 - @edited 2006-10-24 - - Copyright 2000-2007, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_TEXTINPUT_H -#define G3D_TEXTINPUT_H - -#include "G3D/platform.h" -#include "G3D/Array.h" -#include "G3D/Set.h" -#include -#include -#include -#include - -namespace G3D { - -/** - For use with TextInput. - */ -class Token { -public: - - /** - More detailed type information than Type. - */ - enum ExtendedType { - DOUBLE_QUOTED_TYPE, - SINGLE_QUOTED_TYPE, - SYMBOL_TYPE, - FLOATING_POINT_TYPE, - INTEGER_TYPE, - BOOLEAN_TYPE, - END_TYPE - }; - - /** - Strings are enclosed in quotes, symbols are not. - */ - enum Type { - STRING = DOUBLE_QUOTED_TYPE, - SYMBOL = SYMBOL_TYPE, - NUMBER = FLOATING_POINT_TYPE, - BOOLEAN = BOOLEAN_TYPE, - END = END_TYPE - }; - -private: - - friend class TextInput; - - /** - Holds the actual value, which might be any type. If a number, it will be - parsed at runtime. - */ - std::string _string; - - bool _bool; - int _line; - int _character; - Type _type; - ExtendedType _extendedType; - -public: - - Token() : - _string(""), - _bool(false), - _line(0), - _character(0), - _type(END), - _extendedType(END_TYPE) {} - - Token(Type t, ExtendedType e, const std::string& s, int L, int c) - : _string(s), _bool(false), _line(L), _character(c), _type(t), _extendedType(e) {} - - Token(Type t, ExtendedType e, const std::string& s, bool b, int L, int c) - : _string(s), _bool(b), _line(L), _character(c), _type(t), _extendedType(e) {} - - Type type() const { - return _type; - } - - ExtendedType extendedType() const { - return _extendedType; - } - - /** - The value of a single or double quote string (not including the quotes), - the name of a symbol, or the exact textual representation of a number as - parsed from the input. - */ - const std::string& string() const { - return _string; - } - - bool boolean() const { - return _bool; - } - - /** - Starting line of the input from which this token was parsed. Starts - at 1. - */ - int line() const { - return _line; - } - - /** - Starting character position in the input line from which this token was - parsed. Starts at 1. - */ - int character() const { - return _character; - } - - /** Return the numeric value for a number type, or zero if this is - not a number type. - */ - double number() const; -}; - - -/** - A simple style tokenizer for reading text files. TextInput handles a - superset of C++,Java, Matlab, and Bash code text including single - line comments, block comments, quoted strings with escape sequences, - and operators. TextInput recognizes several categories of tokens, - which are separated by white space, quotation marks, or the end of a - recognized operator: - -
    -
  • Token::SINGLE_QUOTED_TYPE string of characters surrounded by single quotes, e.g., 'x', '\0', 'foo'. -
  • Token::DOUBLE_QUOTED_TYPE string of characters surrounded by double quotes, e.g., "x", "abc\txyz", "b o b". -
  • Token::SYMBOL_TYPE legal C++ operators, keywords, and identifiers. e.g., >=, Foo, _X, class, { -
  • Token::INTEGER_TYPE numbers without decimal places or exponential notation. e.g., 10, 0x17F, 32, 0, -155 -
  • Token::FLOATING_POINT_TYPE numbers with decimal places or exponential notation. e.g., 1e3, -1.2, .4, 0.5 -
  • Token::BOOLEAN_TYPE special symbols like "true" and "false"; the exact details can be configured in TextInput::Settings -
- -

The special ".." and "..." tokens are always recognized in - addition to normal C++ operators. Additional tokens can be made - available by changing the Settings. - - Negative numbers are handled specially because of the ambiguity between unary minus and negative numbers-- - see the note on TextInput::read. - - TextInput does not have helper functions for types with non-obvious - formatting, or helpers that would be redundant. Use the serialize - methods instead for parsing specific types like int, Vector3, and - Color3. - - Inside quoted strings escape sequences are converted. Thus the - string token for ["a\nb"] is 'a', followed by a newline, followed by - 'b'. Outside of quoted strings, escape sequences are not converted, - so the token sequence for [a\nb] is symbol 'a', symbol '\', symbol - 'nb' (this matches what a C++ parser would do). The exception is - that a specified TextInput::Settings::otherCommentCharacter preceeded - by a backslash is assumed to be an escaped comment character and is - returned as a symbol token instead of being parsed as a comment - (this is what a LaTex or VRML parser would do). - - Examples - -

-  TextInput ti(TextInput::FROM_STRING, "name = \"Max\", height = 6");
-
-  Token t;
-
-  t = ti.read(); 
-  debugAssert(t.type == Token::SYMBOL);
-  debugAssert(t.sval == "name");
-
-  ti.read();
-  debugAssert(t.type == Token::SYMBOL);
-  debugAssert(t.sval == "=");
-
-  std::string name = ti.read().sval;
-  ti.read();
-  
- -
-  TextInput ti(TextInput::FROM_STRING, "name = \"Max\", height = 6");
-  ti.readSymbols("name", "=");
-  std::string name = ti.readString();
-  ti.readSymbols(",", "height", "=");
-  double height = ti. readNumber();
-  
- - Assumes that the file is not modified once opened. - */ -class TextInput { -public: - - /** Tokenizer configuration options. */ - class Settings { - public: - /** If true, slash-star marks a multi-line comment. Default - is true. */ - bool cComments; - - /** If true, // begins a single line comment. Default is true. */ - bool cppComments; - - /** If true, \r, \n, \t, \0, \\ and other escape sequences inside - strings are converted to the equivalent C++ escaped character. - If false, backslashes are treated literally. It is convenient to - set to false if reading Windows paths, for example, like - c:\foo\bar. - - Default is true. - */ - bool escapeSequencesInStrings; - - /** If non-NUL, specifies a character that begins single line - comments ('#' and '%' are popular choices). This is independent - of the cppComments flag. If the character appears in text with a - backslash in front of it, it is considered escaped and is not - treated as a comment character. - - Default is '\0'. - */ - char otherCommentCharacter; - - /** Another (optional) 1-comment character. Useful for files that - support multiple comment syntaxes. Default is '\0'. - */ - char otherCommentCharacter2; - - /** If true, "-1" parses as the number -1 instead of the - symbol "-" followed by the number 1. Default is true.*/ - bool signedNumbers; - - /** If true, strings can be marked with single quotes (e.g., - 'aaa'). If false, the quote character is parsed as a - symbol. Default is true. Backquote (`) is always parsed - as a symbol. */ - bool singleQuotedStrings; - - /** If set to a non-empty string, that string will be used in - place of the real file name (or in place of a pseudonym - constructed from the buffer if given FROM_STRING) in - tokens and exceptions. - - Default is empty. - */ - std::string sourceFileName; - - - /** Added to the line number reported by peekLineNumber and in - exceptions. Useful for concatenating files that are - parsed separately. Default is zero. */ - int startingLineNumberOffset; - - /** - Parse -1.#IND00 as the floating point number returned by - nan(), -1.#INF00 as -inf(), and 1.#INF00 as inf(). Note - that the C99 standard specifies that a variety of formats - like "NaN" and "nan" are to be used; these are easier to - parse yourself and not currently supported by readNumber. - - An alternative to specifying msvcSpecials is to read numbers as: -
-            Token x = t.read();
-            Token y = t.peek();
-            if ((x.string() == "-1.") && 
-                (y.string() == "#INF00") && 
-                (y.character() == x.character() + 3) &&
-                (y.line() == x.line()) {
-                t.read();
-                return nan();
-            }
-            // ... similar cases for inf
-          
- - If the single-comment character was #, the floating point - special format overrides the comment and will be parsed - instead. - - If signedNumbers is false msvcSpecials will not be parsed. - - Default is true. */ - bool msvcSpecials; - - /** - Parse the following set of useful proof symbols: - - => - ::> - <:: - :> - <: - |- - ::= - := - <- - - Default is false. - */ - bool proofSymbols; - - /** - When parsing booleans and msvcSpecials, is case significant? - Default is {true} - */ - bool caseSensitive; - - /** All symbols that will become the 'true' boolean token. See also caseSensitive. - Clear this value to disable parsing of true booleans. - - Default is {true}. - */ - Set trueSymbols; - - /** See trueSymbols. Default is {false}*/ - Set falseSymbols; - - Settings (); - }; - -private: - - std::deque stack; - - /** - Characters to be tokenized. - */ - Array buffer; - - /** - Offset of current character (the next character to consumed) in - input buffer. - */ - unsigned int currentCharOffset; - - /** - Line number of next character to be consumed from the input buffer. (1 - indicates first line of input.) - - Note that this is the line number of the @e next character to be - consumed from the input, not the line number of the @e last character - consumed! - */ - unsigned int lineNumber; - - /** - Character number (within the line) of the next character to be consumed - from the input buffer. (1 indicates first character of the line). - - Note that this is the character number of the @e next character to be - consumed from the input, not the character number of the @e last - character consumed! - */ - unsigned int charNumber; - - /** Configuration options. This includes the file name that will be - reported in tokens and exceptions. */ - Settings options; - - void init(); - - /** - Consumes the next character from the input buffer, and returns that - character. Updates lineNumber and charNumber to reflect the location of - the next character in the input buffer. - - Note: you shouldn't be using the return value of this function in most - cases. In general, you should peekInputChar() to get the next - character, determine what to do with it, then consume it with this - function (or with eatAndPeekInputChar()). Given that usage, in most - instances you already know what this function would return! - */ - int eatInputChar(); - - /** - Returns the next character from the input buffer, without consuming any - characters. Can also be used to look deeper into the input buffer. - Does not modify lineNumber or charNumber. - - @param distance Index of the character in the input buffer to peek at, - relative to the next character. Default is 0, for the next character in - the input buffer. - */ - int peekInputChar(unsigned int distance = 0); - - /** - Helper function to consume the next character in the input buffer and - peek at the one following (without consuming it). - */ - inline int eatAndPeekInputChar() { - eatInputChar(); - return peekInputChar(0); - } - - /** - Read the next token, returning an END token if no more input is - available. - */ - Token nextToken(); - - /** - Helper for nextToken. Appends characters to t._string until the end - delimiter is reached. - - When called, the next character in the input buffer should be first the - first character after the opening delimiter character. - */ - void parseQuotedString(unsigned char delimiter, Token& t); - -public: - - class TokenException { - public: - /** Name of file being parsed when exception occurred. */ - std::string sourceFile; - - /** Line number of start of token which caused the exception. 1 is - the first line of the file. Note that you can use - TextInput::Settings::startingLineNumberOffset to shift the effective line - number that is reported. - */ - int line; - - /** Character number in the line of start of token which caused the - exception. 1 is the character in the line. - */ - int character; - - /** Pre-formatted error message */ - std::string message; - - virtual ~TokenException() {} - - protected: - - TokenException( - const std::string& src, - int ln, - int ch); - - }; - - /** While parsing a number of the form 1.#IN?00, ? was - not 'D' or 'F'. */ - class BadMSVCSpecial : public TokenException { - public: - - BadMSVCSpecial( - const std::string& src, - int ln, - int ch); - }; - - /** Thrown by the read methods. */ - class WrongTokenType : public TokenException { - public: - Token::Type expected; - Token::Type actual; - - WrongTokenType( - const std::string& src, - int ln, - int ch, - Token::Type e, - Token::Type a); - }; - - class WrongSymbol : public TokenException { - public: - std::string expected; - std::string actual; - - WrongSymbol( - const std::string& src, - int ln, - int ch, - const std::string& e, - const std::string& a); - }; - - - /** String read from input did not match expected string. */ - class WrongString : public TokenException { - public: - std::string expected; - std::string actual; - - WrongString( - const std::string& src, - int ln, - int ch, - const std::string& e, - const std::string& a); - }; - - TextInput(const std::string& filename, const Settings& settings = Settings()); - - enum FS {FROM_STRING}; - /** Creates input directly from a string. The first argument must be - TextInput::FROM_STRING. - */ - TextInput(FS fs, const std::string& str, const Settings& settings = Settings()); - - /** Returns true while there are tokens remaining. */ - bool hasMore(); - - /** Read the next token (which will be the END token if ! hasMore()). - - Signed numbers can be handled in one of two modes. If the option - TextInput::Settings::signedNumbers is true, - A '+' or '-' immediately before a number is prepended onto that number and - if there is intervening whitespace, it is read as a separate symbol. - - If TextInput::Settings::signedNumbers is false, - read() does not distinguish between a plus or minus symbol next - to a number and a positive/negative number itself. For example, "x - 1" and "x -1" - will be parsed the same way by read(). - - In both cases, readNumber() will contract a leading "-" or "+" onto - a number. - */ - Token read(); - - - /** Read one token (or possibly two) as a number or throws - WrongTokenType, and returns the number. - - If the first token in the input is a number, it is returned directly. - - If TextInput::Settings::signedNumbers is false and the input stream - contains a '+' or '-' symbol token immediately followed by a number - token, both tokens will be consumed and a single token will be - returned by this method. - - WrongTokenType will be thrown if one of the input conditions - described above is not satisfied. When an exception is thrown, no - tokens are consumed. - */ - double readNumber(); - - bool readBoolean(); - - /** Reads a string token or throws WrongTokenType, and returns the token. - - Use this method (rather than readString) if you want the token's - location as well as its value. - - WrongTokenType will be thrown if the next token in the input stream - is not a string. When an exception is thrown, no tokens are - consumed. - */ - Token readStringToken(); - - /** Like readStringToken, but returns the token's string. - - Use this method (rather than readStringToken) if you want the token's - value but don't really care about its location in the input. Use of - readStringToken is encouraged for better error reporting. - */ - std::string readString(); - - /** Reads a specific string token or throws either WrongTokenType or - WrongString. If the next token in the input is a string matching @p - s, it will be consumed. - - Use this method if you want to match a specific string from the - input. In that case, typically error reporting related to the token - is only going to occur because of a mismatch, so no location - information is needed by the caller. - - WrongTokenType will be thrown if the next token in the input stream - is not a string. WrongString will be thrown if the next token in the - input stream is a string but does not match the @p s parameter. When - an exception is thrown, no tokens are consumed. - */ - void readString(const std::string& s); - - - /** Reads a symbol token or throws WrongTokenType, and returns the token. - - Use this method (rather than readSymbol) if you want the token's - location as well as its value. - - WrongTokenType will be thrown if the next token in the input stream - is not a symbol. When an exception is thrown, no tokens are - consumed. - */ - Token readSymbolToken(); - - /** Like readSymbolToken, but returns the token's string. - - Use this method (rather than readSymbolToken) if you want the token's - value but don't really care about its location in the input. Use of - readSymbolToken is encouraged for better error reporting. - */ - std::string readSymbol(); - - /** Reads a specific symbol token or throws either WrongTokenType or - WrongSymbol. If the next token in the input is a symbol matching @p - symbol, it will be consumed. - - Use this method if you want to match a specific symbol from the - input. In that case, typically error reporting related to the token - is only going to occur because of a mismatch, so no location - information is needed by the caller. - - WrongTokenType will be thrown if the next token in the input stream - is not a symbol. WrongSymbol will be thrown if the next token in the - input stream is a symbol but does not match the @p symbol parameter. - When an exception is thrown, no tokens are consumed. - */ - void readSymbol(const std::string& symbol); - - - /** Read a series of two specific symbols. See readSymbol. */ - inline void readSymbols(const std::string& s1, const std::string& s2) { - readSymbol(s1); - readSymbol(s2); - } - - /** Read a series of three specific symbols. See readSymbol. */ - inline void readSymbols( - const std::string& s1, - const std::string& s2, - const std::string& s3) { - readSymbol(s1); - readSymbol(s2); - readSymbol(s3); - } - - /** Read a series of four specific symbols. See readSymbol. */ - inline void readSymbols( - const std::string& s1, - const std::string& s2, - const std::string& s3, - const std::string& s4) { - readSymbol(s1); - readSymbol(s2); - readSymbol(s3); - readSymbol(s4); - } - - /** Return a copy of the next token in the input stream, but don't remove - it from the input stream. - */ - Token peek(); - - /** Returns the line number for the @e next token. See also peek. */ - int peekLineNumber(); - - /** Returns the character number (relative to the line) for the @e next - token in the input stream. See also peek. - */ - int peekCharacterNumber(); - - /** Take a previously read token and push it back at the front of the - input stream. - - Can be used in the case where more than one token of read-ahead is - needed (i.e., when peek doesn't suffice). - */ - void push(const Token& t); - - /** Returns the filename from which this input is drawn, or the first few - characters of the string if created from a string. - If options::filename is non-empty that will replace the - true filename.*/ - const std::string& filename() const; -}; - -void deserialize(bool& b, TextInput& ti); -void deserialize(int& b, TextInput& ti); -void deserialize(uint8& b, TextInput& ti); -void deserialize(double& b, TextInput& ti); -void deserialize(float& b, TextInput& ti); -void deserialize(std::string& b, TextInput& ti); - -} // namespace - -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/TextOutput.h b/externals/g3dlite/G3D.lib/include/G3D/TextOutput.h deleted file mode 100644 index 6ae7d14fe00..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/TextOutput.h +++ /dev/null @@ -1,249 +0,0 @@ -/** - @file TextOutput.h - - @maintainer Morgan McGuire, morgan@graphics3d.com - @created 2004-06-21 - @edited 2006-10-24 - - Copyright 2000-2007, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_TEXTOUTPUT_H -#define G3D_TEXTOUTPUT_H - -#include "G3D/platform.h" -#include "G3D/Array.h" -#include - -namespace G3D { - -/** - Convenient formatting of ASCII text written to a file. -

- - The core writeString, writeNumber, and writeSymbol methods map to TextInput's - methods. Number and Symbol each print an additional space that is used to - separate adjacent tokens. - - TextOutput::printf allows arbitrary text to be conveniently dumped - en-masse. Use [de]serialize(bool, TextOutput) and other overloads to read/write - primitive types in a standardized manner and - -

- When a word-wrap line break occurs, all whitespace between words is replaced - with a single newline (the newline may be two characters-- see - G3D::TextOutput::Options::NewlineStyle). Word wrapping occurs against - the number of columns specified by Options::numColumns, minus the current - indent level. - - Indenting adds the specified number of spaces immediately after a newline. - If a newline was followed by spaces in the original string, these are added - to the indent spaces. Indenting will indent blank lines and will leave - indents after the last newline of a file (if the indent level is non-zero at the end). - -

Serialization/Marshalling -

Text serialization is accomplished using TextOutput by defining the pair of - methods: - -
-  void serialize(TextOutput& to) const;
-  void deserialize(TextInput& ti);
-  
- - See also G3D::TextInput. - -

- BETA API -

This API is subject to change in future versions. - */ -class TextOutput { -public: - - class Settings { - public: - /** - WRAP_NONE Word wrapping is disabled - WRAP_WITHOUT_BREAKING Word-wrap, but don't break continuous lines that - are longer than numColumns (default) - WRAP_ALWAYS Wrap even if it means breaking a continuous line or - a quoted string. - - Word wrapping is only allowed at whitespaces ('\n', '\r', '\t', ' '); it - will not occur after commas, punctuation, minus signs, or any other characters - */ - enum WordWrapMode {WRAP_NONE, WRAP_WITHOUT_BREAKING, WRAP_ALWAYS}; - - /** Defaults to WRAP_WITHOUT_BREAKING */ - WordWrapMode wordWrap; - - /** Is word-wrapping allowed to insert newlines inside double quotes? - Default: false */ - bool allowWordWrapInsideDoubleQuotes; - - /** Number of columns for word wrapping. Default: 8 */ - int numColumns; - - /** Number of spaces in each indent. Default: 4 */ - int spacesPerIndent; - - /** Style of newline used by word wrapping and by (optional) conversion. - default: Windows: NEWLINE_WINDOWS, Linux, OS X: NEWLINE_UNIX. - */ - enum NewlineStyle {NEWLINE_WINDOWS, NEWLINE_UNIX}; - - NewlineStyle newlineStyle; - - /** If true, all newlines are converted to NewlineStyle regardless of - how they start out. Default: true. */ - bool convertNewlines; - - /** Used by writeBoolean */ - std::string trueSymbol; - - /** Used by writeBoolean */ - std::string falseSymbol; - - Settings() : - wordWrap(WRAP_WITHOUT_BREAKING), - allowWordWrapInsideDoubleQuotes(false), - numColumns(80), - spacesPerIndent(4), - convertNewlines(true), - trueSymbol("true"), - falseSymbol("false") { - #ifdef G3D_WIN32 - newlineStyle = NEWLINE_WINDOWS; - #else - newlineStyle = NEWLINE_UNIX; - #endif - } - }; - -private: - - /** Used by indentAndAppend to tell when we are writing the - first character of a new line. - - So that push/popIndent work correctly, we cannot indent - immediately after writing a newline. Instead we must - indent on writing the first character after that - newline. - */ - bool startingNewLine; - - /** Number of characters at the end of the buffer since the last newline */ - int currentColumn; - - /** True if we have seen an open " and no close ".*/ - bool inDQuote; - - /** Empty if there is none */ - std::string filename; - - Array data; - - Settings option; - - /** Number of indents to prepend before each line. Always set using setIndentLevel.*/ - int indentLevel; - - void setIndentLevel(int i); - - /** Actual number of spaces to indent. */ - int indentSpaces; - - /** the newline character(s) */ - std::string newline; - - void setOptions(const Settings& _opt); - - /** Converts to the desired newlines. Called from vprintf */ - void convertNewlines(const std::string& in, std::string& out); - - /** Called from vprintf */ - void wordWrapIndentAppend(const std::string& str); - - /** Appends the character to data, indenting whenever a newline is encountered. - Called from wordWrapIndentAppend */ - void indentAppend(char c); - -public: - - explicit TextOutput(const std::string& filename, const Settings& options = Settings()); - - /** Constructs a text output that can later be commited to a string instead of a file.*/ - explicit TextOutput(const Settings& options = Settings()); - - /** Commit to the filename specified on the constructor. - Not called from the destructor; you must call - it yourself. - @param flush If true (default) the file is ready for reading when the method returns, otherwise - the method returns immediately and writes the file in the background.*/ - void commit(bool flush = true); - - /** Commits to this string */ - void commitString(std::string& string); - - /** Increase indent level by 1 */ - void pushIndent(); - - void popIndent(); - - /** Produces a new string that contains the output */ - std::string commitString(); - - /** Writes a quoted string. Special characters in the string (e.g., \, \t, \n) are escaped so that - TextInput will produce the identical string on reading.*/ - void writeString(const std::string& string); - - void writeBoolean(bool b); - - void writeNumber(double n); - - void writeNumber(int n); - - void writeNewline(); - void writeNewlines(int numLines); - - /** The symbol is written without quotes. Symbols are required to begin with a - letter or underscore and contain only letters, underscores, and numbers - or be a C++ symbol (e.g. "{", "(", "++", etc.) - so that they may be properly parsed by TextInput::readSymbol. Symbols are - printed with a trailing space.*/ - void writeSymbol(const std::string& string); - - /** Convenient idiom for writing multiple symbols in a row, e.g. - writeSymbols("name", "="); The empty symbols are not written. - */ - void writeSymbols( - const std::string& a, - const std::string& b = "", - const std::string& c = "", - const std::string& d = "", - const std::string& e = "", - const std::string& f = ""); - - /** Normal printf conventions. Note that the output will be reformatted - for word-wrapping and newlines */ - void __cdecl printf(const char* fmt, ...) - G3D_CHECK_PRINTF_METHOD_ARGS; - - // Can't pass by reference because that confuses va_start - void __cdecl printf(const std::string fmt, ...); - void __cdecl vprintf(const char* fmt, va_list argPtr) - G3D_CHECK_VPRINTF_METHOD_ARGS; -}; - -// Primitive serializers -void serialize(const bool& b, TextOutput& to); -void serialize(const int& b, TextOutput& to); -void serialize(const uint8& b, TextOutput& to); -void serialize(const double& b, TextOutput& to); -void serialize(const float& b, TextOutput& to); -void serialize(const std::string& b, TextOutput& to); -void serialize(const char* b, TextOutput& to); - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/ThreadSet.h b/externals/g3dlite/G3D.lib/include/G3D/ThreadSet.h deleted file mode 100644 index 59c57b062ae..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/ThreadSet.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef G3D_THREADSET_H -#define G3D_THREADSET_H - -#include "G3D/platform.h" -#include "G3D/Array.h" -#include "G3D/ReferenceCount.h" -#include "G3D/GThread.h" - -namespace G3D { - -/** Manages a set of threads. All methods are threadsafe except for - the iterator begin/end. - - @beta*/ -class ThreadSet : public ReferenceCountedObject { -public: - /** Intended to allow future use with a template parameter.*/ - typedef GThread Thread; - - typedef ReferenceCountedPointer ThreadRef; - typedef ReferenceCountedPointer Ref; - typedef Array::Iterator Iterator; - typedef Array::ConstIterator ConstIterator; - -private: - - /** Protects m_thread */ - GMutex m_lock; - - /** Threads in the set */ - Array m_thread; - -public: - - /** Total number of threads (some of which may be completed). */ - int size() const; - - /** Number of threads that have been started */ - int numStarted() const; - - /** Start all threads that are not currently started */ - void start() const; - - /** Terminate all threads that are currently started */ - void terminate() const; - - /** Waits until all started threads have completed. */ - void waitForCompletion() const; - - /** Remove all (not stopping them) */ - void clear(); - - /** Removes completed threads and returns the new size.*/ - int removeCompleted(); - - /** Inserts a new thread, if it is not already present, and - returns the new number of threads.*/ - int insert(const ThreadRef& t); - - /** Removes a thread. Returns true if the thread was present and - removed. */ - bool remove(const ThreadRef& t); - - bool contains(const ThreadRef& t) const; - - /** It is an error to mutate the ThreadSet while iterating through it. */ - Iterator begin(); - - Iterator end(); - - ConstIterator begin() const; - - ConstIterator end() const; -}; - - -} // namespace G3D - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Triangle.h b/externals/g3dlite/G3D.lib/include/G3D/Triangle.h deleted file mode 100644 index 8b67acf4624..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Triangle.h +++ /dev/null @@ -1,143 +0,0 @@ -/** - @file Triangle.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-04-05 - @edited 2008-10-06 - - @cite Random point method by Greg Turk, Generating random points in triangles. In A. S. Glassner, ed., Graphics Gems, pp. 24-28. Academic Press, 1990 - - Copyright 2000-2008, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_TRIANGLE_H -#define G3D_TRIANGLE_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Vector3.h" -#include "G3D/Plane.h" -#include "G3D/BoundsTrait.h" -#include "G3D/debugAssert.h" -#include - -namespace G3D { - -/** - A generic triangle representation. This should not be used - as the underlying triangle for creating models; it is intended - for providing fast property queries but requires a lot of - storage and is mostly immutable. - */ -class Triangle { -private: - friend class CollisionDetection; - friend class Ray; - - Vector3 _vertex[3]; - - /** edgeDirection[i] is the normalized vector v[i+1] - v[i] */ - Vector3 edgeDirection[3]; - float edgeMagnitude[3]; - Plane _plane; - Vector3::Axis _primaryAxis; - - /** vertex[1] - vertex[0] */ - Vector3 _edge01; - - /** vertex[2] - vertex[0] */ - Vector3 _edge02; - - float _area; - - void init(const Vector3& v0, const Vector3& v1, const Vector3& v2); - -public: - - Triangle(class BinaryInput& b); - void serialize(class BinaryOutput& b); - void deserialize(class BinaryInput& b); - - Triangle(); - - Triangle(const Vector3& v0, const Vector3& v1, const Vector3& v2); - - ~Triangle(); - - /** 0, 1, or 2 */ - inline const Vector3& vertex(int n) const { - debugAssert((n >= 0) && (n < 3)); - return _vertex[n]; - } - - /** vertex[1] - vertex[0] */ - inline const Vector3& edge01() const { - return _edge01; - } - - /** vertex[2] - vertex[0] */ - inline const Vector3& edge02() const { - return _edge02; - } - - float area() const; - - Vector3::Axis primaryAxis() const { - return _primaryAxis; - } - - const Vector3& normal() const; - - /** Barycenter */ - Vector3 center() const; - - const Plane& plane() const; - - /** Returns a random point in the triangle. */ - Vector3 randomPoint() const; - - inline void getRandomSurfacePoint(Vector3& P, - Vector3& N = Vector3::dummy) const { - P = randomPoint(); - N = normal(); - } - /** - For two triangles to be equal they must have - the same vertices in the same order. - That is, vertex[0] == vertex[0], etc. - */ - inline bool operator==(const Triangle& other) const { - for (int i = 0; i < 3; ++i) { - if (_vertex[i] != other._vertex[i]) { - return false; - } - } - - return true; - } - - inline size_t hashCode() const { - return - _vertex[0].hashCode() + - (_vertex[1].hashCode() >> 2) + - (_vertex[2].hashCode() >> 3); - } - - void getBounds(class AABox&) const; - -}; - -} // namespace G3D - -template <> struct HashTrait { - static size_t hashCode(const G3D::Triangle& key) { return key.hashCode(); } -}; - - -template<> struct BoundsTrait { - static void getBounds(const G3D::Triangle& t, G3D::AABox& out) { t.getBounds(out); } -}; - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/UprightFrame.h b/externals/g3dlite/G3D.lib/include/G3D/UprightFrame.h deleted file mode 100644 index 52db3080b80..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/UprightFrame.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - @file UprightFrame.h - - @author Morgan McGuire, morgan@cs.williams.edu - */ - -#ifndef G3D_UPRIGHTFRAME_H -#define G3D_UPRIGHTFRAME_H - -#include "G3D/platform.h" -#include "G3D/Spline.h" -#include "G3D/Vector3.h" -#include "G3D/CoordinateFrame.h" - -namespace G3D { - -/** - Coordinate frame expressed in Euler angles. - Unlike a G3D::Quat, UprightFrame always keeps the reference frame from rolling about its own z axis. - Particularly useful for cameras. - - @sa G3D::CoordinateFrame, G3D::Matrix4, G3D::PhysicsFrame, G3D::UprightSpline, G3D::UprightSplineManipulator - */ -class UprightFrame { -public: - - Vector3 translation; - - /** -pi/2 < pitch < pi/2 in radians about the X-axis */ - float pitch; - - /** In radians about the Y-axis */ - float yaw; - - inline UprightFrame(const Vector3& t = Vector3::zero(), float p = 0, float y = 0) - : translation(t), pitch(p), yaw(y) {} - - UprightFrame(const CoordinateFrame& cframe); - - CoordinateFrame toCoordinateFrame() const; - - /** Supports implicit cast to CoordinateFrame */ - inline operator CoordinateFrame() const { - return toCoordinateFrame(); - } - - /** Required for use with spline */ - UprightFrame operator+(const UprightFrame& other) const; - - /** Required for use with spline */ - UprightFrame operator*(const float k) const; - - /** - Unwraps the yaw values in the elements of the array such that - they still represent the same angles but strictly increase/decrease - without wrapping about zero. For use with Spline - */ - static void unwrapYaw(UprightFrame* a, int N); - - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); -}; - -/** Shortest-path linear velocity spline for camera positions. Always keeps the camera from rolling. -@sa G3D::UprightSplineManipulator, G3D::UprightFrame -*/ -class UprightSpline : public Spline { -protected: - - virtual void ensureShortestPath(UprightFrame* A, int N) const { - UprightFrame::unwrapYaw(A, N); - } - -public: - - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); - -}; - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Vector2.h b/externals/g3dlite/G3D.lib/include/G3D/Vector2.h deleted file mode 100644 index b610a1a3500..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Vector2.h +++ /dev/null @@ -1,457 +0,0 @@ -/** - @file Vector2.h - - 2D vector class - - @maintainer Morgan McGuire, morgan@cs.williams.edu - - @created 2001-06-02 - @edited 2008-11-30 - - Copyright 2000-2008, Morgan McGuire. - All rights reserved. -*/ - -#ifndef G3D_VECTOR2_H -#define G3D_VECTOR2_H - -#include - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Table.h" -#include "G3D/HashTrait.h" -#include "G3D/Vector2int16.h" - -namespace G3D { - -class Vector2; -class Vector3; -class Vector4; - -/** - Do not subclass-- this implementation makes assumptions about the - memory layout. - */ -class Vector2 { -private: - // Hidden operators - bool operator<(const Vector2&) const; - bool operator>(const Vector2&) const; - bool operator<=(const Vector2&) const; - bool operator>=(const Vector2&) const; - -public: - float x; - float y; - - /** Creates the zero vector */ - Vector2(); - Vector2(class TextInput& t); - Vector2(class BinaryInput& b); - Vector2(float x, float y); - Vector2(float coordinate[2]); - Vector2(double coordinate[2]); - Vector2(const Vector2& other); - Vector2(const class Vector2int16& other); - - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); - - void serialize(class TextOutput& t) const; - void deserialize(class TextInput& t); - - float& operator[](int i); - const float& operator[](int i) const; - operator float*(); - operator const float*() const; - - // assignment and comparison - Vector2& operator=(const Vector2& other); - bool operator==(const Vector2& other) const; - bool operator!=(const Vector2& other) const; - size_t hashCode() const; - bool fuzzyEq(const Vector2& other) const; - bool fuzzyNe(const Vector2& other) const; - - /** Returns true if this vector has finite length */ - bool isFinite() const; - - /** Returns true if this vector has length == 0 */ - bool isZero() const; - - /** Returns true if this vector has length == 1 */ - bool isUnit() const; - - // arithmetic operations - Vector2 operator+(const Vector2& v) const; - Vector2 operator-(const Vector2& v) const; - Vector2 operator*(float s) const; - - /** Array (pointwise) multiplication */ - Vector2 operator*(const Vector2& v) const; - - /** Array division */ - Vector2 operator/(const Vector2& v) const; - Vector2 operator/(float s) const; - - /** Unary minus */ - Vector2 operator-() const; - - /** x + y */ - inline float sum() const { - return x + y; - } - - /** - Linear interpolation - */ - inline Vector2 lerp(const Vector2& v, float alpha) const { - return (*this) + (v - *this) * alpha; - } - - inline Vector2 clamp(const Vector2& low, const Vector2& high) const { - return Vector2( - G3D::clamp(x, low.x, high.x), - G3D::clamp(y, low.y, high.y)); - } - - inline Vector2 clamp(float low, float high) const { - return Vector2( - (float)G3D::clamp(x, low, high), - (float)G3D::clamp(y, low, high)); - } - - // arithmetic updates - Vector2& operator+=(const Vector2&); - Vector2& operator-=(const Vector2&); - Vector2& operator*=(float); - Vector2& operator/=(float); - Vector2& operator*=(const Vector2&); - Vector2& operator/=(const Vector2&); - - // vector operations - - /** */ - float length() const; - - /** Returns a unit-length vector */ - Vector2 direction() const; - - /** - Potentially less accurate but faster than direction(). - Only works if System::hasSSE is true. - */ - Vector2 fastDirection() const { - return direction(); - } - - float squaredLength() const; - float dot(const Vector2& s) const; - - /** - Make this vector have unit length and return the old length. - If the vector length was less than tolerance, do not normalize. - */ - float unitize(float fTolerance = 1e-06); - - Vector2 min(const Vector2& v) const; - Vector2 max(const Vector2& v) const; - - /** Uniformly distributed random vector on the unit sphere */ - static Vector2 random(); - - // Special values. - // Intentionally not inlined: see Matrix3::identity() for details. - static const Vector2& zero(); - inline static const Vector2& one() { static const Vector2 v(1, 1); return v; } - static const Vector2& unitX(); - static const Vector2& unitY(); - static const Vector2& inf(); - static const Vector2& nan(); - /** smallest (most negative) representable vector */ - static const Vector2& minFinite(); - /** Largest representable vector */ - static const Vector2& maxFinite(); - - std::string toString() const; - - // 2-char swizzles - - Vector2 xx() const; - Vector2 yx() const; - Vector2 xy() const; - Vector2 yy() const; - - // 3-char swizzles - - Vector3 xxx() const; - Vector3 yxx() const; - Vector3 xyx() const; - Vector3 yyx() const; - Vector3 xxy() const; - Vector3 yxy() const; - Vector3 xyy() const; - Vector3 yyy() const; - - // 4-char swizzles - - Vector4 xxxx() const; - Vector4 yxxx() const; - Vector4 xyxx() const; - Vector4 yyxx() const; - Vector4 xxyx() const; - Vector4 yxyx() const; - Vector4 xyyx() const; - Vector4 yyyx() const; - Vector4 xxxy() const; - Vector4 yxxy() const; - Vector4 xyxy() const; - Vector4 yyxy() const; - Vector4 xxyy() const; - Vector4 yxyy() const; - Vector4 xyyy() const; - Vector4 yyyy() const; - -}; - -inline Vector2 operator*(double s, const Vector2& v) { - return v * (float)s; -} - -inline Vector2 operator*(float s, const Vector2& v) { - return v * s; -} - -inline Vector2 operator*(int s, const Vector2& v) { - return v * (float)s; -} - - -inline Vector2::Vector2 () : x(0.0f), y(0.0f) { -} - - -inline Vector2::Vector2(float _x, float _y) : x(_x), y(_y) { -} - - -inline Vector2::Vector2 (float afCoordinate[2]) { - x = afCoordinate[0]; - y = afCoordinate[1]; -} - - - -inline Vector2::Vector2 (double afCoordinate[2]) { - x = (float)afCoordinate[0]; - y = (float)afCoordinate[1]; -} - - -inline Vector2::Vector2 (const Vector2& rkVector) { - x = rkVector.x; - y = rkVector.y; -} - - -inline Vector2::Vector2 (const Vector2int16& v) : x(v.x), y(v.y) { -} - - -inline float& Vector2::operator[] (int i) { - return ((float*)this)[i]; -} - - -inline const float& Vector2::operator[] (int i) const { - return ((float*)this)[i]; -} - - -inline Vector2::operator float* () { - return (float*)this; -} - -inline Vector2::operator const float* () const { - return (float*)this; -} - - -inline Vector2& Vector2::operator= (const Vector2& rkVector) { - x = rkVector.x; - y = rkVector.y; - return *this; -} - - -inline bool Vector2::operator== (const Vector2& rkVector) const { - return ( x == rkVector.x && y == rkVector.y); -} - - -inline bool Vector2::operator!= (const Vector2& rkVector) const { - return ( x != rkVector.x || y != rkVector.y); -} - - -inline Vector2 Vector2::operator+ (const Vector2& rkVector) const { - return Vector2(x + rkVector.x, y + rkVector.y); -} - - -inline Vector2 Vector2::operator- (const Vector2& rkVector) const { - return Vector2(x - rkVector.x, y - rkVector.y); -} - - -inline Vector2 Vector2::operator* (float fScalar) const { - return Vector2(fScalar*x, fScalar*y); -} - - - -inline Vector2 Vector2::operator- () const { - return Vector2( -x, -y); -} - - - -inline Vector2& Vector2::operator+= (const Vector2& rkVector) { - x += rkVector.x; - y += rkVector.y; - return *this; -} - - - -inline Vector2& Vector2::operator-= (const Vector2& rkVector) { - x -= rkVector.x; - y -= rkVector.y; - return *this; -} - - - -inline Vector2& Vector2::operator*= (float fScalar) { - x *= fScalar; - y *= fScalar; - return *this; -} - - - - -inline Vector2& Vector2::operator*= (const Vector2& rkVector) { - x *= rkVector.x; - y *= rkVector.y; - return *this; -} - - - -inline Vector2& Vector2::operator/= (const Vector2& rkVector) { - x /= rkVector.x; - y /= rkVector.y; - return *this; -} - - -inline Vector2 Vector2::operator* (const Vector2& rkVector) const { - return Vector2(x * rkVector.x, y * rkVector.y); -} - - - -inline Vector2 Vector2::operator/ (const Vector2& rkVector) const { - return Vector2(x / rkVector.x, y / rkVector.y); -} - - -inline float Vector2::squaredLength () const { - return x*x + y*y; -} - - -inline float Vector2::length () const { - return sqrtf(x*x + y*y); -} - - -inline Vector2 Vector2::direction () const { - float lenSquared = x * x + y * y; - - if (lenSquared != 1.0f) { - return *this / sqrtf(lenSquared); - } else { - return *this; - } -} - - - -inline float Vector2::dot (const Vector2& rkVector) const { - return x*rkVector.x + y*rkVector.y; -} - - - -inline Vector2 Vector2::min(const Vector2 &v) const { - return Vector2(G3D::min(v.x, x), G3D::min(v.y, y)); -} - - - -inline Vector2 Vector2::max(const Vector2 &v) const { - return Vector2(G3D::max(v.x, x), G3D::max(v.y, y)); -} - - - -inline bool Vector2::fuzzyEq(const Vector2& other) const { - return G3D::fuzzyEq((*this - other).squaredLength(), 0); -} - - - -inline bool Vector2::fuzzyNe(const Vector2& other) const { - return G3D::fuzzyNe((*this - other).squaredLength(), 0); -} - - - -inline bool Vector2::isFinite() const { - return G3D::isFinite(x) && G3D::isFinite(y); -} - - - -inline bool Vector2::isZero() const { - return (x == 0.0f) && (y == 0.0f); -} - - - -inline bool Vector2::isUnit() const { - return squaredLength() == 1.0f; -} - -} // namespace G3D - -template <> -struct HashTrait { - static size_t hashCode(const G3D::Vector2& key) { - return key.hashCode(); - } -}; - - -// Intentionally outside namespace to avoid operator overloading confusion -inline G3D::Vector2 operator*(double s, const G3D::Vector2& v) { - return v * (float)s; -} -inline G3D::Vector2 operator*(int s, const G3D::Vector2& v) { - return v * (float)s; -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Vector2int16.h b/externals/g3dlite/G3D.lib/include/G3D/Vector2int16.h deleted file mode 100644 index b7149ad6c90..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Vector2int16.h +++ /dev/null @@ -1,137 +0,0 @@ -/** - @file Vector2int16.h - - @maintainer Morgan McGuire, matrix@brown.edu - - @created 2003-08-09 - @edited 2004-01-03 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#ifndef VECTOR2INT16_H -#define VECTOR2INT16_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/HashTrait.h" - -namespace G3D { - -/** - A Vector2 that packs its fields into uint16s. - */ -#ifdef G3D_WIN32 - // Switch to tight alignment - #pragma pack(push, 2) -#endif - -class Vector2int16 { -private: - // Hidden operators - bool operator<(const Vector2int16&) const; - bool operator>(const Vector2int16&) const; - bool operator<=(const Vector2int16&) const; - bool operator>=(const Vector2int16&) const; - -public: - G3D::int16 x; - G3D::int16 y; - - Vector2int16() : x(0), y(0) {} - Vector2int16(G3D::int16 _x, G3D::int16 _y) : x(_x), y(_y){} - Vector2int16(const class Vector2& v); - Vector2int16(class BinaryInput& bi); - - inline G3D::int16& operator[] (int i) { - debugAssert(((unsigned int)i) <= 1); - return ((G3D::int16*)this)[i]; - } - - inline const G3D::int16& operator[] (int i) const { - debugAssert(((unsigned int)i) <= 1); - return ((G3D::int16*)this)[i]; - } - - inline Vector2int16 operator+(const Vector2int16& other) const { - return Vector2int16(x + other.x, y + other.y); - } - - inline Vector2int16 operator-(const Vector2int16& other) const { - return Vector2int16(x - other.x, y - other.y); - } - - inline Vector2int16 operator*(const Vector2int16& other) const { - return Vector2int16(x * other.x, y * other.y); - } - - inline Vector2int16 operator*(const int s) const { - return Vector2int16(x * s, y * s); - } - - inline Vector2int16& operator+=(const Vector2int16& other) { - x += other.x; - y += other.y; - return *this; - } - - /** Shifts both x and y */ - inline Vector2int16 operator>>(const int s) const { - return Vector2int16(x >> s, y >> s); - } - - /** Shifts both x and y */ - inline Vector2int16 operator<<(const int s) const { - return Vector2int16(x << s, y << s); - } - - inline Vector2int16& operator-=(const Vector2int16& other) { - x -= other.x; - y -= other.y; - return *this; - } - - inline Vector2int16& operator*=(const Vector2int16& other) { - x *= other.x; - y *= other.y; - return *this; - } - - Vector2int16 clamp(const Vector2int16& lo, const Vector2int16& hi); - - inline bool operator== (const Vector2int16& rkVector) const { - return ((int32*)this)[0] == ((int32*)&rkVector)[0]; - } - - inline bool operator!= (const Vector2int16& rkVector) const { - return ((int32*)this)[0] != ((int32*)&rkVector)[0]; - } - - Vector2int16 max(const Vector2int16& v) const { - return Vector2int16(iMax(x, v.x), iMax(y, v.y)); - } - - Vector2int16 min(const Vector2int16& v) const { - return Vector2int16(iMin(x, v.x), iMin(y, v.y)); - } - - void serialize(class BinaryOutput& bo) const; - void deserialize(class BinaryInput& bi); -} -#if defined(G3D_LINUX) || defined(G3D_OSX) - __attribute((aligned(1))) -#endif -; - -#ifdef G3D_WIN32 - #pragma pack(pop) -#endif - -} - -template<> struct HashTrait { - static size_t hashCode(const G3D::Vector2int16& key) { return static_cast(key.x + ((int)key.y << 16)); } -}; - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Vector3.h b/externals/g3dlite/G3D.lib/include/G3D/Vector3.h deleted file mode 100644 index d37638a229d..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Vector3.h +++ /dev/null @@ -1,761 +0,0 @@ -/** - @file Vector3.h - - 3D vector class - - @maintainer Morgan McGuire, morgan@cs.williams.edu - - @created 2001-06-02 - @edited 2008-11-01 - Copyright 2000-2008, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_VECTOR3_H -#define G3D_VECTOR3_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Vector2.h" -#include "G3D/Table.h" -#include "G3D/HashTrait.h" -#include "G3D/PositionTrait.h" -#include "G3D/Vector2.h" -#include -#include - -//---------------------------------------------------------------------------- -#ifdef SSE - // If you receive an error on this line, it is because you do not have the file - // xmmintrin.h needed for MMX & SSE extensions. Download and install - // - // http://download.microsoft.com/download/vstudio60ent/SP5/Wideband-Full/WIN98Me/EN-US/vs6sp5.exe - // and - // http://download.microsoft.com/download/vb60ent/Update/6/W9X2KXP/EN-US/vcpp5.exe - // - // to get this file. -# include -#endif - -namespace G3D { - -class Vector2; -class Vector3; -class Vector4; -class Vector4int8; - -/** - Swizzles - Vector classes have swizzle operators, e.g. v.xy(), that - allow selection of arbitrary sub-fields. These cannot be used as write - masks. Examples - -
-Vector3 v(1, 2, 3);
-Vector3 j;
-Vector2 b;
-
-b = v.xz();
-j = b.xx();
-
- - - Warning - - Do not subclass-- this implementation makes assumptions about the - memory layout. - */ -class Vector3 { -private: - /** - Reflect this vector about the (not necessarily unit) normal. - Note that if used for a collision or ray reflection you - must negate the resulting vector to get a direction pointing - away from the collision. - -
-       V'    N      V
-                 
-         r   ^   -,
-          \  |  /
-            \|/
-     
- - See also Vector3::reflectionDirection - */ - Vector3 reflectAbout(const Vector3& normal) const; - - // Hidden operators - bool operator<(const Vector3&) const; - bool operator>(const Vector3&) const; - bool operator<=(const Vector3&) const; - bool operator>=(const Vector3&) const; - -public: - // construction - Vector3(); - - /** Divides by 127 */ - Vector3(const Vector4int8&); - explicit Vector3(class BinaryInput& b); - Vector3(float _x, float _y, float _z); - explicit Vector3(const class Vector2& v, float _z); - explicit Vector3(float coordinate[3]); - explicit Vector3(double coordinate[3]); - Vector3(const Vector3& rkVector); - Vector3(const class Vector3int16& v); - explicit Vector3(class TextInput& t); - - /** Format is three float32's */ - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); - - /** Format is "(%f, %f, %f)" */ - void serialize(class TextOutput& t) const; - void deserialize(class TextInput& t); - - // coordinates - float x, y, z; - - // access vector V as V[0] = V.x, V[1] = V.y, V[2] = V.z - // - // WARNING. These member functions rely on - // (1) Vector3 not having virtual functions - // (2) the data packed in a 3*sizeof(float) memory block - const float& operator[] (int i) const; - float& operator[] (int i); - - inline operator float* () { - return (float*)this; - } - - operator const float* () const { - return (float*)this; - } - - enum Axis {X_AXIS=0, Y_AXIS=1, Z_AXIS=2, DETECT_AXIS=-1}; - - /** - Returns the largest dimension. Particularly convenient for determining - which plane to project a triangle onto for point-in-polygon tests. - */ - Axis primaryAxis() const; - - // assignment and comparison - Vector3& operator= (const Vector3& rkVector); - bool operator== (const Vector3& rkVector) const; - bool operator!= (const Vector3& rkVector) const; - size_t hashCode() const; - bool fuzzyEq(const Vector3& other) const; - bool fuzzyNe(const Vector3& other) const; - - /** Returns true if this vector has finite length. */ - bool isFinite() const; - - /** Returns true if this vector has length ~= 0 */ - bool isZero() const; - - /** Returns true if this vector has length ~= 1 */ - bool isUnit() const; - - // arithmetic operations - Vector3 operator+ (const Vector3& v) const; - Vector3 operator- (const Vector3& v) const; - Vector3 operator* (float s) const; - Vector3 operator/ (float s) const; - Vector3 operator* (const Vector3& v) const; - Vector3 operator/ (const Vector3& v) const; - Vector3 operator- () const; - - // arithmetic updates - Vector3& operator+= (const Vector3& v); - Vector3& operator-= (const Vector3& v); - Vector3& operator*= (float s); - Vector3& operator/= (float s); - Vector3& operator*= (const Vector3& v); - Vector3& operator/= (const Vector3& v); - - /** Same as magnitude */ - float length() const; - - float magnitude() const; - - /** - The result is a nan vector if the length is almost zero. - */ - Vector3 direction() const; - - /** - Potentially less accurate but faster than direction(). - Only works if System::hasSSE is true. - */ - Vector3 fastDirection() const; - - - /** - See also G3D::Ray::reflect. - The length is 1. -
-       V'    N       V
-                 
-         r   ^    /
-          \  |  /
-            \|'-
-     
- */ - Vector3 reflectionDirection(const Vector3& normal) const; - - - /** - Returns Vector3::zero() if the length is nearly zero, otherwise - returns a unit vector. - */ - inline Vector3 directionOrZero() const { - float mag = magnitude(); - if (G3D::fuzzyEq(mag, 0.0f)) { - return Vector3::zero(); - } else if (G3D::fuzzyEq(mag, 1.0f)) { - return *this; - } else { - return *this * (1.0f / mag); - } - } - - /** - Returns the direction of a refracted ray, - where iExit is the index of refraction for the - previous material and iEnter is the index of refraction - for the new material. Like Vector3::reflectionDirection, - the result has length 1 and is - pointed away from the intersection. - - Returns Vector3::zero() in the case of total internal refraction. - - @param iOutside The index of refraction (eta) outside - (on the positive normal side) of the surface. - - @param iInside The index of refraction (eta) inside - (on the negative normal side) of the surface. - - See also G3D::Ray::refract. -
-              N      V
-                  
-              ^    /
-              |  /
-              |'-
-          __--
-     V'<--
-     
- */ - Vector3 refractionDirection( - const Vector3& normal, - float iInside, - float iOutside) const; - - /** Synonym for direction */ - inline Vector3 unit() const { - return direction(); - } - - /** Returns a normalized vector. May be computed with lower - precision than unit */ - inline Vector3 fastUnit() const { - return fastDirection(); - } - - /** Same as squaredMagnitude */ - float squaredLength() const; - - float squaredMagnitude () const; - - float dot(const Vector3& rkVector) const; - - float unitize(float tolerance = 1e-06); - - /** Cross product. Note that two cross products in a row - can be computed more cheaply: v1 x (v2 x v3) = (v1 dot v3) v2 - (v1 dot v2) v3. - */ - Vector3 cross(const Vector3& rkVector) const; - Vector3 unitCross (const Vector3& rkVector) const; - - /** - Returns a matrix such that v.cross() * w = v.cross(w). -
-     [ 0  -v.z  v.y ]
-     [ v.z  0  -v.x ]
-     [ -v.y v.x  0  ]
-     
- */ - class Matrix3 cross() const; - - Vector3 min(const Vector3 &v) const; - Vector3 max(const Vector3 &v) const; - - /** Smallest element */ - inline float min() const { - return G3D::min(G3D::min(x, y), z); - } - - /** Largest element */ - inline float max() const { - return G3D::max(G3D::max(x, y), z); - } - - std::string toString() const; - - inline Vector3 clamp(const Vector3& low, const Vector3& high) const { - return Vector3( - G3D::clamp(x, low.x, high.x), - G3D::clamp(y, low.y, high.y), - G3D::clamp(z, low.z, high.z)); - } - - inline Vector3 clamp(float low, float high) const { - return Vector3( - G3D::clamp(x, low, high), - G3D::clamp(y, low, high), - G3D::clamp(z, low, high)); - } - - /** - Linear interpolation - */ - inline Vector3 lerp(const Vector3& v, float alpha) const { - return (*this) + (v - *this) * alpha; - } - - /** Gram-Schmidt orthonormalization. */ - static void orthonormalize (Vector3 akVector[3]); - - /** Random unit vector, uniformly distributed */ - static Vector3 random(); - - /** Random unit vector, distributed - so that the probability of V is proportional - to max(V dot Normal, 0). - - @cite Henrik Wann Jensen, Realistic Image Synthesis using Photon Mapping eqn 2.24 - */ - static Vector3 cosRandom(const Vector3& normal); - - - /** - Random vector distributed over the hemisphere about normal. - */ - static Vector3 hemiRandom(const Vector3& normal); - - // Input W must be initialize to a nonzero vector, output is {U,V,W} - // an orthonormal basis. A hint is provided about whether or not W - // is already unit length. - static void generateOrthonormalBasis (Vector3& rkU, Vector3& rkV, - Vector3& rkW, bool bUnitLengthW = true); - - inline float sum() const { - return x + y + z; - } - - inline float average() const { - return sum() / 3.0f; - } - - // Special values. - inline static const Vector3& zero() { static Vector3 v(0, 0, 0); return v; } - inline static const Vector3& one() { static Vector3 v(1, 1, 1); return v; } - inline static const Vector3& unitX() { static Vector3 v(1, 0, 0); return v; } - inline static const Vector3& unitY() { static Vector3 v(0, 1, 0); return v; } - inline static const Vector3& unitZ() { static Vector3 v(0, 0, 1); return v; } - inline static const Vector3& inf() { static Vector3 v((float)G3D::inf(), (float)G3D::inf(), (float)G3D::inf()); return v; } - inline static const Vector3& nan() { static Vector3 v((float)G3D::nan(), (float)G3D::nan(), (float)G3D::nan()); return v; } - /** Smallest (most negative) representable vector */ - inline static const Vector3& minFinite(){ static Vector3 v(-FLT_MAX, -FLT_MAX, -FLT_MAX); return v; } - /** Largest representable vector */ - inline static const Vector3& maxFinite(){ static Vector3 v(FLT_MAX, FLT_MAX, FLT_MAX); return v; } - - // 2-char swizzles - - Vector2 xx() const; - Vector2 yx() const; - Vector2 zx() const; - Vector2 xy() const; - Vector2 yy() const; - Vector2 zy() const; - Vector2 xz() const; - Vector2 yz() const; - Vector2 zz() const; - - // 3-char swizzles - - Vector3 xxx() const; - Vector3 yxx() const; - Vector3 zxx() const; - Vector3 xyx() const; - Vector3 yyx() const; - Vector3 zyx() const; - Vector3 xzx() const; - Vector3 yzx() const; - Vector3 zzx() const; - Vector3 xxy() const; - Vector3 yxy() const; - Vector3 zxy() const; - Vector3 xyy() const; - Vector3 yyy() const; - Vector3 zyy() const; - Vector3 xzy() const; - Vector3 yzy() const; - Vector3 zzy() const; - Vector3 xxz() const; - Vector3 yxz() const; - Vector3 zxz() const; - Vector3 xyz() const; - Vector3 yyz() const; - Vector3 zyz() const; - Vector3 xzz() const; - Vector3 yzz() const; - Vector3 zzz() const; - - // 4-char swizzles - - Vector4 xxxx() const; - Vector4 yxxx() const; - Vector4 zxxx() const; - Vector4 xyxx() const; - Vector4 yyxx() const; - Vector4 zyxx() const; - Vector4 xzxx() const; - Vector4 yzxx() const; - Vector4 zzxx() const; - Vector4 xxyx() const; - Vector4 yxyx() const; - Vector4 zxyx() const; - Vector4 xyyx() const; - Vector4 yyyx() const; - Vector4 zyyx() const; - Vector4 xzyx() const; - Vector4 yzyx() const; - Vector4 zzyx() const; - Vector4 xxzx() const; - Vector4 yxzx() const; - Vector4 zxzx() const; - Vector4 xyzx() const; - Vector4 yyzx() const; - Vector4 zyzx() const; - Vector4 xzzx() const; - Vector4 yzzx() const; - Vector4 zzzx() const; - Vector4 xxxy() const; - Vector4 yxxy() const; - Vector4 zxxy() const; - Vector4 xyxy() const; - Vector4 yyxy() const; - Vector4 zyxy() const; - Vector4 xzxy() const; - Vector4 yzxy() const; - Vector4 zzxy() const; - Vector4 xxyy() const; - Vector4 yxyy() const; - Vector4 zxyy() const; - Vector4 xyyy() const; - Vector4 yyyy() const; - Vector4 zyyy() const; - Vector4 xzyy() const; - Vector4 yzyy() const; - Vector4 zzyy() const; - Vector4 xxzy() const; - Vector4 yxzy() const; - Vector4 zxzy() const; - Vector4 xyzy() const; - Vector4 yyzy() const; - Vector4 zyzy() const; - Vector4 xzzy() const; - Vector4 yzzy() const; - Vector4 zzzy() const; - Vector4 xxxz() const; - Vector4 yxxz() const; - Vector4 zxxz() const; - Vector4 xyxz() const; - Vector4 yyxz() const; - Vector4 zyxz() const; - Vector4 xzxz() const; - Vector4 yzxz() const; - Vector4 zzxz() const; - Vector4 xxyz() const; - Vector4 yxyz() const; - Vector4 zxyz() const; - Vector4 xyyz() const; - Vector4 yyyz() const; - Vector4 zyyz() const; - Vector4 xzyz() const; - Vector4 yzyz() const; - Vector4 zzyz() const; - Vector4 xxzz() const; - Vector4 yxzz() const; - Vector4 zxzz() const; - Vector4 xyzz() const; - Vector4 yyzz() const; - Vector4 zyzz() const; - Vector4 xzzz() const; - Vector4 yzzz() const; - Vector4 zzzz() const; - - /** A value that can be passed to ignore a parameter. Never look at the result of dummy. */ - static Vector3 dummy; -}; - -inline G3D::Vector3 operator*(float s, const G3D::Vector3& v) { - return v * s; -} - -inline G3D::Vector3 operator*(double s, const G3D::Vector3& v) { - return v * (float)s; -} - -inline G3D::Vector3 operator*(int s, const G3D::Vector3& v) { - return v * (float)s; -} - -std::ostream& operator<<(std::ostream& os, const Vector3&); - - -void serialize(const Vector3::Axis& a, class BinaryOutput& bo); -void deserialize(Vector3::Axis& a, class BinaryInput& bo); - - -//---------------------------------------------------------------------------- -inline Vector3::Vector3() : x(0.0f), y(0.0f), z(0.0f) { -} - -//---------------------------------------------------------------------------- - -inline Vector3::Vector3 (float fX, float fY, float fZ) : x(fX), y(fY), z(fZ) { -} - -//---------------------------------------------------------------------------- -inline Vector3::Vector3 (float V[3]) : x(V[0]), y(V[1]), z(V[2]){ -} -//---------------------------------------------------------------------------- -inline Vector3::Vector3 (double V[3]) : x((float)V[0]), y((float)V[1]), z((float)V[2]){ -} - -//---------------------------------------------------------------------------- -inline Vector3::Vector3 (const Vector3& V) : x(V.x), y(V.y), z(V.z) { -} - -//---------------------------------------------------------------------------- - -//inline Vector3::Vector3 (const __m128& m) { - // Cast from SSE packed floats -// *this = *(Vector3*)&m; -//} - -//---------------------------------------------------------------------------- -inline const float& Vector3::operator[] (int i) const { - return ((float*)this)[i]; -} - -inline float& Vector3::operator[] (int i) { - return ((float*)this)[i]; -} - - -//---------------------------------------------------------------------------- -inline Vector3& Vector3::operator= (const Vector3& rkVector) { - x = rkVector.x; - y = rkVector.y; - z = rkVector.z; - return *this; -} - -//---------------------------------------------------------------------------- - -inline bool Vector3::fuzzyEq(const Vector3& other) const { - return G3D::fuzzyEq((*this - other).squaredMagnitude(), 0); -} - -//---------------------------------------------------------------------------- - -inline bool Vector3::fuzzyNe(const Vector3& other) const { - return G3D::fuzzyNe((*this - other).squaredMagnitude(), 0); -} - -//---------------------------------------------------------------------------- - -inline bool Vector3::isFinite() const { - return G3D::isFinite(x) && G3D::isFinite(y) && G3D::isFinite(z); -} - -//---------------------------------------------------------------------------- -inline bool Vector3::operator== (const Vector3& rkVector) const { - return ( x == rkVector.x && y == rkVector.y && z == rkVector.z ); -} - -//---------------------------------------------------------------------------- -inline bool Vector3::operator!= (const Vector3& rkVector) const { - return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); -} - -//---------------------------------------------------------------------------- -inline Vector3 Vector3::operator+ (const Vector3& rkVector) const { - return Vector3(x + rkVector.x, y + rkVector.y, z + rkVector.z); -} - -//---------------------------------------------------------------------------- -inline Vector3 Vector3::operator- (const Vector3& rkVector) const { - return Vector3(x - rkVector.x, y - rkVector.y, z - rkVector.z); -} - -//---------------------------------------------------------------------------- -inline Vector3 Vector3::operator* (const Vector3& rkVector) const { - return Vector3(x * rkVector.x, y * rkVector.y, z * rkVector.z); -} - -inline Vector3 Vector3::operator*(float f) const { - return Vector3(x * f, y * f, z * f); -} - -//---------------------------------------------------------------------------- -inline Vector3 Vector3::operator/ (const Vector3& rkVector) const { - return Vector3(x / rkVector.x, y / rkVector.y, z / rkVector.z); -} - -//---------------------------------------------------------------------------- -inline Vector3 Vector3::operator- () const { - return Vector3(-x, -y, -z); -} - -//---------------------------------------------------------------------------- -inline Vector3& Vector3::operator+= (const Vector3& rkVector) { - x += rkVector.x; - y += rkVector.y; - z += rkVector.z; - return *this; -} - -//---------------------------------------------------------------------------- -inline Vector3& Vector3::operator-= (const Vector3& rkVector) { - x -= rkVector.x; - y -= rkVector.y; - z -= rkVector.z; - return *this; -} - -//---------------------------------------------------------------------------- -inline Vector3& Vector3::operator*= (float fScalar) { - x *= fScalar; - y *= fScalar; - z *= fScalar; - return *this; -} - -//---------------------------------------------------------------------------- -inline Vector3& Vector3::operator*= (const Vector3& rkVector) { - x *= rkVector.x; - y *= rkVector.y; - z *= rkVector.z; - return *this; -} - -//---------------------------------------------------------------------------- -inline Vector3& Vector3::operator/= (const Vector3& rkVector) { - x /= rkVector.x; - y /= rkVector.y; - z /= rkVector.z; - return *this; -} - -//---------------------------------------------------------------------------- -inline float Vector3::squaredMagnitude () const { - return x*x + y*y + z*z; -} - -//---------------------------------------------------------------------------- -inline float Vector3::squaredLength () const { - return squaredMagnitude(); -} - -//---------------------------------------------------------------------------- -inline float Vector3::magnitude() const { - return sqrtf(x*x + y*y + z*z); -} - -//---------------------------------------------------------------------------- -inline float Vector3::length() const { - return magnitude(); -} - -//---------------------------------------------------------------------------- -inline Vector3 Vector3::direction () const { - float lenSquared = squaredMagnitude(); - float invSqrt = 1.0f / sqrtf(lenSquared); - return Vector3(x * invSqrt, y * invSqrt, z * invSqrt); -} - -//---------------------------------------------------------------------------- - -inline Vector3 Vector3::fastDirection () const { - float lenSquared = x * x + y * y + z * z; - float invSqrt = rsq(lenSquared); - return Vector3(x * invSqrt, y * invSqrt, z * invSqrt); -} - -//---------------------------------------------------------------------------- -inline float Vector3::dot (const Vector3& rkVector) const { - return x*rkVector.x + y*rkVector.y + z*rkVector.z; -} - -//---------------------------------------------------------------------------- -inline Vector3 Vector3::cross (const Vector3& rkVector) const { - return Vector3(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z, - x*rkVector.y - y*rkVector.x); -} - -//---------------------------------------------------------------------------- -inline Vector3 Vector3::unitCross (const Vector3& rkVector) const { - Vector3 kCross(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z, - x*rkVector.y - y*rkVector.x); - kCross.unitize(); - return kCross; -} - -//---------------------------------------------------------------------------- -inline Vector3 Vector3::min(const Vector3 &v) const { - return Vector3(G3D::min(v.x, x), G3D::min(v.y, y), G3D::min(v.z, z)); -} - -//---------------------------------------------------------------------------- -inline Vector3 Vector3::max(const Vector3 &v) const { - return Vector3(G3D::max(v.x, x), G3D::max(v.y, y), G3D::max(v.z, z)); -} - -//---------------------------------------------------------------------------- -inline bool Vector3::isZero() const { - return G3D::fuzzyEq(squaredMagnitude(), 0.0f); -} - -//---------------------------------------------------------------------------- - -inline bool Vector3::isUnit() const { - return G3D::fuzzyEq(squaredMagnitude(), 1.0f); -} - -} // namespace G3D - - -template <> -struct HashTrait { - static size_t hashCode(const G3D::Vector3& key) { - return key.hashCode(); - } -}; - - -template<> struct PositionTrait { - static void getPosition(const G3D::Vector2& v, G3D::Vector3& p) { p = G3D::Vector3(v, 0); } -}; - -template<> struct PositionTrait { - static void getPosition(const G3D::Vector3& v, G3D::Vector3& p) { p = v; } -}; - - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Vector3int16.h b/externals/g3dlite/G3D.lib/include/G3D/Vector3int16.h deleted file mode 100644 index f3f30a5bab4..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Vector3int16.h +++ /dev/null @@ -1,130 +0,0 @@ -/** - @file Vector3int16.h - - @maintainer Morgan McGuire, matrix@brown.edu - - @created 2003-04-07 - @edited 2003-06-24 - Copyright 2000-2004, Morgan McGuire. - All rights reserved. - */ - -#ifndef VECTOR3INT16_H -#define VECTOR3INT16_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/HashTrait.h" - -namespace G3D { - -/** - A Vector3 that packs its fields into uint16s. - */ -#ifdef G3D_WIN32 - // Switch to tight alignment - #pragma pack(push, 2) -#endif - -class Vector3int16 { -private: - // Hidden operators - bool operator<(const Vector3int16&) const; - bool operator>(const Vector3int16&) const; - bool operator<=(const Vector3int16&) const; - bool operator>=(const Vector3int16&) const; - -public: - G3D::int16 x; - G3D::int16 y; - G3D::int16 z; - - Vector3int16() : x(0), y(0), z(0) {} - Vector3int16(G3D::int16 _x, G3D::int16 _y, G3D::int16 _z) : x(_x), y(_y), z(_z) {} - Vector3int16(const class Vector3& v); - Vector3int16(class BinaryInput& bi); - - void serialize(class BinaryOutput& bo) const; - void deserialize(class BinaryInput& bi); - - inline G3D::int16& operator[] (int i) { - debugAssert(i <= 2); - return ((G3D::int16*)this)[i]; - } - - inline const G3D::int16& operator[] (int i) const { - debugAssert(i <= 2); - return ((G3D::int16*)this)[i]; - } - - inline Vector3int16 operator+(const Vector3int16& other) const { - return Vector3int16(x + other.x, y + other.y, z + other.z); - } - - inline Vector3int16 operator-(const Vector3int16& other) const { - return Vector3int16(x - other.x, y - other.y, z - other.z); - } - - inline Vector3int16 operator*(const Vector3int16& other) const { - return Vector3int16(x * other.x, y * other.y, z * other.z); - } - - inline Vector3int16 operator*(const int s) const { - return Vector3int16(x * s, y * s, z * s); - } - - inline Vector3int16& operator+=(const Vector3int16& other) { - x += other.x; - y += other.y; - z += other.y; - return *this; - } - - inline Vector3int16& operator-=(const Vector3int16& other) { - x -= other.x; - y -= other.y; - z -= other.z; - return *this; - } - - inline Vector3int16& operator*=(const Vector3int16& other) { - x *= other.x; - y *= other.y; - z *= other.z; - return *this; - } - - inline bool operator== (const Vector3int16& rkVector) const { - return ( x == rkVector.x && y == rkVector.y && z == rkVector.z ); - } - - inline bool operator!= (const Vector3int16& rkVector) const { - return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); - } - - Vector3int16 max(const Vector3int16& v) const { - return Vector3int16(iMax(x, v.x), iMax(y, v.y), iMax(z, v.z)); - } - - Vector3int16 min(const Vector3int16& v) const { - return Vector3int16(iMin(x, v.x), iMin(y, v.y), iMin(z, v.z)); - } - - std::string toString() const; -} -#if defined(G3D_LINUX) || defined(G3D_OSX) - __attribute((aligned(1))) -#endif -; - -#ifdef G3D_WIN32 - #pragma pack(pop) -#endif - -} - -template <> struct HashTrait { - static size_t hashCode(const G3D::Vector3int16& key) { return static_cast(key.x + ((int)key.y << 5) + ((int)key.z << 10)); } -}; - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Vector3int32.h b/externals/g3dlite/G3D.lib/include/G3D/Vector3int32.h deleted file mode 100644 index 01c8581b47a..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Vector3int32.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - @file Vector3int32.h - - @maintainer Morgan McGuire, matrix@brown.edu - - @created 2008-07-01 - @edited 2008-07-01 - Copyright 2000-2008, Morgan McGuire. - All rights reserved. - */ - -#ifndef VECTOR3INT32_H -#define VECTOR3INT32_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/HashTrait.h" - -namespace G3D { - -/** - A Vector3 that packs its fields into uint32s. - */ -#ifdef G3D_WIN32 - // Switch to tight alignment - #pragma pack(push, 4) -#endif - -class Vector3int32 { -private: - // Hidden operators - bool operator<(const Vector3int32&) const; - bool operator>(const Vector3int32&) const; - bool operator<=(const Vector3int32&) const; - bool operator>=(const Vector3int32&) const; - -public: - G3D::int32 x; - G3D::int32 y; - G3D::int32 z; - - Vector3int32() : x(0), y(0), z(0) {} - Vector3int32(int _x, int _y, int _z) : x(_x), y(_y), z(_z) {} - Vector3int32(const class Vector3int16& v); - Vector3int32(const class Vector3& v); - Vector3int32(class BinaryInput& bi); - - void serialize(class BinaryOutput& bo) const; - void deserialize(class BinaryInput& bi); - - inline G3D::int32& operator[] (int i) { - debugAssert(i <= 2); - return ((G3D::int32*)this)[i]; - } - - inline const G3D::int32& operator[] (int i) const { - debugAssert(i <= 2); - return ((G3D::int32*)this)[i]; - } - - inline Vector3int32 operator+(const Vector3int32& other) const { - return Vector3int32(x + other.x, y + other.y, z + other.z); - } - - inline Vector3int32 operator-(const Vector3int32& other) const { - return Vector3int32(x - other.x, y - other.y, z - other.z); - } - - inline Vector3int32 operator*(const Vector3int32& other) const { - return Vector3int32(x * other.x, y * other.y, z * other.z); - } - - inline Vector3int32 operator*(const int s) const { - return Vector3int32(x * s, y * s, z * s); - } - - inline Vector3int32& operator+=(const Vector3int32& other) { - x += other.x; - y += other.y; - z += other.y; - return *this; - } - - inline Vector3int32& operator-=(const Vector3int32& other) { - x -= other.x; - y -= other.y; - z -= other.z; - return *this; - } - - inline Vector3int32& operator*=(const Vector3int32& other) { - x *= other.x; - y *= other.y; - z *= other.z; - return *this; - } - - inline bool operator== (const Vector3int32& rkVector) const { - return ( x == rkVector.x && y == rkVector.y && z == rkVector.z ); - } - - inline bool operator!= (const Vector3int32& rkVector) const { - return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); - } - - Vector3int32 max(const Vector3int32& v) const { - return Vector3int32(iMax(x, v.x), iMax(y, v.y), iMax(z, v.z)); - } - - Vector3int32 min(const Vector3int32& v) const { - return Vector3int32(iMin(x, v.x), iMin(y, v.y), iMin(z, v.z)); - } - - std::string toString() const; -} -#if defined(G3D_LINUX) || defined(G3D_OSX) - __attribute((aligned(1))) -#endif -; - -#ifdef G3D_WIN32 - #pragma pack(pop) -#endif - -} - -template <> struct HashTrait { - static size_t hashCode(const G3D::Vector3int32& key) { - // Mask for the top bit of a uint32 - const G3D::uint32 top = (1 << 31); - // Mask for the bottom 10 bits of a uint32 - const G3D::uint32 bot = 0x000003FF; - return static_cast(((key.x & top) | ((key.y & top) >> 1) | ((key.z & top) >> 2)) | - (((key.x & bot) << 19) ^ ((key.y & bot) << 10) ^ (key.z & bot))); - } -}; - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Vector4.h b/externals/g3dlite/G3D.lib/include/G3D/Vector4.h deleted file mode 100644 index d60ff76ea8b..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Vector4.h +++ /dev/null @@ -1,717 +0,0 @@ -/** - @file Vector4.h - - Homogeneous vector class. - - @maintainer Morgan McGuire, morgan@cs.williams.edu - - @created 2002-07-09 - @edited 2008-11-01 - - Copyright 2000-2008, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_VECTOR4_H -#define G3D_VECTOR4_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Vector3.h" -#include "G3D/Vector2.h" -#include "G3D/Table.h" -#include "G3D/HashTrait.h" -#include "G3D/PositionTrait.h" -#include - -namespace G3D { - -class Vector2; -class Vector3; -class Vector4; -class Vector4int8; - -/** - Do not subclass-- this implementation makes assumptions about the - memory layout. - */ -class Vector4 { -private: - // Hidden operators - bool operator<(const Vector4&) const; - bool operator>(const Vector4&) const; - bool operator<=(const Vector4&) const; - bool operator>=(const Vector4&) const; - -public: - // construction - Vector4(); - Vector4(float fX, float fY, float fZ, float fW); - Vector4(float afCoordinate[4]); - Vector4(const Vector4& rkVector); - Vector4(const class Color4& c); - Vector4(const Vector3& rkVector, float fW); - Vector4(const Vector2& v1, const Vector2& v2); - Vector4(const Vector2& v1, float fz, float fw); - - /** Divides by 127 when converting */ - Vector4(const Vector4int8&); - - Vector4(class BinaryInput& b); - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); - - // coordinates - float x, y, z, w; - - // access vector V as V[0] = V.x, V[1] = V.y, V[2] = V.z, etc. - // - // WARNING. These member functions rely on - // (1) Vector4 not having virtual functions - // (2) the data packed in a 4*sizeof(float) memory block - float& operator[] (int i); - const float& operator[] (int i) const; - operator float* (); - operator const float* () const; - - // assignment and comparison - Vector4& operator= (const Vector4& rkVector); - bool operator== (const Vector4& rkVector) const; - bool operator!= (const Vector4& rkVector) const; - - inline void set(float _x, float _y, float _z, float _w) { - x = _x; - y = _y; - z = _z; - w = _w; - } - - inline void set(const Vector3& v, float _w) { - x = v.x; - y = v.y; - z = v.z; - w = _w; - } - - inline void set(const Vector2& v, float _z, float _w) { - x = v.x; - y = v.y; - z = _z; - w = _w; - } - - size_t hashCode() const; - bool fuzzyEq(const Vector4& other) const; - bool fuzzyNe(const Vector4& other) const; - - inline static const Vector4& inf() { static Vector4 v((float)G3D::inf(), (float)G3D::inf(), (float)G3D::inf(), (float)G3D::inf()); return v; } - inline static const Vector4& nan() { static Vector4 v((float)G3D::nan(), (float)G3D::nan(), (float)G3D::nan(), (float)G3D::nan()); return v; } - - /** sqrt(this->dot(*this)) */ - float length() const; - float squaredLength() const; - - inline float sum() const { - return x + y + z + w; - } - - /** Returns true if this vector has finite length */ - bool isFinite() const; - - /** Returns true if this vector has length == 0 */ - bool isZero() const; - - /** Returns true if this vector has length == 1 */ - bool isUnit() const; - - // arithmetic operations - Vector4 operator+ (const Vector4& rkVector) const; - Vector4 operator- (const Vector4& rkVector) const; - - inline Vector4 operator*(const Vector4& rkVector) const { - return Vector4(x * rkVector.x, y * rkVector.y, z * rkVector.z, w * rkVector.w); - } - - inline Vector4 operator/(const Vector4& rkVector) const { - return Vector4(x / rkVector.x, y / rkVector.y, z / rkVector.z, w / rkVector.w); - } - - Vector4 operator*(const class Matrix4& M) const; - - Vector4 operator* (float fScalar) const; - Vector4 operator/ (float fScalar) const; - Vector4 operator- () const; - friend Vector4 operator* (float, const Vector4& rkVector); - - // arithmetic updates - Vector4& operator+= (const Vector4& rkVector); - Vector4& operator-= (const Vector4& rkVector); - Vector4& operator*= (float fScalar); - Vector4& operator/= (float fScalar); - - inline Vector4 clamp(const Vector4& low, const Vector4& high) const { - return Vector4( - G3D::clamp(x, low.x, high.x), - G3D::clamp(y, low.y, high.y), - G3D::clamp(z, low.z, high.z), - G3D::clamp(w, low.w, high.w)); - } - - inline Vector4 clamp(float low, float high) const { - return Vector4( - G3D::clamp(x, low, high), - G3D::clamp(y, low, high), - G3D::clamp(z, low, high), - G3D::clamp(w, low, high)); - } - - float dot (const Vector4& rkVector) const; - - Vector4 min(const Vector4& v) const; - Vector4 max(const Vector4& v) const; - - std::string toString() const; - - /** - Linear interpolation - */ - Vector4 lerp(const Vector4& v, float alpha) const; - - // 2-char swizzles - - Vector2 xx() const; - Vector2 yx() const; - Vector2 zx() const; - Vector2 wx() const; - Vector2 xy() const; - Vector2 yy() const; - Vector2 zy() const; - Vector2 wy() const; - Vector2 xz() const; - Vector2 yz() const; - Vector2 zz() const; - Vector2 wz() const; - Vector2 xw() const; - Vector2 yw() const; - Vector2 zw() const; - Vector2 ww() const; - - // 3-char swizzles - - Vector3 xxx() const; - Vector3 yxx() const; - Vector3 zxx() const; - Vector3 wxx() const; - Vector3 xyx() const; - Vector3 yyx() const; - Vector3 zyx() const; - Vector3 wyx() const; - Vector3 xzx() const; - Vector3 yzx() const; - Vector3 zzx() const; - Vector3 wzx() const; - Vector3 xwx() const; - Vector3 ywx() const; - Vector3 zwx() const; - Vector3 wwx() const; - Vector3 xxy() const; - Vector3 yxy() const; - Vector3 zxy() const; - Vector3 wxy() const; - Vector3 xyy() const; - Vector3 yyy() const; - Vector3 zyy() const; - Vector3 wyy() const; - Vector3 xzy() const; - Vector3 yzy() const; - Vector3 zzy() const; - Vector3 wzy() const; - Vector3 xwy() const; - Vector3 ywy() const; - Vector3 zwy() const; - Vector3 wwy() const; - Vector3 xxz() const; - Vector3 yxz() const; - Vector3 zxz() const; - Vector3 wxz() const; - Vector3 xyz() const; - Vector3 yyz() const; - Vector3 zyz() const; - Vector3 wyz() const; - Vector3 xzz() const; - Vector3 yzz() const; - Vector3 zzz() const; - Vector3 wzz() const; - Vector3 xwz() const; - Vector3 ywz() const; - Vector3 zwz() const; - Vector3 wwz() const; - Vector3 xxw() const; - Vector3 yxw() const; - Vector3 zxw() const; - Vector3 wxw() const; - Vector3 xyw() const; - Vector3 yyw() const; - Vector3 zyw() const; - Vector3 wyw() const; - Vector3 xzw() const; - Vector3 yzw() const; - Vector3 zzw() const; - Vector3 wzw() const; - Vector3 xww() const; - Vector3 yww() const; - Vector3 zww() const; - Vector3 www() const; - - // 4-char swizzles - - Vector4 xxxx() const; - Vector4 yxxx() const; - Vector4 zxxx() const; - Vector4 wxxx() const; - Vector4 xyxx() const; - Vector4 yyxx() const; - Vector4 zyxx() const; - Vector4 wyxx() const; - Vector4 xzxx() const; - Vector4 yzxx() const; - Vector4 zzxx() const; - Vector4 wzxx() const; - Vector4 xwxx() const; - Vector4 ywxx() const; - Vector4 zwxx() const; - Vector4 wwxx() const; - Vector4 xxyx() const; - Vector4 yxyx() const; - Vector4 zxyx() const; - Vector4 wxyx() const; - Vector4 xyyx() const; - Vector4 yyyx() const; - Vector4 zyyx() const; - Vector4 wyyx() const; - Vector4 xzyx() const; - Vector4 yzyx() const; - Vector4 zzyx() const; - Vector4 wzyx() const; - Vector4 xwyx() const; - Vector4 ywyx() const; - Vector4 zwyx() const; - Vector4 wwyx() const; - Vector4 xxzx() const; - Vector4 yxzx() const; - Vector4 zxzx() const; - Vector4 wxzx() const; - Vector4 xyzx() const; - Vector4 yyzx() const; - Vector4 zyzx() const; - Vector4 wyzx() const; - Vector4 xzzx() const; - Vector4 yzzx() const; - Vector4 zzzx() const; - Vector4 wzzx() const; - Vector4 xwzx() const; - Vector4 ywzx() const; - Vector4 zwzx() const; - Vector4 wwzx() const; - Vector4 xxwx() const; - Vector4 yxwx() const; - Vector4 zxwx() const; - Vector4 wxwx() const; - Vector4 xywx() const; - Vector4 yywx() const; - Vector4 zywx() const; - Vector4 wywx() const; - Vector4 xzwx() const; - Vector4 yzwx() const; - Vector4 zzwx() const; - Vector4 wzwx() const; - Vector4 xwwx() const; - Vector4 ywwx() const; - Vector4 zwwx() const; - Vector4 wwwx() const; - Vector4 xxxy() const; - Vector4 yxxy() const; - Vector4 zxxy() const; - Vector4 wxxy() const; - Vector4 xyxy() const; - Vector4 yyxy() const; - Vector4 zyxy() const; - Vector4 wyxy() const; - Vector4 xzxy() const; - Vector4 yzxy() const; - Vector4 zzxy() const; - Vector4 wzxy() const; - Vector4 xwxy() const; - Vector4 ywxy() const; - Vector4 zwxy() const; - Vector4 wwxy() const; - Vector4 xxyy() const; - Vector4 yxyy() const; - Vector4 zxyy() const; - Vector4 wxyy() const; - Vector4 xyyy() const; - Vector4 yyyy() const; - Vector4 zyyy() const; - Vector4 wyyy() const; - Vector4 xzyy() const; - Vector4 yzyy() const; - Vector4 zzyy() const; - Vector4 wzyy() const; - Vector4 xwyy() const; - Vector4 ywyy() const; - Vector4 zwyy() const; - Vector4 wwyy() const; - Vector4 xxzy() const; - Vector4 yxzy() const; - Vector4 zxzy() const; - Vector4 wxzy() const; - Vector4 xyzy() const; - Vector4 yyzy() const; - Vector4 zyzy() const; - Vector4 wyzy() const; - Vector4 xzzy() const; - Vector4 yzzy() const; - Vector4 zzzy() const; - Vector4 wzzy() const; - Vector4 xwzy() const; - Vector4 ywzy() const; - Vector4 zwzy() const; - Vector4 wwzy() const; - Vector4 xxwy() const; - Vector4 yxwy() const; - Vector4 zxwy() const; - Vector4 wxwy() const; - Vector4 xywy() const; - Vector4 yywy() const; - Vector4 zywy() const; - Vector4 wywy() const; - Vector4 xzwy() const; - Vector4 yzwy() const; - Vector4 zzwy() const; - Vector4 wzwy() const; - Vector4 xwwy() const; - Vector4 ywwy() const; - Vector4 zwwy() const; - Vector4 wwwy() const; - Vector4 xxxz() const; - Vector4 yxxz() const; - Vector4 zxxz() const; - Vector4 wxxz() const; - Vector4 xyxz() const; - Vector4 yyxz() const; - Vector4 zyxz() const; - Vector4 wyxz() const; - Vector4 xzxz() const; - Vector4 yzxz() const; - Vector4 zzxz() const; - Vector4 wzxz() const; - Vector4 xwxz() const; - Vector4 ywxz() const; - Vector4 zwxz() const; - Vector4 wwxz() const; - Vector4 xxyz() const; - Vector4 yxyz() const; - Vector4 zxyz() const; - Vector4 wxyz() const; - Vector4 xyyz() const; - Vector4 yyyz() const; - Vector4 zyyz() const; - Vector4 wyyz() const; - Vector4 xzyz() const; - Vector4 yzyz() const; - Vector4 zzyz() const; - Vector4 wzyz() const; - Vector4 xwyz() const; - Vector4 ywyz() const; - Vector4 zwyz() const; - Vector4 wwyz() const; - Vector4 xxzz() const; - Vector4 yxzz() const; - Vector4 zxzz() const; - Vector4 wxzz() const; - Vector4 xyzz() const; - Vector4 yyzz() const; - Vector4 zyzz() const; - Vector4 wyzz() const; - Vector4 xzzz() const; - Vector4 yzzz() const; - Vector4 zzzz() const; - Vector4 wzzz() const; - Vector4 xwzz() const; - Vector4 ywzz() const; - Vector4 zwzz() const; - Vector4 wwzz() const; - Vector4 xxwz() const; - Vector4 yxwz() const; - Vector4 zxwz() const; - Vector4 wxwz() const; - Vector4 xywz() const; - Vector4 yywz() const; - Vector4 zywz() const; - Vector4 wywz() const; - Vector4 xzwz() const; - Vector4 yzwz() const; - Vector4 zzwz() const; - Vector4 wzwz() const; - Vector4 xwwz() const; - Vector4 ywwz() const; - Vector4 zwwz() const; - Vector4 wwwz() const; - Vector4 xxxw() const; - Vector4 yxxw() const; - Vector4 zxxw() const; - Vector4 wxxw() const; - Vector4 xyxw() const; - Vector4 yyxw() const; - Vector4 zyxw() const; - Vector4 wyxw() const; - Vector4 xzxw() const; - Vector4 yzxw() const; - Vector4 zzxw() const; - Vector4 wzxw() const; - Vector4 xwxw() const; - Vector4 ywxw() const; - Vector4 zwxw() const; - Vector4 wwxw() const; - Vector4 xxyw() const; - Vector4 yxyw() const; - Vector4 zxyw() const; - Vector4 wxyw() const; - Vector4 xyyw() const; - Vector4 yyyw() const; - Vector4 zyyw() const; - Vector4 wyyw() const; - Vector4 xzyw() const; - Vector4 yzyw() const; - Vector4 zzyw() const; - Vector4 wzyw() const; - Vector4 xwyw() const; - Vector4 ywyw() const; - Vector4 zwyw() const; - Vector4 wwyw() const; - Vector4 xxzw() const; - Vector4 yxzw() const; - Vector4 zxzw() const; - Vector4 wxzw() const; - Vector4 xyzw() const; - Vector4 yyzw() const; - Vector4 zyzw() const; - Vector4 wyzw() const; - Vector4 xzzw() const; - Vector4 yzzw() const; - Vector4 zzzw() const; - Vector4 wzzw() const; - Vector4 xwzw() const; - Vector4 ywzw() const; - Vector4 zwzw() const; - Vector4 wwzw() const; - Vector4 xxww() const; - Vector4 yxww() const; - Vector4 zxww() const; - Vector4 wxww() const; - Vector4 xyww() const; - Vector4 yyww() const; - Vector4 zyww() const; - Vector4 wyww() const; - Vector4 xzww() const; - Vector4 yzww() const; - Vector4 zzww() const; - Vector4 wzww() const; - Vector4 xwww() const; - Vector4 ywww() const; - Vector4 zwww() const; - Vector4 wwww() const; - -}; - - -//---------------------------------------------------------------------------- -inline Vector4::Vector4() { - x = y = z = w = 0; -} - -//---------------------------------------------------------------------------- - -inline Vector4::Vector4 (float fX, float fY, float fZ, float fW) { - x = fX; - y = fY; - z = fZ; - w = fW; -} - -//---------------------------------------------------------------------------- -inline Vector4::Vector4 (float afCoordinate[4]) { - x = afCoordinate[0]; - y = afCoordinate[1]; - z = afCoordinate[2]; - w = afCoordinate[3]; -} - -//---------------------------------------------------------------------------- -inline Vector4::Vector4(const Vector4& rkVector) { - x = rkVector.x; - y = rkVector.y; - z = rkVector.z; - w = rkVector.w; -} -//---------------------------------------------------------------------------- -inline Vector4::Vector4(const Vector3& rkVector, float fW) { - x = rkVector.x; - y = rkVector.y; - z = rkVector.z; - w = fW; -} - -//---------------------------------------------------------------------------- -inline float& Vector4::operator[] (int i) { - return ((float*)this)[i]; -} - -//---------------------------------------------------------------------------- -inline const float& Vector4::operator[] (int i) const { - return ((float*)this)[i]; -} - -//---------------------------------------------------------------------------- -inline Vector4::operator float* () { - return (float*)this; -} - -inline Vector4::operator const float* () const { - return (float*)this; -} - -//---------------------------------------------------------------------------- -inline Vector4& Vector4::operator= (const Vector4& rkVector) { - x = rkVector.x; - y = rkVector.y; - z = rkVector.z; - w = rkVector.w; - return *this; -} - -//---------------------------------------------------------------------------- -inline bool Vector4::operator== (const Vector4& rkVector) const { - return ( (x == rkVector.x) && (y == rkVector.y) && (z == rkVector.z) && (w == rkVector.w)); -} - -//---------------------------------------------------------------------------- -inline bool Vector4::operator!= (const Vector4& rkVector) const { - return ( x != rkVector.x || y != rkVector.y || z != rkVector.z || w != rkVector.w); -} - -//---------------------------------------------------------------------------- -inline Vector4 Vector4::operator+ (const Vector4& rkVector) const { - return Vector4(x + rkVector.x, y + rkVector.y, z + rkVector.z, w + rkVector.w); -} - -//---------------------------------------------------------------------------- -inline Vector4 Vector4::operator- (const Vector4& rkVector) const { - return Vector4(x - rkVector.x, y - rkVector.y, z - rkVector.z, w - rkVector.w); -} - -//---------------------------------------------------------------------------- -inline Vector4 Vector4::operator* (float fScalar) const { - return Vector4(fScalar*x, fScalar*y, fScalar*z, fScalar*w); -} - -//---------------------------------------------------------------------------- -inline Vector4 Vector4::operator- () const { - return Vector4( -x, -y, -z, -w); -} - -//---------------------------------------------------------------------------- -inline Vector4& Vector4::operator+= (const Vector4& rkVector) { - x += rkVector.x; - y += rkVector.y; - z += rkVector.z; - w += rkVector.w; - return *this; -} - -//---------------------------------------------------------------------------- -inline Vector4& Vector4::operator-= (const Vector4& rkVector) { - x -= rkVector.x; - y -= rkVector.y; - z -= rkVector.z; - w -= rkVector.w; - return *this; -} - -//---------------------------------------------------------------------------- - -inline Vector4 Vector4::lerp(const Vector4& v, float alpha) const { - return (*this) + (v - *this) * alpha; -} - - -//---------------------------------------------------------------------------- -inline Vector4& Vector4::operator*= (float fScalar) { - x *= fScalar; - y *= fScalar; - z *= fScalar; - w *= fScalar; - return *this; -} - - -//---------------------------------------------------------------------------- -inline float Vector4::dot(const Vector4& rkVector) const { - return x*rkVector.x + y*rkVector.y + z*rkVector.z + w*rkVector.w; -} - -//---------------------------------------------------------------------------- -inline Vector4 Vector4::min(const Vector4 &v) const { - return Vector4(G3D::min(v.x, x), G3D::min(v.y, y), G3D::min(v.z, z), G3D::min(v.w, w)); -} - -//---------------------------------------------------------------------------- -inline Vector4 Vector4::max(const Vector4 &v) const { - return Vector4(G3D::max(v.x, x), G3D::max(v.y, y), G3D::max(v.z, z), G3D::max(v.w, w)); -} - -//---------------------------------------------------------------------------- -inline bool Vector4::isZero() const { - return (x == 0.0f) && (y == 0.0f) && (z == 0.0f) && (w == 0.0f); -} - -//---------------------------------------------------------------------------- - -inline bool Vector4::isFinite() const { - return G3D::isFinite(x) && G3D::isFinite(y) && G3D::isFinite(z) && G3D::isFinite(w); -} - -//---------------------------------------------------------------------------- - -inline bool Vector4::isUnit() const { - return squaredLength() == 1.0; -} - -//---------------------------------------------------------------------------- - -inline float Vector4::length() const { - return sqrtf(squaredLength()); -} - -//---------------------------------------------------------------------------- - -inline float Vector4::squaredLength() const { - return x * x + y * y + z * z + w * w; -} - -} - -template <> struct HashTrait { - static size_t hashCode(const G3D::Vector4& key) { return key.hashCode(); } -}; - - -template<> struct PositionTrait { - static void getPosition(const G3D::Vector4& v, G3D::Vector3& p) { p = v.xyz(); } -}; - -inline G3D::Vector4 operator* (float s, const G3D::Vector4& v) { - return v * s; -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/Vector4int8.h b/externals/g3dlite/G3D.lib/include/G3D/Vector4int8.h deleted file mode 100644 index 8476a2d008b..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/Vector4int8.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - @file Vector4int8.h - - Homogeneous vector class. - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-02-09 - @edited 2007-02-09 - - Copyright 2000-2007, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_VECTOR4INT8_H -#define G3D_VECTOR4INT8_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" - -namespace G3D { - -class Vector3; -class Vector4; - -/** - Homogeneous vector stored efficiently in four signed int8s. - - */ -class Vector4int8 { -private: - // Hidden operators - bool operator<(const Vector4int8&) const; - bool operator>(const Vector4int8&) const; - bool operator<=(const Vector4int8&) const; - bool operator>=(const Vector4int8&) const; - - - /** For fast operations, treat this packed data structure as - an int32 */ - inline uint32& asInt32() { - return *reinterpret_cast(this); - } - - inline const uint32& asInt32() const { - return *reinterpret_cast(this); - } - -public: - // construction - inline Vector4int8() : x(0), y(0), z(0), w(0) {} - - /** Multiplies the source by 127 and clamps to (-128, 127) when converting */ - Vector4int8(const Vector4& source); - - /** Multiplies the source by 127 and clamps to (-128, 127) when converting */ - Vector4int8(const Vector3& source, int8 w); - - inline Vector4int8(int8 x, int8 y, int8 z, int8 w) : x(x), y(y), z(z), w(w) {} - - Vector4int8(class BinaryInput& b); - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); - - // coordinates - int8 x, y, z, w; - - inline operator int8* () { - return reinterpret_cast(this); - } - - inline operator const int8* () const { - return reinterpret_cast(this); - } - - // access vector V as V[0] = V.x, V[1] = V.y, V[2] = V.z, etc. - // - // WARNING. These member functions rely on - // (1) Vector4int8 not having virtual functions - // (2) the data packed in a 4*sizeof(int8) memory block - inline int8& operator[] (int i) { - debugAssert(i >= 0 && i <= 4); - return ((int8*)this)[i]; - } - - const int8& operator[] (int i) const { - debugAssert(i >= 0 && i <= 4); - return ((const int8*)this)[i]; - } - - // assignment and comparison - Vector4int8& operator= (const Vector4int8& other) { - asInt32() = other.asInt32(); - return *this; - } - - inline bool operator== (const Vector4int8& other) const { - return asInt32() == other.asInt32(); - } - - inline bool operator!= (const Vector4int8& other) const { - return ! (*this == other); - } - - inline unsigned int hashCode() const { - return asInt32(); - } -}; - -} // namespace G3D - - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/WeakCache.h b/externals/g3dlite/G3D.lib/include/G3D/WeakCache.h deleted file mode 100644 index 87988aaf5cb..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/WeakCache.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - @file WeakCache.h - - @maintainer Morgan McGuire, graphics3d.com - - @created 2007-05-16 - @edited 2007-05-16 - - Copyright 2000-2007, Morgan McGuire. - All rights reserved. - */ -#ifndef G3D_WEAKCACHE_H -#define G3D_WEAKCACHE_H - -#include "G3D/ReferenceCount.h" -#include "G3D/Table.h" - -namespace G3D { - -/** - A cache that does not prevent its members from being garbage collected. - Useful to avoid loading or computing an expression twice. Useful - for memoization and dynamic programming. - - Maintains a table of weak pointers. Weak pointers do not prevent - an object from being garbage collected. If the object is garbage - collected, the cache removes its reference. - - There are no "contains" or "iterate" methods because elements can be - flushed from the cache at any time if they are garbage collected. - - Example: -
-      WeakCache textureCache;
-
-      TextureRef loadTexture(std::string s) {
-          TextureRef t = textureCache[s];
-
-          if (t.isNull()) {
-              t = Texture::fromFile(s);
-              textureCache.set(s, t);
-          }
-
-          return t;
-      }
-      
-      
-    
- */ -template -class WeakCache { - typedef WeakReferenceCountedPointer ValueWeakRef; - -private: - - Table table; - -public: - /** - Returns NULL if the object is not in the cache - */ - ValueRef operator[](const Key& k) { - if (table.containsKey(k)) { - ValueWeakRef w = table[k]; - ValueRef s = w.createStrongPtr(); - if (s.isNull()) { - // This object has been collected; clean out its key - table.remove(k); - } - return s; - } else { - return NULL; - } - } - - void set(const Key& k, ValueRef v) { - table.set(k, v); - } - - /** Removes k from the cache or does nothing if it is not currently in the cache.*/ - void remove(const Key& k) { - if (table.containsKey(k)) { - table.remove(k); - } - } -}; - -} -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/WrapMode.h b/externals/g3dlite/G3D.lib/include/G3D/WrapMode.h deleted file mode 100644 index f97e68d6910..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/WrapMode.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - @file WrapMode.h - - @maintainer Morgan McGuire, graphics3d.com - - @created 2007-04-17 - @edited 2007-04-17 - - Copyright 2000-2007, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_WRAPMODE_H -#define G3D_WRAPMODE_H - -#include "G3D/platform.h" -#include "G3D/enumclass.h" - -#ifdef IGNORE -# undef IGNORE -#endif -#ifdef ZERO -# undef ZERO -#endif -#ifdef ERROR -# undef ERROR -#endif - -namespace G3D { - -/** - Describes the behavior of G3D::Texture, G3D::Map2D, G3D::Image3, etc. when accessing an out-of-bounds - pixel. Not all classes support all modes. - - Refer to these as scoped enums, e.g., WrapMode m = WrapMode::CLAMP;. - - WrapMode::IGNORE silently discards attempts to write to out - of bounds locations and returns an undefined value for reading - from out of bounds locations. - - WrapMode::ERROR generates an error when the - pixel indices are out of bounds - - WrapMode::CLAMP makes out of bounds pixels equal to the last in-range pixel along that dimension. - - WrapMode::TILE computes out of bounds pixels modulo the dimension - - WrapMode::ZERO treats out of bounds values as the zero value, which varies in definition - according to the class used. For example, with a G3D::Texture, ZERO = Color4(0,0,0,0). - - Uses the "Intelligent Enum" design pattern - http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4001/ - */ -class WrapMode { -public: - /** Don't use this enum; use WrapMode instances instead. */ - enum Value { - CLAMP, - TILE, - ZERO, - IGNORE, - ERROR - }; - -private: - - Value value; - -public: - - G3D_DECLARE_ENUM_CLASS_METHODS(WrapMode); - -}; - -} // namespace G3D - -G3D_DECLARE_ENUM_CLASS_HASHCODE(G3D::WrapMode); - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/debug.h b/externals/g3dlite/G3D.lib/include/G3D/debug.h deleted file mode 100644 index a96babc6fa0..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/debug.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - @file debug.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2001-08-26 - @edited 2006-02-16 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. -*/ - -#ifndef G3D_DEBUG_H -#define G3D_DEBUG_H - -#include "G3D/platform.h" -#ifdef _MSC_VER - #include -#endif - -#include "G3D/debugPrintf.h" -#include "G3D/debugAssert.h" - -namespace G3D { - -#ifdef _MSC_VER - // Turn off 64-bit warnings -# pragma warning(push) -# pragma warning( disable : 4312) -# pragma warning( disable : 4267) -# pragma warning( disable : 4311) -#endif - - -/** - Useful for debugging purposes. - */ -inline bool isValidHeapPointer(const void* x) { - #ifdef _MSC_VER - return - (x != (void*)0xcccccccc) && (x != (void*)0xdeadbeef) && (x != (void*)0xfeeefeee); - #else - return x != NULL; - #endif -} - -/** - Returns true if the pointer is likely to be - a valid pointer (instead of an arbitrary number). - Useful for debugging purposes. - */ -inline bool isValidPointer(const void* x) { - #ifdef _MSC_VER - return x != ((void*)0xcccccccc) && (x != (void*)0xdeadbeef) && (x != (void*)0xfeeefeee); - #else - return x != NULL; - #endif -} - -#ifdef _MSC_VER -# pragma warning(pop) -#endif - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/debugAssert.h b/externals/g3dlite/G3D.lib/include/G3D/debugAssert.h deleted file mode 100644 index f9b5bea4e9f..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/debugAssert.h +++ /dev/null @@ -1,236 +0,0 @@ -/** - @file debugAssert.h - - debugAssert(expression); - debugAssertM(expression, message); - - @cite - John Robbins, Microsoft Systems Journal Bugslayer Column, Feb 1999. - - http://msdn.microsoft.com/library/periodic/period99/feb99_BUGSLAYE_BUGSLAYE.htm - - @cite - Douglas Cox, An assert() Replacement, Code of The Day, flipcode, Sept 19, 2000 - - http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-AssertReplace&forum=cotd&id=-1 - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2001-08-26 - @edited 2006-01-12 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_DEBUGASSERT_H -#define G3D_DEBUGASSERT_H - -#include -#include "G3D/platform.h" - -#include - -#ifdef _MSC_VER -// conditional expression is constant -# pragma warning (disable : 4127) -#endif - -#ifdef G3D_LINUX - // Needed so we can define a global display - // pointer for debugAssert. - #include - #include - #include -#endif - -#ifdef G3D_OSX - // Need this for DebugStr() - #import -#endif - - -/** - @def debugBreak() - - Break at the current location (i.e. don't push a procedure stack frame - before breaking). - */ - -/** - @def debugAssert(exp) - Breaks if the expression is false. If G3D_DEBUG_NOGUI is defined, prompts at - the console, otherwise pops up a dialog. The user may then break (debug), - ignore, ignore always, or halt the program. - - The assertion is also posted to the clipboard under Win32. - */ - -/** - @def debugAssertM(exp, msg) - Breaks if the expression is false and displays a message. If G3D_DEBUG_NOGUI - is defined, prompts at the console, otherwise pops up a dialog. The user may - then break (debug), ignore, ignore always, or halt the program. - - The assertion is also posted to the clipboard under Win32. - */ - -namespace G3D { -typedef bool (*AssertionHook)( - const char* _expression, - const std::string& message, - const char* filename, - int lineNumber, - bool& ignoreAlways, - bool useGuiPrompt); - -/** - Allows customization of the global function invoked when a debugAssert fails. - The initial value is G3D::_internal::_handleDebugAssert_. G3D will invoke - rawBreak if the hook returns true. If NULL, assertions are not handled. -*/ -void setAssertionHook(AssertionHook hook); - -AssertionHook assertionHook(); - -/** - Called by alwaysAssertM in case of failure in release mode. If returns - true then the program exits with -1 (you can replace this with your own - version that throws an exception or has other failure modes). - */ -void setFailureHook(AssertionHook hook); -AssertionHook failureHook(); - -namespace _internal { - extern AssertionHook _debugHook; - extern AssertionHook _failureHook; -} // internal -} // G3D - -/** - @def __debugPromptShowDialog__ - @internal - */ - -#ifdef G3D_DEBUG - -# if defined(_MSC_VER) -# define rawBreak() ::DebugBreak(); -# elif defined(__i386__) - // gcc on intel -# define rawBreak() __asm__ __volatile__ ( "int $3" ); -# else - // some other gcc -# define rawBreak() ::abort() -# endif -// old mac code: -//# define rawBreak() DebugStr((const unsigned char*)("\nG3D: Invoking breakpoint in debugger.")); /* XCode must be set to break on Debugger()/DebugStr() */ - - -# define debugBreak() G3D::_internal::_releaseInputGrab_(); rawBreak(); G3D::_internal::_restoreInputGrab_(); -# define debugAssert(exp) debugAssertM(exp, "Debug assertion failure") - - #ifdef G3D_DEBUG_NOGUI - #define __debugPromptShowDialog__ false - #else - #define __debugPromptShowDialog__ true - #endif - - #define debugAssertM(exp, message) do { \ - static bool __debugAssertIgnoreAlways__ = false; \ - if (!__debugAssertIgnoreAlways__ && !(exp)) { \ - G3D::_internal::_releaseInputGrab_(); \ - if ((G3D::_internal::_debugHook != NULL) && \ - G3D::_internal::_debugHook((const char*)(#exp), message, __FILE__, __LINE__, __debugAssertIgnoreAlways__, __debugPromptShowDialog__)) { \ - rawBreak(); \ - } \ - G3D::_internal::_restoreInputGrab_(); \ - } \ - } while (0) - - #define alwaysAssertM debugAssertM - -#else // Release - #ifdef G3D_DEBUG_NOGUI - #define __debugPromptShowDialog__ false - #else - #define __debugPromptShowDialog__ true - #endif - - // In the release build, just define away assertions. - #define rawBreak() do {} while (0) - #define debugAssert(exp) do {} while (0) - #define debugAssertM(exp, message) do {} while (0) - #define debugBreak() do {} while (0) - - // But keep the 'always' assertions - #define alwaysAssertM(exp, message) { \ - static bool __alwaysAssertIgnoreAlways__ = false; \ - if (!__alwaysAssertIgnoreAlways__ && !(exp)) { \ - G3D::_internal::_releaseInputGrab_(); \ - if ((G3D::_internal::_failureHook != NULL) && \ - G3D::_internal::_failureHook(#exp, message, __FILE__, __LINE__, __alwaysAssertIgnoreAlways__, __debugPromptShowDialog__)) { \ - ::exit(-1); \ - } \ - G3D::_internal::_restoreInputGrab_(); \ - } \ - } - -#endif // if debug - - - -namespace G3D { namespace _internal { - -#ifdef G3D_LINUX - /** - A pointer to the X11 display. Initially NULL. If set to a - non-null value (e.g. by SDLWindow), debugAssert attempts to use - this display to release the mouse/input grab when an assertion - fails. - */ - extern Display* x11Display; - - /** - A pointer to the X11 window. Initially NULL. If set to a - non-null value (e.g. by SDLWindow), debugAssert attempts to use - this window to release the mouse/input grab when an assertion - fails. - */ - extern Window x11Window; -#endif - -/** - Pops up an assertion dialog or prints an assertion - - ignoreAlways - return result of pressing the ignore button. - useGuiPrompt - if true, shows a dialog - */ -bool _handleDebugAssert_( - const char* expression, - const std::string& message, - const char* filename, - int lineNumber, - bool& ignoreAlways, - bool useGuiPrompt); - -bool _handleErrorCheck_( - const char* expression, - const std::string& message, - const char* filename, - int lineNumber, - bool& ignoreAlways, - bool useGuiPrompt); - -/** Attempts to give the user back their mouse and keyboard if they - were locked to the current window. - @internal*/ -void _releaseInputGrab_(); - -/** Attempts to restore the state before _releaseInputGrab_. - @internal*/ -void _restoreInputGrab_(); - -}; }; // namespace - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/debugPrintf.h b/externals/g3dlite/G3D.lib/include/G3D/debugPrintf.h deleted file mode 100644 index bc3315c8a6d..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/debugPrintf.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - @file debugPrintf.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2001-08-26 - @edited 2007-07-20 - - Copyright 2000-2007, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_DEBUGPRINTF_H -#define G3D_DEBUGPRINTF_H - -#include "G3D/platform.h" -#include -#include -#include "G3D/format.h" -#include - -namespace G3D { - -typedef void (*ConsolePrintHook)(const std::string&); - -namespace _internal { - extern ConsolePrintHook _consolePrintHook; -} - -/** Called by consolePrintf after the log and terminal have been written to. - Used by GConsole to intercept printing routines.*/ -void setConsolePrintHook(ConsolePrintHook h); - -ConsolePrintHook consolePrintHook(); - -/** - Sends output to the log and to the last GConsole instantiated. - - Guarantees that the output has been flushed by the time the routine - returns. - @sa G3D::logPrintf, G3D::screenPrintf - @return The string that was printed - */ -std::string __cdecl consolePrintf(const char* fmt ...) G3D_CHECK_PRINTF_ARGS; -std::string consolePrint(const std::string&); - -/** - Under visual studio, appears in the VS debug pane. - On unix-based operating systems the output is sent to stderr. - - Also sends output to the console (G3D::consolePrintf) if there is a consolePrintHook, - and log (G3D::logPrintf), and flushes before returning. - - @return The string that was printed -*/ -std::string __cdecl debugPrintf(const char* fmt ...) G3D_CHECK_PRINTF_ARGS; -std::string debugPrint(const std::string&); - -} // namespace G3D - -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/enumclass.h b/externals/g3dlite/G3D.lib/include/G3D/enumclass.h deleted file mode 100644 index 7e7bc3f6ac3..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/enumclass.h +++ /dev/null @@ -1,141 +0,0 @@ -/** - @file G3D/enumclass.h - - @maintainer Morgan McGuire, morgan@graphics3d.com - @created 2007-01-27 - @edited 2007-07-20 -*/ -#ifndef G3D_ENUMCLASS_H -#define G3D_ENUMCLASS_H - -#include "G3D/Table.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - -/** - Creates a series of methods that turn a class into a scoped enumeration. - Uses the "Intelligent Enum" design pattern - http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4001/ - - Enum classes are initialized to their zero value by default. - - See GLG3D/GKey.h for an example. - */ -#define G3D_DECLARE_ENUM_CLASS_METHODS(Classname)\ - inline Classname(char v) : value((Value)v) {}\ -\ - inline Classname() : value((Value)0) {}\ -\ - inline Classname(const Value v) : value(v) {}\ -\ - explicit inline Classname(int v) : value((Value)v) {}\ -\ - /** Support cast back to the Value type, which is needed to allow implicit assignment inside unions. */\ - /*inline operator Value() const { - return value; - }*/\ -\ - inline operator int() const {\ - return (int)value;\ - }\ -\ - inline bool operator== (const Classname other) const {\ - return value == other.value;\ - }\ -\ - inline bool operator== (const Classname::Value other) const {\ - return value == other;\ - }\ -\ - inline bool operator!= (const Classname other) const {\ - return value != other.value;\ - }\ -\ - inline bool operator!= (const Classname::Value other) const {\ - return value != other;\ - }\ -\ - inline bool operator< (const Classname other) const {\ - return value < other.value;\ - }\ -\ - inline bool operator> (const Classname other) const {\ - return value > other.value;\ - }\ -\ - inline bool operator>= (const Classname other) const {\ - return value >= other.value;\ - }\ -\ - inline bool operator<= (const Classname other) const {\ - return value <= other.value;\ - }\ -\ - inline bool operator< (const Value other) const {\ - return value < other;\ - }\ -\ - inline bool operator> (const Value other) const {\ - return value > other;\ - }\ -\ - inline bool operator<= (const Value other) const {\ - return value <= other;\ - }\ -\ - inline bool operator>= (const Value other) const {\ - return value >= other;\ - }\ -\ - inline Classname& operator-- () {\ - value = (Value)((int)value - 1);\ - return *this;\ - }\ -\ - inline Classname& operator++ () {\ - value = (Value)((int)value + 1);\ - return *this;\ - }\ -\ - inline Classname& operator+= (const int x) {\ - value = (Value)((int)value + x);\ - return *this;\ - }\ -\ - inline Classname& operator-= (const int x) {\ - value = (Value)((int)value - x);\ - return *this;\ - }\ -\ - inline Classname operator+ (const int x) const {\ - return Classname((int)value + x);\ - }\ -\ - inline Classname operator- (const int x) const {\ - return Classname((int)value - x);\ - }\ -\ - inline unsigned int hashCode() const {\ - return (unsigned int)value;\ - }\ -\ - void serialize(BinaryOutput& b) const {\ - b.writeInt32(value);\ - }\ -\ - void deserialize(BinaryInput& b) {\ - value = (Value)b.readInt32();\ - } - -#define G3D_DECLARE_ENUM_CLASS_HASHCODE(Classname)\ -template <> struct HashTrait \ -{ \ - static size_t hashCode(Classname::Value key) { return static_cast(key); } \ -}; \ - \ -template <> struct HashTrait \ -{ \ - static size_t hashCode(Classname key) { return static_cast(key.hashCode()); } \ -}; - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/fileutils.h b/externals/g3dlite/G3D.lib/include/G3D/fileutils.h deleted file mode 100644 index ead20720870..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/fileutils.h +++ /dev/null @@ -1,246 +0,0 @@ -/** - @file fileutils.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @author 2002-06-06 - @edited 2007-01-18 - - Copyright 2000-2007, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_FILEUTILS_H -#define G3D_FILEUTILS_H - -#include "G3D/platform.h" -#include -#include -#include "G3D/Array.h" -#include "G3D/Set.h" -#include "G3D/g3dmath.h" - -#ifdef G3D_WIN32 -// For chdir, mkdir, etc. -# include -#endif - -namespace G3D { - - namespace _internal { - extern Set currentFilesUsed; - } - -/** Returns all the files used by G3D and GLG3D during the current execution. */ -Array filesUsed(); - -std::string readWholeFile( - const std::string& filename); - - -/** Reads from a zip file and decompresses the desired contents - into memory. Does not support recursive zip calls (i.e. a .zip - stored within another .zip) - - @param file the path, of the format C:\...\something.zip\...\desiredfile.ext - @param data a pointer to the memory where the file will be stored - @param length the size of the file decompressed to memory */ -void zipRead(const std::string& file, - void*& data, - size_t& length); - - -/** Closes the contents of a zip file that had been decompressed to - memory. Must be called in tandem with zipRead() to avoid memory - leaks. - - @param data the pointer to the decompressed file in memory */ -void zipClose(void* data); - - -/** - @param flush If true (default), the file is ready for reading as soon - as the function returns. If false, the function returns immediately and - writes the file in the background. - */ -void writeWholeFile( - const std::string& filename, - const std::string& str, - bool flush = true); - -/** - Creates the directory (which may optionally end in a /) - and any parents needed to reach it. - */ -void createDirectory( - const std::string& dir); - -/** - Fully qualifies a filename. The filename may contain wildcards, - in which case the wildcards will be preserved in the returned value. - */ -std::string resolveFilename(const std::string& filename); - -/** - Appends all files matching filespec to the files array. The names - will not contain paths unless includePath == true. These may be - relative to the current directory unless the filespec is fully qualified - (can be done with resolveFilename). - Wildcards can only appear to the right of the last slash in filespec. - Works with .zip files used as paths, if filespec is passed in the form - C:\...\something.zip\* Does not work recursively with zipfiles (a - .zip within a .zip will not work) - */ -void getFiles( - const std::string& filespec, - Array& files, - bool includePath = false); - -/** - Appends all directories matching filespec to the files array. The names - will not contain paths unless includePath == true. These may be - relative to the current directory unless the filespec is fully qualified - (can be done with resolveFilename). - Does not append special directories "." or "..". - Works with .zip files used as paths, if filespec is passed in the form - C:\...\something.zip\* Does not work recursively with zipfiles (a - .zip within a .zip will not work) - */ -void getDirs( - const std::string& filespec, - Array& files, - bool includePath = false); - - -/** Returns true if the specified path exists and is a directory */ -bool isDirectory(const std::string& filespec); - - -/** Returns true if the specified filename exists and is a zipfile */ -bool isZipfile(const std::string& filename); - - -/** Returns the length of the file. If - filename specifies a path that contains a zipfile, but the - contents within are specified correctly, returns the - uncompressed size of the requested file. Returns -1 if - the file does not exist. - - @param filename the path to test, may contain .zip -*/ -int64 fileLength(const std::string& filename); - -/** - Copies the file - */ -void copyFile( - const std::string& source, - const std::string& dest); - -/** Returns a temporary file that is open for read/write access. This - tries harder than the ANSI tmpfile, so it may succeed when that fails. */ -FILE* createTempFile(); - -/** - Returns true if the given file (or directory) exists. - - @param filename the path to test. must not end in a trailing slash. - @param lookInZipfiles if the path does not exist, calls zipfileExists() - */ -bool fileExists( - const std::string& filename, - const bool lookInZipfiles = true); - -/** - Returns true if the given file (or directory) exists - within a zipfile. Called if fileExists initially - returns false and the lookInZipfiles flag has been set. - Must not end in a trailing slash. Does not work for recursive - zipfiles (.zips within another .zip) - - @param filename the path to test - @param outZipfile the path to the .zip file - @param outInternalFile the path (within the .zip) where the desired file is located, if valid - - */ -bool zipfileExists( - const std::string& filename, - std::string& outZipfile, - std::string& outInternalFile - ); - -bool zipfileExists(const std::string& filename); - -/** - Parses a filename into four useful pieces. - - Examples: - - c:\a\b\d.e - root = "c:\" - path = "a" "b" - base = "d" - ext = "e" - - /a/b/d.e - root = "/" - path = "a" "b" - base = "d" - ext = "e" - - /a/b - root = "/" - path = "a" - base = "b" - ext = "e" - - */ -void parseFilename( - const std::string& filename, - std::string& drive, - Array& path, - std::string& base, - std::string& ext); - - -/** - Returns the part of the filename that includes the base and ext from - parseFilename (i.e. everything to the right of the path). - */ -std::string filenameBaseExt(const std::string& filename); - -/** - Returns the extension on a filename. - */ -std::string filenameExt(const std::string& filename); - - -/** Returns the portion of a filename to the left of the last period - and to the right of the last slash or colon. - */ -std::string filenameBase(const std::string& filename); - -/** Creates a unique filename base in the current directory using the - specified prefix.*/ -std::string generateFilenameBase(const std::string& prefix = ""); - -/** - Returns the drive (if Win32) and path from a filename, including - a slash if there was one. - filenamePath(f) + filenameBaseExt(f) == f - */ -std::string filenamePath(const std::string& filename); - -/** Returns true if '*' or '?' appears in the string */ -bool filenameContainsWildcards(const std::string& filename); - -/** Returns true if dst does not exist or src is newer than dst. Works on both files and directories. */ -bool fileIsNewer(const std::string& src, const std::string& dst); - -/** Appends file onto dirname, ensuring a / if needed. */ -std::string pathConcat(const std::string& dirname, const std::string& file); - -} // namespace - -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/filter.h b/externals/g3dlite/G3D.lib/include/G3D/filter.h deleted file mode 100644 index 74a32ad01ea..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/filter.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - @file G3D/filter.h - - @author Morgan McGuire, matrix@graphics3d.com - @created 2007-03-01 - @edited 2007-03-01 - - Copyright 2000-2007, Morgan McGuire. - All rights reserved. - */ -#ifndef G3D_FILTER_H -#define G3D_FILTER_H - -#include "G3D/platform.h" -#include "G3D/Array.h" -#include "G3D/g3dmath.h" - -namespace G3D { -/** - Generates a set of 1D gaussian filter coefficients of size N. The coefficients - are centered on element (N-1)/2 and have standard deviation given by std. The coefficients - are normalized such that the sum across coeff is 1.0. - - Matches the results returned by Matlab fspecial('gaussian', [1, N], std) - */ -void gaussian1D(Array& coeff, int N = 5, float std = 0.5f); -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/format.h b/externals/g3dlite/G3D.lib/include/G3D/format.h deleted file mode 100644 index f993a74038f..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/format.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - @file format.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @author 2000-09-09 - @edited 2005-11-03 - - Copyright 2000-2005, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_FORMAT_H -#define G3D_FORMAT_H - -#include "G3D/platform.h" -#include -#include -#include - -namespace G3D { - -/** - Produces a string from arguments of the style of printf. This avoids - problems with buffer overflows when using sprintf and makes it easy - to use the result functionally. This function is fast when the resulting - string is under 160 characters (not including terminator) and slower - when the string is longer. - */ -std::string __cdecl format( - const char* fmt - ...) G3D_CHECK_PRINTF_ARGS; - -/** - Like format, but can be called with the argument list from a ... function. - */ -std::string vformat( - const char* fmt, - va_list argPtr) G3D_CHECK_VPRINTF_ARGS; - - -} // namespace - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/g3dmath.h b/externals/g3dlite/G3D.lib/include/G3D/g3dmath.h deleted file mode 100644 index 0a4f01f11c6..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/g3dmath.h +++ /dev/null @@ -1,810 +0,0 @@ -/** - @file g3dmath.h - - Math util class. - - @maintainer Morgan McGuire, matrix@graphics3d.com - @cite highestBit by Jukka Liimatta - - @created 2001-06-02 - @edited 2006-01-16 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3DMATH_H -#define G3DMATH_H - -#ifdef _MSC_VER -// Disable conditional expression is constant, which occurs incorrectly on inlined functions -# pragma warning (push) -# pragma warning (disable : 4127) -// disable: "C++ exception handler used" -# pragma warning (disable : 4530) -#endif - -#include "G3D/platform.h" -#include -#include -#include -#include - -#ifdef _MSC_VER - // Visual Studio is missing inttypes.h -# ifndef PRId64 -# define PRId64 "I64d" -# endif -#else -#include -#endif - -/*These defines enable functionality introduced with the 1999 ISO C -**standard. They must be defined before the inclusion of math.h to -**engage them. If optimisation is enabled, these functions will be -**inlined. With optimisation switched off, you have to link in the -**maths library using -lm. -*/ - -#define _ISOC9X_SOURCE1 -#define _ISOC99_SOURCE1 -#define __USE_ISOC9X1 -#define __USE_ISOC991 - -#include - -#include "G3D/debug.h" - -#undef min -#undef max - -namespace G3D { - -#ifdef _MSC_VER - -/** - Win32 implementation of the C99 fast rounding routines. - - @cite routines are - Copyright (C) 2001 Erik de Castro Lopo - - Permission to use, copy, modify, distribute, and sell this file for any - purpose is hereby granted without fee, provided that the above copyright - and this permission notice appear in all copies. No representations are - made about the suitability of this software for any purpose. It is - provided "as is" without express or implied warranty. -*/ - -__inline long int lrint (double flt) { - int intgr; - - _asm { - fld flt - fistp intgr - }; - - return intgr; -} - -__inline long int lrintf(float flt) { - int intgr; - - _asm { - fld flt - fistp intgr - }; - - return intgr; -} -#endif - - - -const double fuzzyEpsilon = 0.00001; - -/** Returns a reference to a static double. - This value should not be tested against directly, instead - G3D::isNan() and G3D::isFinite() will return reliable results. */ -inline const double& inf() { - - // double is a standard type and should have infinity - static const double i = std::numeric_limits::infinity(); - return i; -} - -/** Returns a reference to a static double. - This value should not be tested against directly, instead - G3D::isNan() and G3D::isFinite() will return reliable results. */ -inline const double& nan() { - - // double is a standard type and should have quiet NaN - static const double n = std::numeric_limits::quiet_NaN(); - return n; -} - -/** Returns a reference to a static double. Use instead of G3D_PI. */ -inline const double& pi() { - static const double p = 3.1415926535898; - return p; -} - -/** Returns a reference to a static double. */ -inline const double& halfPi() { - static const double p = pi() / 2.0; - return p; -} - -/** Returns a reference to a static double. */ -inline const double& twoPi() { - static const double p = pi() * 2.0;; - return p; -} - -typedef signed char int8; -typedef unsigned char uint8; -typedef short int16; -typedef unsigned short uint16; -typedef int int32; -typedef unsigned int uint32; - -#ifdef _MSC_EXTENSIONS - typedef __int64 int64; - typedef unsigned __int64 uint64; -#elif ! defined(_MSC_VER) - typedef int64_t int64; - typedef uint64_t uint64; -#else - typedef long long int64; - typedef unsigned long long uint64; -#endif - -typedef float float32; -typedef double float64; - -int iAbs(int iValue); -int iCeil(double fValue); - -/** - Clamps the value to the range [low, hi] (inclusive) - */ -int iClamp(int val, int low, int hi); -int16 iClamp(int16 val, int16 low, int16 hi); -double clamp(double val, double low, double hi); -float clamp(float val, float low, float hi); - -/** - Returns a + (b - a) * f; - */ -inline double lerp(double a, double b, double f) { - return a + (b - a) * f; -} - -inline float lerp(float a, float b, float f) { - return a + (b - a) * f; -} - -/** - Wraps the value to the range [0, hi) (exclusive - on the high end). This is like the clock arithmetic - produced by % (modulo) except the result is guaranteed - to be positive. - */ -int iWrap(int val, int hi); - -int iFloor(double fValue); - -int iSign(int iValue); -int iSign(double fValue); - -inline int iSign(float f) { - return iSign((double)f); -} - - -/** - Fast round to integer using the lrint routine. - Typically 6x faster than casting to integer. - */ -inline int iRound(double fValue) { - return lrint(fValue); -} - -/** - Fast round to integer using the lrint routine. - Typically 6x faster than casting to integer. - */ -inline int iRound(float f) { - return lrintf(f); -} - -/** - Returns a random number uniformly at random between low and hi - (inclusive). - */ -int iRandom(int low, int hi); - -double abs (double fValue); -double aCos (double fValue); -double aSin (double fValue); -double aTan (double fValue); -double aTan2 (double fY, double fX); -double sign (double fValue); -double square (double fValue); - -/** - Returns true if the argument is a finite real number. - */ -bool isFinite(double x); - -/** - Returns true if the argument is NaN (not a number). - You can't use x == nan to test this because all - comparisons against nan return false. - */ -bool isNaN(double x); - -/** - Computes x % 3. - */ -int iMod3(int x); - -/** - Uniform random number between low and hi, inclusive. [low, hi] - */ -float uniformRandom(float low = 0.0f, float hi = 1.0f); - -/** - Normally distributed random number. - */ -float gaussRandom(float mean = 0.0f, float stdev = 1.0f); - -template -inline T min(const T& x, const T& y) { - return std::min(x, y); -} - -template -inline T min(const T& x, const T& y, const T& z) { - return std::min(std::min(x, y), z); -} - -template -inline T min(const T& x, const T& y, const T& z, const T& w) { - return std::min(std::min(x, y), std::min(z, w)); -} - -template -inline T max(const T& x, const T& y) { - return std::max(x, y); -} - -template -inline T max(const T& x, const T& y, const T& z) { - return std::max(std::max(x, y), z); -} - -template -inline T max(const T& x, const T& y, const T& z, const T& w) { - return std::max(std::max(x, y), std::max(z, w)); -} - -int iMin(int x, int y); -int iMax(int x, int y); - -double square(double x); -double sumSquares(double x, double y); -double sumSquares(double x, double y, double z); -double distance(double x, double y); -double distance(double x, double y, double z); - -/** - Returnes the 0-based index of the highest 1 bit from - the left. -1 means the number was 0. - - @cite Based on code by jukka@liimatta.org - */ -int highestBit(uint32 x); - -/** - Note that fuzzyEq(a, b) && fuzzyEq(b, c) does not imply - fuzzyEq(a, c), although that will be the case on some - occasions. - */ -bool fuzzyEq(double a, double b); - -/** True if a is definitely not equal to b. - Guaranteed false if a == b. - Possibly false when a != b.*/ -bool fuzzyNe(double a, double b); - -/** Is a strictly greater than b? (Guaranteed false if a <= b). - (Possibly false if a > b) */ -bool fuzzyGt(double a, double b); - -/** Is a near or greater than b? */ -bool fuzzyGe(double a, double b); - -/** Is a strictly less than b? (Guaranteed false if a >= b)*/ -bool fuzzyLt(double a, double b); - -/** Is a near or less than b? */ -bool fuzzyLe(double a, double b); - -/** - Computes 1 / sqrt(x). - */ -inline float rsq(float x) { - return 1.0f / sqrtf(x); -} - -/** - Uses SSE to implement rsq. - @cite Nick nicolas@capens.net - */ -inline float SSErsq(float x) { - - #if defined(SSE) && defined(G3D_WIN32) - __asm { - movss xmm0, x - rsqrtss xmm0, xmm0 - movss x, xmm0 - } - return x; - #else - return 1.0f / sqrt(x); - #endif -} - -/** - Return the next power of 2 higher than the input - If the input is already a power of 2, the output will be the same - as the input. - */ -int ceilPow2(unsigned int in); - -/** Returns 2^x */ -inline int pow2(unsigned int x) { - return 1 << x; -} - - -/** Log base 2 */ -inline float log2(float x) { - return ::logf(x) / ::logf(2.0f); -} - -/** Log base 2 */ -inline double log2(double x) { - return ::log(x) / ::log(2.0); -} - -/** Log base 2 */ -inline double log2(int x) { - return log2((double)x); -} - - -/** - * True if num is a power of two. - */ -bool isPow2(int num); - -bool isOdd(int num); -bool isEven(int num); - -double toRadians(double deg); -double toDegrees(double rad); - -/** - Returns true if x is not exactly equal to 0.0f. - */ -inline bool any(float x) { - return x != 0; -} - -/** - Returns true if x is not exactly equal to 0.0f. - */ -inline bool all(float x) { - return x != 0; -} - -/** - v / v (for DirectX/Cg support) - */ -inline float normalize(float v) { - return v / v; -} - -/** - a * b (for DirectX/Cg support) - */ -inline float dot(float a, float b) { - return a * b; -} - - -/** - a * b (for DirectX/Cg support) - */ -inline float mul(float a, float b) { - return a * b; -} - -/** - 2^x - */ -inline double exp2(double x) { - return pow(2.0, x); -} - -inline double rsqrt(double x) { - return 1.0 / sqrt(x); -} - - -/** - sin(x)/x - */ -inline double sinc(double x) { - double r = sin(x) / x; - - if (isNaN(r)) { - return 1.0; - } else { - return r; - } -} - -/** - Computes a floating point modulo; the result is t wrapped to the range [lo, hi). - */ -inline float wrap(float t, float lo, float hi) { - if ((t >= lo) && (t < hi)) { - return t; - } - - debugAssert(hi > lo); - - float interval = hi - lo; - - return t - interval * iFloor((t - lo) / interval); -} - - -inline double wrap(double t, double lo, double hi) { - if ((t >= lo) && (t < hi)) { - return t; - } - - debugAssert(hi > lo); - - double interval = hi - lo; - - return t - interval * iFloor((t - lo) / interval); -} - -inline double wrap(double t, double hi) { - return wrap(t, 0.0, hi); -} - - -inline bool isNaN(double x) { - bool b1 = (x < 0.0); - bool b2 = (x >= 0.0); - bool b3 = !(b1 || b2); - return b3; -} - -inline bool isFinite(double x) { - return ! isNaN(x) && (x < G3D::inf()) && (x > -G3D::inf()); -} - -//---------------------------------------------------------------------------- -inline int iAbs (int iValue) { - return ( iValue >= 0 ? iValue : -iValue ); -} - -//---------------------------------------------------------------------------- -inline int iCeil (double fValue) { - return int(::ceil(fValue)); -} - -//---------------------------------------------------------------------------- - -inline int iClamp(int val, int low, int hi) { - debugAssert(low <= hi); - if (val <= low) { - return low; - } else if (val >= hi) { - return hi; - } else { - return val; - } -} - -//---------------------------------------------------------------------------- - -inline int16 iClamp(int16 val, int16 low, int16 hi) { - debugAssert(low <= hi); - if (val <= low) { - return low; - } else if (val >= hi) { - return hi; - } else { - return val; - } -} - -//---------------------------------------------------------------------------- - -inline double clamp(double val, double low, double hi) { - debugAssert(low <= hi); - if (val <= low) { - return low; - } else if (val >= hi) { - return hi; - } else { - return val; - } -} - -inline float clamp(float val, float low, float hi) { - debugAssert(low <= hi); - if (val <= low) { - return low; - } else if (val >= hi) { - return hi; - } else { - return val; - } -} -//---------------------------------------------------------------------------- - -inline int iWrap(int val, int hi) { - if (val < 0) { - return ((val % hi) + hi) % hi; - } else { - return val % hi; - } -} - -//---------------------------------------------------------------------------- -inline int iFloor (double fValue) { - return int(::floor(fValue)); -} - -//---------------------------------------------------------------------------- -inline int iSign (int iValue) { - return ( iValue > 0 ? + 1 : ( iValue < 0 ? -1 : 0 ) ); -} - -inline int iSign (double fValue) { - return ( fValue > 0.0 ? + 1 : ( fValue < 0.0 ? -1 : 0 ) ); -} - -//---------------------------------------------------------------------------- -inline double abs (double fValue) { - return double(::fabs(fValue)); -} - -//---------------------------------------------------------------------------- -inline double aCos (double fValue) { - if ( -1.0 < fValue ) { - if ( fValue < 1.0 ) - return double(::acos(fValue)); - else - return 0.0; - } else { - return pi(); - } -} - -//---------------------------------------------------------------------------- -inline double aSin (double fValue) { - if ( -1.0 < fValue ) { - if ( fValue < 1.0 ) { - return double(::asin(fValue)); - } else { - return -halfPi(); - } - } else { - return halfPi(); - } -} - -//---------------------------------------------------------------------------- -inline double aTan (double fValue) { - return double(::atan(fValue)); -} - -//---------------------------------------------------------------------------- -inline double aTan2 (double fY, double fX) { - return double(::atan2(fY, fX)); -} - -//---------------------------------------------------------------------------- -inline double sign (double fValue) { - if (fValue > 0.0) { - return 1.0; - } - - if (fValue < 0.0) { - return -1.0; - } - - return 0.0; -} - -inline float sign (float fValue) { - if (fValue > 0.0f) { - return 1.0f; - } - - if (fValue < 0.0f) { - return -1.0f; - } - - return 0.0f; -} - - -inline float uniformRandom(float low, float hi) { - return (hi - low) * float(::rand()) / float(RAND_MAX) + low; -} - -//---------------------------------------------------------------------------- -inline double square(double x) { - return x * x; -} - -//---------------------------------------------------------------------------- -inline double sumSquares(double x, double y) { - return x*x + y*y; -} - -//---------------------------------------------------------------------------- -inline double sumSquares(double x, double y, double z) { - return x*x + y*y + z*z; -} - -//---------------------------------------------------------------------------- -inline double distance(double x, double y) { - return sqrt(sumSquares(x, y)); -} - -//---------------------------------------------------------------------------- -inline double distance(double x, double y, double z) { - return sqrt(sumSquares(x, y, z)); -} - -//---------------------------------------------------------------------------- - -/** @deprecated use G3D::min */ -inline int iMin(int x, int y) { - return (x >= y) ? y : x; -} - -//---------------------------------------------------------------------------- -/** @deprecated use G3D::min */ -inline int iMax(int x, int y) { - return (x >= y) ? x : y; -} - -//---------------------------------------------------------------------------- -inline int ceilPow2(unsigned int in) { - in -= 1; - - in |= in >> 16; - in |= in >> 8; - in |= in >> 4; - in |= in >> 2; - in |= in >> 1; - - return in + 1; -} - -inline bool isPow2(int num) { - return ((num & -num) == num); -} - -inline bool isOdd(int num) { - return (num & 1) == 1; -} - -inline bool isEven(int num) { - return (num & 1) == 0; -} - -inline double toRadians(double deg) { - return deg * pi() / 180.0; -} - -inline double toDegrees(double rad) { - return rad * 180.0 / pi(); -} - -inline float toRadians(float deg) { - return deg * (float)pi() / 180.0f; -} - -inline float toDegrees(float rad) { - return rad * 180.0f / (float)pi(); -} - -inline float toRadians(int deg) { - return deg * (float)pi() / 180.0f; -} - -inline float toDegrees(int rad) { - return rad * 180.0f / (float)pi(); -} -/** - Computes an appropriate epsilon for comparing a and b. - */ -inline double eps(double a, double b) { - // For a and b to be nearly equal, they must have nearly - // the same magnitude. This means that we can ignore b - // since it either has the same magnitude or the comparison - // will fail anyway. - (void)b; - const double aa = abs(a) + 1; - if (aa == inf()) { - return fuzzyEpsilon; - } else { - return fuzzyEpsilon * aa; - } -} - -inline bool fuzzyEq(double a, double b) { - return (a == b) || (abs(a - b) <= eps(a, b)); -} - -inline bool fuzzyNe(double a, double b) { - return ! fuzzyEq(a, b); -} - -inline bool fuzzyGt(double a, double b) { - return a > b + eps(a, b); -} - -inline bool fuzzyGe(double a, double b) { - return a > b - eps(a, b); -} - -inline bool fuzzyLt(double a, double b) { - return a < b - eps(a, b); -} - -inline bool fuzzyLe(double a, double b) { - return a < b + eps(a, b); -} - -inline int iMod3(int x) { - return x % 3; -} - -/** - Given a 32-bit integer, returns the integer with the bytes in the opposite order. - */ -inline uint32 flipEndian32(const uint32 x) { - return (x << 24) | ((x & 0xFF00) << 8) | - ((x & 0xFF0000) >> 8) | ((x & 0xFF000000) >> 24); -} - -/** - Given a 16-bit integer, returns the integer with the bytes in the opposite order. - */ -inline uint16 flipEndian16(const uint16 x) { - return (x << 8) | ((x & 0xFF00) >> 8); -} - - -} // namespace - -#ifdef _MSC_VER -# pragma warning (pop) -#endif - -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/platform.h b/externals/g3dlite/G3D.lib/include/G3D/platform.h deleted file mode 100644 index be9ec4d5123..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/platform.h +++ /dev/null @@ -1,256 +0,0 @@ -/** - @file platform.h - - #defines for platform specific issues. - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-06-09 - @edited 2007-07-30 - */ - -#ifndef G3D_PLATFORM_H -#define G3D_PLATFORM_H - -/** - The version number of G3D in the form: MmmBB -> - version M.mm [beta BB] - */ -#define G3D_VER 70100 - -#if defined(G3D_RELEASEDEBUG) -# define G3D_DEBUGRELEASE -#endif - -#if defined(G3D_DEBUGRELEASE) && defined(_DEBUG) -# undef _DEBUG -#endif - -#if !defined(G3D_DEBUG) && (defined(_DEBUG) || defined(G3D_DEBUGRELEASE)) -# define G3D_DEBUG -#endif - -#ifdef _MSC_VER - #define G3D_WIN32 -#elif defined(__FreeBSD__) || defined(__OpenBSD__) - #define G3D_FREEBSD - #define G3D_LINUX -#elif defined(__linux__) - #define G3D_LINUX -#elif defined(__APPLE__) - #define G3D_OSX - - // Prevent OS X fp.h header from being included; it defines - // pi as a constant, which creates a conflict with G3D -#define __FP__ -#else - #error Unknown platform -#endif - - -// Default to compiling with SSE, but if you want to compile -// without installing SP5.0 and the Processor Pack on Windows, compile with NO_SSE -// defined (can be passed to the compiler command line with /D "NO_SSE") -#if !defined(NO_SSE) - #define SSE -#endif - -// On g++, recognize cases where the -msse2 flag was not specified -#if defined(SSE) && defined(__GNUC__) && ! defined (__SSE__) -# undef SSE -#endif - - -// Verify that the supported compilers are being used and that this is a known -// processor. - -#ifdef G3D_LINUX -# ifndef __GNUC__ -# error G3D only supports the gcc compiler on Linux. -# endif -#endif - -#ifdef G3D_OSX -# ifndef __GNUC__ -# error G3D only supports the gcc compiler on OS X. -# endif - -# if defined(__i386__) -# define G3D_OSX_INTEL -# elif defined(__PPC__) -# define G3D_OSX_PPC -# else -# define G3D_OSX_UNKNOWN -# endif - -#endif - - -#ifdef _MSC_VER -// Microsoft Visual C++ 8.0 ("Express") = 1400 -// Microsoft Visual C++ 7.1 ("2003") _MSC_VER = 1310 -// Microsoft Visual C++ 7.0 ("2002") _MSC_VER = 1300 -// Microsoft Visual C++ 6.0 _MSC_VER = 1200 -// Microsoft Visual C++ 5.0 _MSC_VER = 1100 - -// Turn off warnings about deprecated C routines (TODO: revisit) -# pragma warning (disable : 4996) - -// Turn off "conditional expression is constant" warning; MSVC generates this -// for debug assertions in inlined methods. -# pragma warning (disable : 4127) - -# define G3D_DEPRECATED __declspec(deprecated) - -// Prevent Winsock conflicts by hiding the winsock API -# ifndef _WINSOCKAPI_ -# define _G3D_INTERNAL_HIDE_WINSOCK_ -# define _WINSOCKAPI_ -# endif - -// Disable 'name too long for browse information' warning -# pragma warning (disable : 4786) -// TODO: remove -# pragma warning (disable : 4244) - -# define ZLIB_WINAPI - -# define restrict - -# define G3D_CHECK_PRINTF_ARGS -# define G3D_CHECK_VPRINTF_ARGS -# define G3D_CHECK_PRINTF_METHOD_ARGS -# define G3D_CHECK_VPRINTF_METHOD_ARGS - - // On MSVC, we need to link against the multithreaded DLL version of - // the C++ runtime because that is what SDL and ZLIB are compiled - // against. This is not the default for MSVC, so we set the following - // defines to force correct linking. - // - // For documentation on compiler options, see: - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/HTML/_core_Compiler_Reference.asp - // - - // DLL runtime - #ifndef _DLL - #define _DLL - #endif - - // Multithreaded runtime - #ifndef _MT - #define _MT 1 - #endif - - // Ensure that we aren't forced into the static lib - #ifdef _STATIC_CPPLIB - #undef _STATIC_CPPLIB - #endif - - #ifdef _DEBUG - #pragma comment (linker, "/NODEFAULTLIB:LIBCMTD.LIB") - #pragma comment (linker, "/NODEFAULTLIB:LIBCPMTD.LIB") - #pragma comment (linker, "/NODEFAULTLIB:LIBCPD.LIB") - #pragma comment (linker, "/DEFAULTLIB:MSVCPRTD.LIB") - #pragma comment(linker, "/NODEFAULTLIB:LIBCD.LIB") - #pragma comment(linker, "/DEFAULTLIB:MSVCRTD.LIB") - #else - #pragma comment(linker, "/NODEFAULTLIB:LIBC.LIB") - #pragma comment(linker, "/DEFAULTLIB:MSVCRT.LIB") - #pragma comment (linker, "/NODEFAULTLIB:LIBCMT.LIB") - #pragma comment (linker, "/NODEFAULTLIB:LIBCPMT.LIB") - #pragma comment(linker, "/NODEFAULTLIB:LIBCP.LIB") - #pragma comment (linker, "/DEFAULTLIB:MSVCPRT.LIB") - #endif - - // Now set up external linking - -# ifdef _DEBUG - // zlib was linked against the release MSVCRT; force - // the debug version. -# pragma comment(linker, "/NODEFAULTLIB:MSVCRT.LIB") -# endif - - -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN 1 -# endif - - -# define NOMINMAX 1 -# ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0500 -# endif -# include -# undef WIN32_LEAN_AND_MEAN -# undef NOMINMAX - -# ifdef _G3D_INTERNAL_HIDE_WINSOCK_ -# undef _G3D_INTERNAL_HIDE_WINSOCK_ -# undef _WINSOCKAPI_ -# endif - - -# define G3D_START_AT_MAIN()\ -int WINAPI G3D_WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw);\ -int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) {\ - return G3D_WinMain(hInst, hPrev, szCmdLine, sw);\ -} - -#else - -# define G3D_START_AT_MAIN() - -#endif // win32 - -#ifdef __GNUC__ - -# include - -# if __STDC_VERSION__ < 199901 -# define restrict __restrict__ -# endif - -# define G3D_DEPRECATED __attribute__((__deprecated__)) - -// setup function calling conventions -# if defined(__i386__) && ! defined(__x86_64__) - -# ifndef __cdecl -# define __cdecl __attribute__((cdecl)) -# endif - -# ifndef __stdcall -# define __stdcall __attribute__((stdcall)) -# endif - -# elif defined(__x86_64__) || defined(__powerpc__) - -# ifndef __cdecl -# define __cdecl -# endif - -# ifndef __stdcall -# define __stdcall -# endif -# endif // calling conventions - -# define G3D_CHECK_PRINTF_METHOD_ARGS __attribute__((__format__(__printf__, 2, 3))) -# define G3D_CHECK_VPRINTF_METHOD_ARGS __attribute__((__format__(__printf__, 2, 0))) -# define G3D_CHECK_PRINTF_ARGS __attribute__((__format__(__printf__, 1, 2))) -# define G3D_CHECK_VPRINTF_ARGS __attribute__((__format__(__printf__, 1, 0))) -#endif - - -/** - @def STR(expression) - - Creates a string from the expression. Frequently used with G3D::Shader - to express shading programs inline. - - STR(this becomes a string)
 evaluates the same as "this becomes a string"
- */
-#define STR(x) #x
-
-// Header guard
-#endif
diff --git a/externals/g3dlite/G3D.lib/include/G3D/prompt.h b/externals/g3dlite/G3D.lib/include/G3D/prompt.h
deleted file mode 100644
index e25b955ab28..00000000000
--- a/externals/g3dlite/G3D.lib/include/G3D/prompt.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/** 
- @file prompt.h
- 
- @maintainer Morgan McGuire, matrix@graphics3d.com
- @cite   Windows GUI code by Max McGuire
-
- @created 2001-08-26
- @edited  2006-08-13
- */
-
-#ifndef G3D_PROMPT_H
-#define G3D_PROMPT_H
-
-#include "platform.h"
-#include 
-
-namespace G3D {
-
-/**
-  Prints a prompt to stdout and waits for user input.  The return value is
-  the number of the user's choice (the first is 0, if there are no
-  choices, returns 0). 
- 
-  @param useGui Under Win32, use a GUI, not stdout prompt.
-  @param windowTitle The title for the prompt window
-  @param promptx The text string to prompt the user with
-  @param choice  An array of strings that are the choices the user may make
-  @param numChoices The length of choice.
-
-  @cite Windows dialog interface by Max McGuire, mmcguire@ironlore.com
-  @cite Font setting code by Kurt Miller, kurt@flipcode.com
- */
-int prompt(
-    const char*     windowTitle,
-    const char*     promptx,
-    const char**    choice,
-    int             numChoices,
-    bool            useGui);
-
-/**
-  Prints a prompt and waits for user input.  The return value is
-  the number of the user's choice (the first is 0, if there are no
-  choices, returns 0).
-  

Uses GUI under Win32, stdout prompt otherwise. - */ -inline int prompt( - const char* windowTitle, - const char* promptx, - const char** choice, - int numChoices) { - - return prompt(windowTitle, promptx, choice, numChoices, true); -} - - -/** - Displays a GUI prompt with "Ok" as the only choice. - */ -void msgBox( - const std::string& message, - const std::string& title = "Message"); - - -}; // namespace - -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/serialize.h b/externals/g3dlite/G3D.lib/include/G3D/serialize.h deleted file mode 100644 index 2382c0ee0fd..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/serialize.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef G3D_SERIALIZE_H -#define G3D_SERIALIZE_H - -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/Array.h" - -namespace G3D { - - -template -void serialize(const Array& array, BinaryOutput& b) { - b.writeInt32(array.size()); - for (int i = 0; i < array.size(); ++i) { - serialize(array[i], b); - } -} - -template -void deserialize(Array& array, BinaryInput& b) { - int N = b.readInt32(); - array.resize(N); - for (int i = 0; i < array.size(); ++i) { - deserialize(array[i], b); - } -} - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/splinefunc.h b/externals/g3dlite/G3D.lib/include/G3D/splinefunc.h deleted file mode 100644 index a9daad9b578..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/splinefunc.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - @file spline.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2004-07-25 - @edited 2007-05-05 - */ - -#ifndef G3D_SPLINEFUNC_H -#define G3D_SPLINEFUNC_H - -namespace G3D { - -#include "G3D/platform.h" -#include "G3D/debug.h" -#include "G3D/Array.h" -#include "G3D/g3dmath.h" - -/** - Interpolates a property according to a piecewise linear spline. This provides - C0 continuity but the derivatives are not smooth. -

- Example: - - const double times[] = {MIDNIGHT, SUNRISE - HOUR, SUNRISE, SUNRISE + sunRiseAndSetTime / 4, SUNRISE + sunRiseAndSetTime, SUNSET - sunRiseAndSetTime, SUNSET - sunRiseAndSetTime / 2, SUNSET, SUNSET + HOUR/2, DAY}; - const Color3 color[] = {Color3(0, .0, .1), Color3(0, .0, .1), Color3::black(), Color3::black(), Color3::white() * .25, Color3::white() * .25, Color3(.5, .2, .2), Color3(.05, .05, .1), Color3(0, .0, .1), Color3(0, .0, .1)}; - ambient = linearSpline(time, times, color, 10); - - - See also G3D::Spline - - @param x The spline is a function of x; this is the sample to choose. - @param controlX controlX[i], controlY[i] is a control points. It is assumed - that controlX are strictly increasing. XType must support - the "<" operator and a subtraction operator that returns - a number. - @param controlY YType must support multiplication and addition. - @param numControl The number of control points. - */ -template -YType linearSpline(double x, const XType* controlX, const YType* controlY, int numControl) { - debugAssert(numControl >= 1); - - // Off the beginning - if ((numControl == 1) || (x < controlX[0])) { - return controlY[0]; - } - - for (int i = 1; i < numControl; ++i) { - if (x < controlX[i]) { - const double alpha = (double)(controlX[i] - x) / (controlX[i] - controlX[i - 1]); - return controlY[i] * (1 - alpha) + controlY[i - 1] * alpha; - } - } - - // Off the end - return controlY[numControl - 1]; -} - - - /** See also G3D::Spline*/ -template YType cyclicCatmullRomSpline( - double t, - const YType* controlY, - int numPoints) { - - debugAssert(numPoints >= 3); - - t = wrap(t, numPoints); - - // Find the indices of adjacent control points - int i = iFloor(t); - - // Compute the distance from the control point - t = t - i; - - // Shift back one point for correct indexing - i += numPoints - 1; - - // Pick up four control points - const YType& P0 = controlY[(i + 0) % numPoints]; - const YType& P1 = controlY[(i + 1) % numPoints]; - const YType& P2 = controlY[(i + 2) % numPoints]; - const YType& P3 = controlY[(i + 3) % numPoints]; - - return 0.5 * ((2 * P1) + - (-P0 + P2) * t + - (2*P0 - 5*P1 + 4*P2 - P3) * t*t + - (-P0 + 3*P1- 3*P2 + P3) * t*t*t); -} - -/** - A cubic spline with regularly spaced - control points. The spline interpolates - the control points. The spline - will wrap from the last point back to the first. - - The t parameter is on the range [0, controlY.size()], - where integers correspond to control points exactly. - - See also G3D::Spline - - @cite http://www.mvps.org/directx/articles/catmull/ -*/ -template YType cyclicCatmullRomSpline( - double t, - const Array& controlY) { - - int numPoints = controlY.size(); - return cyclicCatmullRomSpline(t, controlY.getCArray(), numPoints); -} - -} - -#endif - - diff --git a/externals/g3dlite/G3D.lib/include/G3D/stringutils.h b/externals/g3dlite/G3D.lib/include/G3D/stringutils.h deleted file mode 100644 index 20a2ff6e795..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/stringutils.h +++ /dev/null @@ -1,130 +0,0 @@ -/** - @file stringutils.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @author 2000-09-09 - @edited 2008-08-05 - */ - -#ifndef G3D_STRINGUTILS_H -#define G3D_STRINGUTILS_H - -#include "G3D/platform.h" -#include "G3D/Array.h" -#include - -namespace G3D { - -extern const char* NEWLINE; - -/** - Returns true if the test string begins with the pattern string. - */ -bool beginsWith( - const std::string& test, - const std::string& pattern); - -/** - Returns true if the test string ends with the pattern string. - */ -bool endsWith( - const std::string& test, - const std::string& pattern); - -/** - Produces a new string that is the input string - wrapped at a certain number of columns (where - the line is broken at the latest space before the - column limit.) Platform specific NEWLINEs - are inserted to wrap. - */ -std::string wordWrap( - const std::string& input, - int numCols); - -/** - A comparison function for passing to Array::sort. - */ -int stringCompare( - const std::string& s1, - const std::string& s2); - -int stringPtrCompare( - const std::string* s1, - const std::string* s2); - -/** - Returns a new string that is an uppercase version of x. - */ -std::string toUpper( - const std::string& x); - -std::string toLower( - const std::string& x); - -/** - Splits x at each occurance of splitChar. - */ -G3D::Array stringSplit( - const std::string& x, - char splitChar); - -/** - joinChar is not inserted at the beginning or end, just in between - elements. - */ -std::string stringJoin( - const G3D::Array& a, - char joinChar); - -std::string stringJoin( - const G3D::Array& a, - const std::string& joinStr); - -/** - Strips whitespace from both ends of the string. - */ -std::string trimWhitespace( - const std::string& s); - -/** These standard C functions are renamed for clarity/naming - conventions and to return bool, not int. - */ -inline bool isWhiteSpace(const unsigned char c) { - return isspace(c) != 0; -} - -/** These standard C functions are renamed for clarity/naming - conventions and to return bool, not int. - */ -inline bool isNewline(const unsigned char c) { - return (c == '\n') || (c == '\r'); -} - -/** These standard C functions are renamed for clarity/naming - conventions and to return bool, not int. - */ -inline bool isDigit(const unsigned char c) { - return isdigit(c) != 0; -} - -/** These standard C functions are renamed for clarity/naming - conventions and to return bool, not int. - */ -inline bool isLetter(const unsigned char c) { - return isalpha(c) != 0; -} - -inline bool isSlash(const unsigned char c) { - return (c == '\\') || (c == '/'); -} - -inline bool isQuote(const unsigned char c) { - return (c == '\'') || (c == '\"'); -} - -}; // namespace - -#endif - diff --git a/externals/g3dlite/G3D.lib/include/G3D/uint128.h b/externals/g3dlite/G3D.lib/include/G3D/uint128.h deleted file mode 100644 index 3e970cb2a7e..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/uint128.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - @file uint128.h - - @maintainer Morgan McGuire, matrix@graphics3d.com - @author Kyle Whitson - - @created 2008-07-17 - @edited 2008-07-17 - */ - -#ifndef G3D_UINT128_H -#define G3D_UINT128_H - -#include "G3D/g3dmath.h" - -namespace G3D { - -/** Limited functionality 128-bit unsigned integer. This is primarily to support FNV hashing and other - cryptography applications. See the GMP library for high-precision C++ math support. */ -class uint128 { -public: - - G3D::uint64 hi; - G3D::uint64 lo; - - uint128(const uint64& lo); - - uint128(const uint64& hi, const uint64& lo); - - uint128& operator+=(const uint128& x); - - uint128& operator*=(const uint128& x); - - uint128& operator^=(const uint128& x); - - uint128& operator&=(const uint128& x); - - uint128& operator|=(const uint128& x); - - bool operator==(const uint128& x); - - uint128& operator>>=(const int x); - - uint128& operator<<=(const int x); - - uint128 operator&(const uint128& x); - -}; -} - -#endif diff --git a/externals/g3dlite/G3D.lib/include/G3D/vectorMath.h b/externals/g3dlite/G3D.lib/include/G3D/vectorMath.h deleted file mode 100644 index aedc731e7f8..00000000000 --- a/externals/g3dlite/G3D.lib/include/G3D/vectorMath.h +++ /dev/null @@ -1,235 +0,0 @@ -/** - @file vectorMath.h - - Function aliases for popular vector methods. - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created: 2001-06-02 - @edited: 2004-02-02 - Copyright 2000-2004, Morgan McGuire. - All rights reserved. - */ - -#ifndef G3D_VECTORMATH_H -#define G3D_VECTORMATH_H - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Vector2.h" -#include "G3D/Vector3.h" -#include "G3D/Vector4.h" -#include "G3D/Matrix3.h" -#include "G3D/Matrix4.h" -#include "G3D/Color1.h" -#include "G3D/Color3.h" -#include "G3D/Color4.h" - - -namespace G3D { - - -inline Matrix4 mul(const Matrix4& a, const Matrix4& b) { - return a * b; -} - -inline Vector4 mul(const Matrix4& m, const Vector4& v) { - return m * v; -} - -inline Vector3 mul(const Matrix3& m, const Vector3& v) { - return m * v; -} - -inline Matrix3 mul(const Matrix3& a, const Matrix3& b) { - return a * b; -} - -inline float dot(const Vector2& a, const Vector2& b) { - return a.dot(b); -} - -inline float dot(const Vector3& a, const Vector3& b) { - return a.dot(b); -} - -inline float dot(const Vector4& a, const Vector4& b) { - return a.dot(b); -} - -inline Vector2 normalize(const Vector2& v) { - return v / v.length(); -} - -inline Vector3 normalize(const Vector3& v) { - return v / v.magnitude(); -} - -inline Vector4 normalize(const Vector4& v) { - return v / v.length(); -} - -inline Vector2 abs(const Vector2& v) { - return Vector2(::fabsf(v.x), ::fabsf(v.y)); -} - -inline Vector3 abs(const Vector3& v) { - return Vector3(::fabsf(v.x), ::fabsf(v.y), ::fabsf(v.z)); -} - -inline Vector4 abs(const Vector4& v) { - return Vector4(::fabsf(v.x), ::fabsf(v.y), ::fabsf(v.z), ::fabsf(v.w)); -} - -inline bool all(const Vector2& v) { - return (v.x != 0) && (v.y != 0); -} - -inline bool all(const Vector3& v) { - return (v.x != 0) && (v.y != 0) && (v.z != 0); -} - -inline bool all(const Vector4& v) { - return (v.x != 0) && (v.y != 0) && (v.z != 0) && (v.w != 0); -} - -inline bool any(const Vector2& v) { - return (v.x != 0) || (v.y != 0); -} - -inline bool any(const Vector3& v) { - return (v.x != 0) || (v.y != 0) || (v.z != 0); -} - -inline bool any(const Vector4& v) { - return (v.x != 0) || (v.y != 0) || (v.z != 0) || (v.w != 0); -} - -inline Vector2 clamp(const Vector2& v, const Vector2& a, const Vector2& b) { - return v.clamp(a, b); -} - -inline Vector3 clamp(const Vector3& v, const Vector3& a, const Vector3& b) { - return v.clamp(a, b); -} - -inline Vector4 clamp(const Vector4& v, const Vector4& a, const Vector4& b) { - return v.clamp(a, b); -} - -inline Vector2 lerp(const Vector2& v1, const Vector2& v2, float f) { - return v1.lerp(v2, f); -} - -inline Vector3 lerp(const Vector3& v1, const Vector3& v2, float f) { - return v1.lerp(v2, f); -} - -inline Vector4 lerp(const Vector4& v1, const Vector4& v2, float f) { - return v1.lerp(v2, f); -} - -inline Color1 lerp(const Color1& v1, const Color1& v2, float f) { - return v1.lerp(v2, f); -} - -inline Color3 lerp(const Color3& v1, const Color3& v2, float f) { - return v1.lerp(v2, f); -} - -inline Color4 lerp(const Color4& v1, const Color4& v2, float f) { - return v1.lerp(v2, f); -} - -inline Vector3 cross(const Vector3& v1, const Vector3& v2) { - return v1.cross(v2); -} - -inline double determinant(const Matrix3& m) { - return m.determinant(); -} - -inline double determinant(const Matrix4& m) { - return m.determinant(); -} - -inline Vector2 min(const Vector2& v1, const Vector2& v2) { - return v1.min(v2); -} - -inline Vector3 min(const Vector3& v1, const Vector3& v2) { - return v1.min(v2); -} - -inline Vector4 min(const Vector4& v1, const Vector4& v2) { - return v1.min(v2); -} - -inline Color3 min(const Color3& v1, const Color3& v2) { - return v1.min(v2); -} - -inline Color4 min(const Color4& v1, const Color4& v2) { - return v1.min(v2); -} - -inline Vector2 max(const Vector2& v1, const Vector2& v2) { - return v1.max(v2); -} - -inline Vector3 max(const Vector3& v1, const Vector3& v2) { - return v1.max(v2); -} - -inline Vector4 max(const Vector4& v1, const Vector4& v2) { - return v1.max(v2); -} - -inline Color3 max(const Color3& v1, const Color3& v2) { - return v1.max(v2); -} - -inline Color4 max(const Color4& v1, const Color4& v2) { - return v1.max(v2); -} - -inline Vector2 sign(const Vector2& v) { - return Vector2((float)sign(v.x), (float)sign(v.y)); -} - -inline Vector3 sign(const Vector3& v) { - return Vector3((float)sign(v.x), (float)sign(v.y), (float)sign(v.z)); -} - -inline Vector4 sign(const Vector4& v) { - return Vector4((float)sign(v.x), (float)sign(v.y), (float)sign(v.z), (float)sign(v.w)); -} - -inline float length(float v) { - return ::fabsf(v); -} - -inline float length(const Vector2& v) { - return v.length(); -} - -inline float length(const Vector3& v) { - return v.magnitude(); -} - -inline float length(const Vector4& v) { - return v.length(); -} - -/** - Computes the log of each component. Useful for - inverting the monitor gamma function or simulating - perceptual response. - */ -inline Color3 log(const Color3& c) { - return Color3(::logf(c.r), ::logf(c.g), ::logf(c.b)); -} - -} - -#endif diff --git a/externals/g3dlite/G3D.lib/source/AABox.cpp b/externals/g3dlite/G3D.lib/source/AABox.cpp deleted file mode 100644 index 9e871aa8af7..00000000000 --- a/externals/g3dlite/G3D.lib/source/AABox.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/** - @file AABox.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2004-01-10 - @edited 2006-01-11 -*/ - -#include "G3D/platform.h" -#include "G3D/AABox.h" -#include "G3D/Box.h" -#include "G3D/Plane.h" -#include "G3D/Sphere.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - - -namespace G3D { - - -void AABox::serialize(class BinaryOutput& b) const { - b.writeVector3(lo); - b.writeVector3(hi); -} - - -void AABox::deserialize(class BinaryInput& b) { - lo = b.readVector3(); - hi = b.readVector3(); -} - - -void AABox::split(const Vector3::Axis& axis, float location, AABox& low, AABox& high) const { - // Low, medium, and high along the chosen axis - float L = G3D::min(location, lo[axis]); - float M = G3D::min(G3D::max(location, lo[axis]), hi[axis]); - float H = G3D::max(location, hi[axis]); - - // Copy over this box. - high = low = *this; - - // Now move the split points along the special axis - low.lo[axis] = L; - low.hi[axis] = M; - high.lo[axis] = M; - high.hi[axis] = H; -} - - -Vector3 AABox::randomSurfacePoint() const { - Vector3 extent = hi - lo; - float aXY = extent.x * extent.y; - float aYZ = extent.y * extent.z; - float aZX = extent.z * extent.x; - - float r = (float)uniformRandom(0.0f, aXY + aYZ + aZX); - - // Choose evenly between positive and negative face planes - float d = ((float)uniformRandom(0, 1) < 0.5f) ? 0.0f : 1.0f; - - // The probability of choosing a given face is proportional to - // its area. - if (r < aXY) { - return - lo + - Vector3( - (float)uniformRandom(0.0f, extent.x), - (float)uniformRandom(0.0f, extent.y), - d * extent.z); - } else if (r < aYZ) { - return - lo + - Vector3( - d * extent.x, - (float)uniformRandom(0, extent.y), - (float)uniformRandom(0, extent.z)); - } else { - return - lo + - Vector3( - (float)uniformRandom(0, extent.x), - d * extent.y, - (float)uniformRandom(0, extent.z)); - } -} - - -Vector3 AABox::randomInteriorPoint() const { - return Vector3( - (float)uniformRandom(lo.x, hi.x), - (float)uniformRandom(lo.y, hi.y), - (float)uniformRandom(lo.z, hi.z)); -} - - -bool AABox::intersects(const AABox& other) const { - // Must be overlap along all three axes. - // Try to find a separating axis. - - for (int a = 0; a < 3; ++a) { - - // |--------| - // |------| - - if ((lo[a] > other.hi[a]) || - (hi[a] < other.lo[a])) { - return false; - } - } - - return true; -} - -int AABox::dummy = 0; - - -bool AABox::culledBy( - const Array& plane, - int& cullingPlane, - const uint32 _inMask, - uint32& childMask) const { - - uint32 inMask = _inMask; - assert(plane.size() < 31); - - childMask = 0; - - const bool finite = - (abs(lo.x) < G3D::inf()) && - (abs(hi.x) < G3D::inf()) && - (abs(lo.y) < G3D::inf()) && - (abs(hi.y) < G3D::inf()) && - (abs(lo.z) < G3D::inf()) && - (abs(hi.z) < G3D::inf()); - - // See if there is one plane for which all of the - // vertices are in the negative half space. - for (int p = 0; p < plane.size(); ++p) { - - // Only test planes that are not masked - if ((inMask & 1) != 0) { - - Vector3 corner; - - int numContained = 0; - int v = 0; - - // We can early-out only if we have found one point on each - // side of the plane (i.e. if we are straddling). That - // occurs when (numContained < v) && (numContained > 0) - for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) { - // Unrolling these 3 if's into a switch decreases performance - // by about 2x - corner.x = (v & 1) ? hi.x : lo.x; - corner.y = (v & 2) ? hi.y : lo.y; - corner.z = (v & 4) ? hi.z : lo.z; - - if (finite) { // this branch is highly predictable - if (plane[p].halfSpaceContainsFinite(corner)) { - ++numContained; - } - } else { - if (plane[p].halfSpaceContains(corner)) { - ++numContained; - } - } - } - - if (numContained == 0) { - // Plane p culled the box - cullingPlane = p; - - // The caller should not recurse into the children, - // since the parent is culled. If they do recurse, - // make them only test against this one plane, which - // will immediately cull the volume. - childMask = 1 << p; - return true; - - } else if (numContained < v) { - // The bounding volume straddled the plane; we have - // to keep testing against this plane - childMask |= (1 << p); - } - } - - // Move on to the next bit. - inMask = inMask >> 1; - } - - // None of the planes could cull this box - cullingPlane = -1; - return false; -} - - -bool AABox::culledBy( - const Array& plane, - int& cullingPlane, - const uint32 _inMask) const { - - uint32 inMask = _inMask; - assert(plane.size() < 31); - - const bool finite = - (abs(lo.x) < G3D::inf()) && - (abs(hi.x) < G3D::inf()) && - (abs(lo.y) < G3D::inf()) && - (abs(hi.y) < G3D::inf()) && - (abs(lo.z) < G3D::inf()) && - (abs(hi.z) < G3D::inf()); - - // See if there is one plane for which all of the - // vertices are in the negative half space. - for (int p = 0; p < plane.size(); ++p) { - - // Only test planes that are not masked - if ((inMask & 1) != 0) { - - bool culled = true; - Vector3 corner; - - int v; - - // Assume this plane culls all points. See if there is a point - // not culled by the plane... early out when at least one point - // is in the positive half space. - for (v = 0; (v < 8) && culled; ++v) { - - // Unrolling these 3 if's into a switch decreases performance - // by about 2x - corner.x = (v & 1) ? hi.x : lo.x; - corner.y = (v & 2) ? hi.y : lo.y; - corner.z = (v & 4) ? hi.z : lo.z; - - if (finite) { // this branch is highly predictable - culled = ! plane[p].halfSpaceContainsFinite(corner); - } else { - culled = ! plane[p].halfSpaceContains(corner); - } - } - - if (culled) { - // Plane p culled the box - cullingPlane = p; - - return true; - } - } - - // Move on to the next bit. - inMask = inMask >> 1; - } - - // None of the planes could cull this box - cullingPlane = -1; - return false; -} - - -bool AABox::intersects(const class Sphere& sphere) const { - double d = 0; - - //find the square of the distance - //from the sphere to the box - for (int i = 0; i < 3; ++i) { - if (sphere.center[i] < lo[i]) { - d += square(sphere.center[i] - lo[i]); - } else if (sphere.center[i] > hi[i]) { - d += square(sphere.center[i] - hi[i]); - } - } - - return d <= square(sphere.radius); -} - -Vector3 AABox::corner(int index) const { - - // default constructor inits all components to 0 - Vector3 v; - - switch (index) - { - case 0: - v.x = lo.x; - v.y = lo.y; - v.z = hi.z; - break; - - case 1: - v.x = hi.x; - v.y = lo.y; - v.z = hi.z; - break; - - case 2: - v.x = hi.x; - v.y = hi.y; - v.z = hi.z; - break; - - case 3: - v.x = lo.x; - v.y = hi.y; - v.z = hi.z; - break; - - case 4: - v.x = lo.x; - v.y = lo.y; - v.z = lo.z; - break; - - case 5: - v.x = hi.x; - v.y = lo.y; - v.z = lo.z; - break; - - case 6: - v.x = hi.x; - v.y = hi.y; - v.z = lo.z; - break; - - case 7: - v.x = lo.x; - v.y = hi.y; - v.z = lo.z; - break; - - default: - debugAssertM(false, "Invalid corner index"); - break; - } - - return v; -} - - -} diff --git a/externals/g3dlite/G3D.lib/source/AnyVal.cpp b/externals/g3dlite/G3D.lib/source/AnyVal.cpp deleted file mode 100644 index 45fb41df534..00000000000 --- a/externals/g3dlite/G3D.lib/source/AnyVal.cpp +++ /dev/null @@ -1,1381 +0,0 @@ -/** - @file AnyVal.cpp - @author Morgan McGuire - @maintainer Morgan McGuire - @created 2006-06-11 - @edited 2008-07-14 - */ - -#include "G3D/AnyVal.h" -#include "G3D/Array.h" -#include "G3D/stringutils.h" -#include "G3D/Table.h" -#include "G3D/Vector2.h" -#include "G3D/Vector3.h" -#include "G3D/Vector4.h" -#include "G3D/Color1.h" -#include "G3D/Color3.h" -#include "G3D/Color4.h" -#include "G3D/Matrix2.h" -#include "G3D/Matrix3.h" -#include "G3D/Matrix4.h" -#include "G3D/Rect2D.h" -#include "G3D/AABox.h" -#include "G3D/CoordinateFrame.h" -#include "G3D/Quat.h" -#include "G3D/TextInput.h" -#include "G3D/TextOutput.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - -namespace G3D { - -AnyVal AnyVal::fromFile(const std::string& filename) { - TextInput t(filename); - return AnyVal(t); -} - - -void AnyVal::load(const std::string& filename) { - *this = fromFile(filename); -} - - -void AnyVal::save(const std::string& filename) const { - TextOutput t(filename); - serialize(t); - t.commit(); -} - - -AnyVal::AnyVal() : m_type(NIL), m_value(NULL), m_referenceCount(NULL) { -} - - -AnyVal::AnyVal(bool b) : m_type(BOOLEAN), m_value(new bool(b)), m_referenceCount(NULL) { -} - - -AnyVal::AnyVal(G3D::TextInput& t) : m_type(NIL), m_value(NULL), m_referenceCount(NULL) { - deserialize(t); -} - - -/*AnyVal::AnyVal(G3D::BinaryInput& b) { - deserialize(b); -} -*/ - -AnyVal::AnyVal(double v) : m_type(NUMBER), m_referenceCount(NULL) { - m_value = new double(v); -} - - -AnyVal::AnyVal(int v) : m_type(NUMBER), m_referenceCount(NULL) { - m_value = new double(v); -} - - -AnyVal::AnyVal(const Rect2D& v) : m_type(RECT2D), m_referenceCount(NULL) { - m_value = new Rect2D(v); -} - - -AnyVal::AnyVal(const AABox& v) : m_type(AABOX), m_referenceCount(NULL) { - m_value = new AABox(v); -} - - -AnyVal::AnyVal(const Vector2& v) : m_type(VECTOR2), m_referenceCount(NULL) { - m_value = new Vector2(v); -} - - -AnyVal::AnyVal(const Vector3& v) : m_type(VECTOR3), m_referenceCount(NULL) { - m_value = new Vector3(v); -} - - -AnyVal::AnyVal(const Vector4& v) : m_type(VECTOR4), m_referenceCount(NULL) { - m_value = new Vector4(v); -} - - -AnyVal::AnyVal(const Color1& v) : m_type(COLOR1), m_referenceCount(NULL) { - m_value = new Color1(v); -} - - -AnyVal::AnyVal(const Color3& v) : m_type(COLOR3), m_referenceCount(NULL) { - m_value = new Color3(v); -} - - -AnyVal::AnyVal(const Color4& v) : m_type(COLOR4), m_referenceCount(NULL) { - m_value = new Color4(v); -} - - -AnyVal::AnyVal(const std::string& v) : m_type(STRING), m_referenceCount(NULL) { - m_value = new std::string(v); -} - - -AnyVal::AnyVal(const char* v) : m_type(STRING), m_referenceCount(NULL) { - m_value = new std::string(v); -} - - -AnyVal::AnyVal(const Quat& v) : m_type(QUAT), m_referenceCount(NULL) { - m_value = new Quat(v); -} - - -AnyVal::AnyVal(const CoordinateFrame& v) : m_type(COORDINATEFRAME), m_referenceCount(NULL) { - m_value = new CoordinateFrame(v); -} - - -AnyVal::AnyVal(const Matrix2& v) : m_type(MATRIX2), m_referenceCount(NULL) { - m_value = new Matrix2(v); -} - -AnyVal::AnyVal(const Matrix3& v) : m_type(MATRIX3), m_referenceCount(NULL) { - m_value = new Matrix3(v); -} - - -AnyVal::AnyVal(const Matrix4& v) : m_type(MATRIX4), m_referenceCount(NULL) { - m_value = new Matrix4(v); -} - - -AnyVal::AnyVal(const AnyVal& c) : m_type(NIL), m_value(NULL), m_referenceCount(NULL) { - *this = c; -} - - -AnyVal::AnyVal(Type arrayOrTable) : m_type(NIL), m_value(NULL), m_referenceCount(new int(1)) { - // TODO: make AnyVal::createArray() - switch (arrayOrTable) { - case ARRAY: - m_type = ARRAY; - m_value = new Array(); - break; - - case TABLE: - m_type = TABLE; - m_value = new Table(); - break; - - default: - debugAssertM(false, "Cannot construct AnyVal from constants except ARRAY or TABLE."); - } -} - - -AnyVal::~AnyVal() { - deleteValue(); -} - - -void AnyVal::deleteValue() { - if (m_referenceCount) { - --(*m_referenceCount); - if (*m_referenceCount <= 0) { - delete m_referenceCount; - m_referenceCount = NULL; - // Pass through and delete the real object now - } else { - // Someone else is holding a reference, so we can't delete - // the object. - m_referenceCount = NULL; - return; - } - } - - switch (m_type) { - case NIL: - // Nothing to do - break; - - case NUMBER: - delete (double*)m_value; - break; - - case BOOLEAN: - delete (bool*)m_value; - break; - - case STRING: - delete (std::string*)m_value; - break; - - case RECT2D: - delete (Rect2D*)m_value; - break; - - case AABOX: - delete (AABox*)m_value; - break; - - case VECTOR2: - delete (Vector2*)m_value; - break; - - case VECTOR3: - delete (Vector3*)m_value; - break; - - case VECTOR4: - delete (Vector4*)m_value; - break; - - case MATRIX2: - delete (Matrix2*)m_value; - break; - - case MATRIX3: - delete (Matrix3*)m_value; - break; - - case MATRIX4: - delete (Matrix4*)m_value; - break; - - case QUAT: - delete (Quat*)m_value; - break; - - case COORDINATEFRAME: - delete (CoordinateFrame*)m_value; - break; - - case COLOR1: - delete (Color1*)m_value; - break; - - case COLOR3: - delete (Color3*)m_value; - break; - - case COLOR4: - delete (Color4*)m_value; - break; - - case ARRAY: - delete (Array*)m_value; - break; - - case TABLE: - delete (Table*)m_value; - break; - - default: - debugAssertM(false, "Internal error: no destructor for this type."); - } - - m_value = NULL; -} - - -AnyVal& AnyVal::operator=(const AnyVal& v) { - deleteValue(); - - m_type = v.m_type; - - m_referenceCount = v.m_referenceCount; - - if (isSharedType()) { - ++(*m_referenceCount); - m_value = v.m_value; - } else { - m_value = v.copyValue(); - } - - return *this; -} - - -void* AnyVal::copyValue() const { - switch (m_type) { - case NIL: - return NULL; - - case NUMBER: - return new double(*(double*)m_value); - - case BOOLEAN: - return new bool(*(bool*)m_value); - - case STRING: - return new std::string(*(std::string*)m_value); - - case RECT2D: - return new Rect2D(*(Rect2D*)m_value); - - case AABOX: - return new AABox(*(AABox*)m_value); - - case VECTOR2: - return new Vector2(*(Vector2*)m_value); - - case VECTOR3: - return new Vector3(*(Vector3*)m_value); - - case VECTOR4: - return new Vector4(*(Vector4*)m_value); - - case MATRIX2: - return new Matrix2(*(Matrix2*)m_value); - - case MATRIX3: - return new Matrix3(*(Matrix3*)m_value); - - case MATRIX4: - return new Matrix4(*(Matrix4*)m_value); - - case QUAT: - return new Quat(*(Quat*)m_value); - - case COORDINATEFRAME: - return new CoordinateFrame(*(CoordinateFrame*)m_value); - - case COLOR1: - return new Color1(*(Color1*)m_value); - - case COLOR3: - return new Color3(*(Color3*)m_value); - - case COLOR4: - return new Color4(*(Color4*)m_value); - - case ARRAY: - return new Array(*(Array*)m_value); - - case TABLE: - return new Table(*(Table*)m_value); - - default: - debugAssertM(false, "Internal error: no assignment operator for this type."); - return NULL; - } -} - -AnyVal::Type AnyVal::type() const { - return m_type; -} - - -static bool legalIdentifier(const std::string& s) { - if (s.size() == 0) { - return false; - } - - if (! isLetter(s[0]) || (s[0] == '_')) { - return false; - } - - bool ok = true; - - for (unsigned int i = 1; i < s.size(); ++i) { - ok &= isDigit(s[i]) || isLetter(s[i]) || (s[i] == '_'); - } - - return ok; -} - - -void AnyVal::serialize(G3D::TextOutput& t) const { - switch (m_type) { - case NIL: - t.writeSymbol("Nil"); - break; - - case NUMBER: - t.printf("%g", *(double*)m_value); - break; - - case BOOLEAN: - t.writeBoolean(*(bool*)m_value); - break; - - case STRING: - t.writeString(*(std::string*)m_value); - break; - - case RECT2D: - t.printf("R(%g, %g, %g, %g)", ((Rect2D*)m_value)->x0(), ((Rect2D*)m_value)->y0(), - ((Rect2D*)m_value)->width(), ((Rect2D*)m_value)->height()); - break; - - case AABOX: - t.printf("AAB(V3(%g, %g, %g), V3(%g, %g, %g))", - aabox().low().x, - aabox().low().y, - aabox().low().z, - aabox().high().x, - aabox().high().y, - aabox().high().z); - break; - - case VECTOR2: - t.printf("V2(%g, %g)", ((Vector2*)m_value)->x, ((Vector2*)m_value)->y); - break; - - case VECTOR3: - t.printf("V3(%g, %g, %g)", ((Vector3*)m_value)->x, ((Vector3*)m_value)->y, ((Vector3*)m_value)->z); - break; - - case VECTOR4: - t.printf("V4(%g, %g, %g, %g)", ((Vector4*)m_value)->x, ((Vector4*)m_value)->y, ((Vector4*)m_value)->z, ((Vector4*)m_value)->w); - break; - - case MATRIX2: - { - const Matrix2& m = *(Matrix2*)m_value; - t.printf("M2(\n"); - t.pushIndent(); - t.printf("%10.5f, %10.5f,\n%10.5f, %10.5f)", - m[0][0], m[0][1], - m[1][0], m[1][1]); - t.popIndent(); - } - break; - - case MATRIX3: - { - const Matrix3& m = *(Matrix3*)m_value; - t.printf("M3(\n"); - t.pushIndent(); - t.printf("%10.5f, %10.5f, %10.5f,\n%10.5f, %10.5f, %10.5f,\n%10.5f, %10.5f, %10.5f)", - m[0][0], m[0][1], m[0][2], - m[1][0], m[1][1], m[1][2], - m[2][0], m[2][1], m[2][2]); - t.popIndent(); - } - break; - - case MATRIX4: - { - const Matrix4& m = *(Matrix4*)m_value; - t.printf("M4(\n"); - t.pushIndent(); - t.printf( - "%10.5f, %10.5f, %10.5f, %10.5f,\n" - "%10.5f, %10.5f, %10.5f, %10.5f,\n" - "%10.5f, %10.5f, %10.5f, %10.5f,\n" - "%10.5f, %10.5f, %10.5f, %10.5f)", - m[0][0], m[0][1], m[0][2], m[0][3], - m[1][0], m[1][1], m[1][2], m[1][3], - m[2][0], m[2][1], m[2][2], m[2][3], - m[3][0], m[3][1], m[3][2], m[3][3]); - t.popIndent(); - } - break; - - case QUAT: - t.printf("Q(%g, %g, %g, %g)", ((Quat*)m_value)->x, ((Quat*)m_value)->y, ((Quat*)m_value)->z, ((Quat*)m_value)->w); - break; - - case COORDINATEFRAME: - { - const CoordinateFrame& c = *(CoordinateFrame*)m_value; - float x,y,z,yaw,pitch,roll; - c.getXYZYPRDegrees(x,y,z,yaw,pitch,roll); - t.printf("CF(V3(%g,%g,%g), %g, %g, %g)", x, y, z, yaw, pitch, roll); - /* - t.pushIndent(); - t.printf( - "CF(\n%10.5f, %10.5f, %10.5f, %10.5f,\n" - "%10.5f, %10.5f, %10.5f, %10.5f,\n" - "%10.5f, %10.5f, %10.5f, %10.5f)", - c.rotation[0][0], c.rotation[0][1], c.rotation[0][2], c.translation.x, - c.rotation[1][0], c.rotation[1][1], c.rotation[1][2], c.translation.y, - c.rotation[2][0], c.rotation[2][1], c.rotation[2][2], c.translation.z); - t.popIndent(); - */ - } - break; - - case COLOR1: - t.printf("C1(%g)", ((Color1*)m_value)->value); - break; - - case COLOR3: - t.printf("C3(%g, %g, %g)", ((Color3*)m_value)->r, ((Color3*)m_value)->g, ((Color3*)m_value)->b); - break; - - case COLOR4: - t.printf("C4(%g, %g, %g, %g)", ((Color4*)m_value)->r, ((Color4*)m_value)->g, ((Color4*)m_value)->b, ((Color4*)m_value)->a); - break; - - case ARRAY: - { - const Array& a = *(Array*)m_value; - t.printf("[\n"); - t.pushIndent(); - for (int i = 0; i < a.size(); ++i) { - a[i].serialize(t); - if (i != a.size() - 1) { - t.printf(", \n"); - } - } - t.printf("]"); - t.popIndent(); - } - break; - - case TABLE: - { - const Table& a = *(Table*)m_value; - t.printf("{\n"); - t.pushIndent(); - Table::Iterator i = a.begin(); - const Table::Iterator end = a.end(); - while (i != end) { - // Quote names that are not legal C++ identifiers - if (! legalIdentifier(i->key)) { - t.printf("'%s' ", i->key.c_str()); - } else { - t.writeSymbol(i->key); - } - t.printf("= "); - - i->value.serialize(t); - - if (i != end) { - t.printf("\n"); - } - ++i; - } - t.popIndent(); - t.printf("}"); - } - break; - - default: - debugAssertM(false, "Internal error: no serialize method for this type."); - } -} - - -std::string AnyVal::toString() const { - TextOutput t; - serialize(t); - std::string s; - t.commitString(s); - return s; -} - -/* -void AnyVal::serialize(G3D::BinaryOutput& t) const { - alwaysAssertM(false, "TODO"); -} -*/ - -void AnyVal::deserialize(G3D::TextInput& t) { - deleteValue(); - m_type = NIL; - m_value = NULL; - - if (! t.hasMore()) { - return; - } - - switch (t.peek().type()) { - case Token::END: - // should never get here because of the hasMore check above - return; - break; - - case Token::NUMBER: - m_type = NUMBER; - m_value = new double(t.readNumber()); - break; - - case Token::STRING: - m_type = STRING; - m_value = new std::string(t.readString()); - break; - - case Token::BOOLEAN: - m_type = BOOLEAN; - m_value = new bool(t.readBoolean()); - break; - - case Token::SYMBOL: - { - std::string s = t.readSymbol(); - if (s == "NIL") { - break; - - } else if (s == "true") { - - m_type = BOOLEAN; - m_value = new bool(true); - - } else if (s == "false") { - - m_type = BOOLEAN; - m_value = new bool(false); - - } else if (s == "R") { - - m_type = RECT2D; - t.readSymbol("("); - float x,y,w,h; - x = (float)t.readNumber(); - t.readSymbol(","); - y = (float)t.readNumber(); - t.readSymbol(","); - w = (float)t.readNumber(); - t.readSymbol(","); - h = (float)t.readNumber(); - t.readSymbol(")"); - m_value = new Rect2D(Rect2D::xywh(x, y, w, h)); - - } else if (s == "AAB") { - - m_type = AABOX; - Vector3 v[2]; - t.readSymbol("("); - for (int i = 0; i < 2; ++i) { - t.readSymbols("V3", "("); - v[i].x = (float)t.readNumber(); - t.readSymbol(","); - v[i].y = (float)t.readNumber(); - t.readSymbol(","); - v[i].z = (float)t.readNumber(); - t.readSymbol(","); - if (i == 0) { - t.readSymbol(","); - } - } - t.readSymbol(")"); - m_value = new AABox(v[0], v[1]); - - } else if (s == "V2") { - - t.readSymbol("("); - Vector2 v; - v.x = (float)t.readNumber(); - t.readSymbol(","); - v.y = (float)t.readNumber(); - t.readSymbol(")"); - m_value = new Vector2(v); - m_type = VECTOR2; - - } else if (s == "V3") { - - t.readSymbol("("); - Vector3 v; - v.x = (float)t.readNumber(); - t.readSymbol(","); - v.y = (float)t.readNumber(); - t.readSymbol(","); - v.z = (float)t.readNumber(); - t.readSymbol(")"); - m_value = new Vector3(v); - m_type = VECTOR3; - - } else if (s == "V4") { - - t.readSymbol("("); - Vector4 v; - v.x = (float)t.readNumber(); - t.readSymbol(","); - v.y = (float)t.readNumber(); - t.readSymbol(","); - v.z = (float)t.readNumber(); - t.readSymbol(","); - v.w = (float)t.readNumber(); - t.readSymbol(")"); - m_value = new Vector4(v); - m_type = VECTOR4; - - } else if (s == "M2") { - - t.readSymbol("("); - Matrix2 m; - for (int r = 0; r < 2; ++r) { - for (int c = 0; c < 2; ++c) { - m[r][c] = (float)t.readNumber(); - if ((c != 1) || (r != 1)) { - t.readSymbol(","); - } - } - } - t.readSymbol(")"); - m_value = new Matrix2(m); - m_type = MATRIX2; - - } else if (s == "M3") { - - t.readSymbol("("); - Matrix3 m; - for (int r = 0; r < 3; ++r) { - for (int c = 0; c < 3; ++c) { - m[r][c] = (float)t.readNumber(); - if ((c != 2) || (r != 2)) { - t.readSymbol(","); - } - } - } - t.readSymbol(")"); - m_value = new Matrix3(m); - m_type = MATRIX3; - - } else if (s == "M4") { - - t.readSymbol("("); - Matrix4 m; - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - m[r][c] = (float)t.readNumber(); - if ((c != 3) || (r != 3)) { - t.readSymbol(","); - } - } - } - t.readSymbol(")"); - m_value = new Matrix4(m); - m_type = MATRIX4; - - } else if (s == "Q") { - - t.readSymbol("("); - Quat q; - q.x = (float)t.readNumber(); - t.readSymbol(","); - q.y = (float)t.readNumber(); - t.readSymbol(","); - q.z = (float)t.readNumber(); - t.readSymbol(","); - q.w = (float)t.readNumber(); - t.readSymbol(")"); - m_value = new Quat(q); - m_type = QUAT; - - } else if (s == "CF") { - - t.readSymbol("("); - CoordinateFrame m; - if (t.peek().type() == Token::SYMBOL) { - // Angle format - float x, y, z, yaw, roll, pitch; - t.readSymbols("V3", "("); - x = (float)t.readNumber(); - t.readSymbol(","); - y = (float)t.readNumber(); - t.readSymbol(","); - z = (float)t.readNumber(); - t.readSymbols(")", ","); - yaw = (float)t.readNumber(); - t.readSymbol(","); - pitch = (float)t.readNumber(); - roll = 0; - if (t.peek().string() == ",") { - t.readSymbol(","); - roll = (float)t.readNumber(); - } - m = CoordinateFrame::fromXYZYPRDegrees(x, y, z, yaw, pitch, roll); - } else { - // Matrix format - for (int r = 0; r < 3; ++r) { - for (int c = 0; c < 3; ++c) { - m.rotation[r][c] = (float)t.readNumber(); - } - m.translation[r] = (float)t.readNumber(); - if (r != 2) { - t.readSymbol(","); - } - } - } - t.readSymbol(")"); - m_value = new CoordinateFrame(m); - m_type = COORDINATEFRAME; - - } else if (s == "C1") { - - t.readSymbol("("); - float v = (float)t.readNumber(); - t.readSymbol(")"); - m_value = new Color1(v); - m_type = COLOR1; - - } else if (s == "C3") { - - t.readSymbol("("); - Color3 c; - c.r = (float)t.readNumber(); - t.readSymbol(","); - c.g = (float)t.readNumber(); - t.readSymbol(","); - c.b = (float)t.readNumber(); - t.readSymbol(")"); - m_value = new Color3(c); - m_type = COLOR3; - - } else if (s == "C4") { - - t.readSymbol("("); - Color4 c; - c.r = (float)t.readNumber(); - t.readSymbol(","); - c.g = (float)t.readNumber(); - t.readSymbol(","); - c.b = (float)t.readNumber(); - t.readSymbol(","); - c.a = (float)t.readNumber(); - t.readSymbol(")"); - m_value = new Color4(c); - m_type = COLOR4; - - } else if (s == "[") { - - // Array - m_type = ARRAY; - m_value = new Array(); - m_referenceCount = new int(1); - Array& a = *(Array*)m_value; - - Token peek = t.peek(); - while ((peek.type() != Token::SYMBOL) || (peek.string() != "]")) { - // Avoid copying large objects - a.next().deserialize(t); - - peek = t.peek(); - if (peek.type() != Token::SYMBOL) { - throw CorruptText("Expected ',' or ']'", peek); - } else if (peek.string() == ",") { - t.readSymbol(","); - } else if (peek.string() != "]") { - throw CorruptText("Missing ']'", peek); - } - } - t.readSymbol("]"); - - } else if (s == "{") { - - // Table - m_type = TABLE; - m_value = new Table(); - m_referenceCount = new int(1); - Table& a = *(Table*)m_value; - - Token peek = t.peek(); - while ((peek.type() != Token::SYMBOL) || (peek.string() != "}")) { - - std::string key; - // Get the name - if (peek.type() == Token::SYMBOL) { - key = t.readSymbol(); - } else if (peek.extendedType() == Token::SINGLE_QUOTED_TYPE) { - key = t.readString(); - } else { - throw CorruptText("Expected name inside table", peek); - } - - t.readSymbol("="); - - // Avoid copying large values - a.set(key, AnyVal()); - a[key].deserialize(t); - - peek = t.peek(); - if ((peek.type() != Token::SYMBOL) && (peek.extendedType() == Token::SINGLE_QUOTED_TYPE)) { - throw CorruptText("Missing expected name or '}'", peek); - } - } - t.readSymbol("}"); - - } else { - throw CorruptText("Invalid value type.", t.peek()); - } // dispatch on symbol type - } // scope - break; - } -} - -/* -void AnyVal::deserialize(G3D::BinaryInput& t) { - alwaysAssertM(false, "TODO"); -} -*/ - - -AnyVal& AnyVal::operator[](const char* key) { - return this->operator[]((std::string)key); -} - - -const AnyVal& AnyVal::operator[](const char* key) const { - return this->operator[]((std::string)key); -} - - -AnyVal& AnyVal::operator[](const std::string& key) { - if (m_type != TABLE) { - throw WrongType(TABLE, m_type); - } - - makeMutable(); - - Table& t = *(Table*)m_value; - - if (! t.containsKey(key)) { - t.set(key, AnyVal()); - } - - return t[key]; -} - - -const AnyVal& AnyVal::operator[](const std::string& key) const { - if (m_type != TABLE) { - throw WrongType(TABLE, m_type); - } - - const Table& t = *(const Table*)m_value; - - if (! t.containsKey(key)) { - throw KeyNotFound(key); - } - - return t[key]; -} - - -void AnyVal::append(const AnyVal& v) { - if (m_type != ARRAY) { - throw WrongType(ARRAY, m_type); - } - makeMutable(); - - Array& a = *(Array*)m_value; - a.append(v); -} - - -void AnyVal::getKeys(Array& keys) const { - if (m_type != TABLE) { - throw WrongType(TABLE, m_type); - } - - const Table& t = *(const Table*)m_value; - t.getKeys(keys); -} - - -int AnyVal::size() const { - switch (m_type) { - case TABLE: - { - const Table& t = *(const Table*)m_value; - return t.size(); - } - - case ARRAY: - { - const Array& a = *(Array*)m_value; - return a.size(); - } - - default: - throw WrongType(ARRAY, m_type); - } -} - - -AnyVal& AnyVal::operator[](int i) { - if (m_type != ARRAY) { - throw WrongType(ARRAY, m_type); - } - makeMutable(); - - Array& a = *(Array*)m_value; - - if (i < 0) { - throw IndexOutOfBounds(i, a.size()); - } - - if (a.size() <= i) { - a.resize(i + 1); - } - - return a[i]; -} - - -const AnyVal& AnyVal::operator[](int i) const { - if (m_type != ARRAY) { - throw WrongType(ARRAY, m_type); - } - - const Array& a = *(Array*)m_value; - - if (a.size() <= i || i < 0) { - throw IndexOutOfBounds(i, a.size()); - } - - return a[i]; -} - - -void AnyVal::makeMutable() { - if (*m_referenceCount > 1) { - // This is a shared instance - --(*m_referenceCount); - m_referenceCount = new int(1); - m_value = copyValue(); - } -} - -bool AnyVal::boolean() const { - if (m_type != BOOLEAN) { - throw WrongType(BOOLEAN, m_type); - } - - return *(bool*)m_value; -} - - -bool AnyVal::boolean(bool defaultVal) const { - if (m_type != BOOLEAN) { - return defaultVal; - } - - return *(bool*)m_value; -} - - -const std::string& AnyVal::string() const { - if (m_type != STRING) { - throw WrongType(STRING, m_type); - } - - return *(std::string*)m_value; -} - - -const std::string& AnyVal::string(const std::string& defaultVal) const { - if (m_type != STRING) { - return defaultVal; - } else { - return *(std::string*)m_value; - } -} - - -double AnyVal::number() const { - if (m_type != NUMBER) { - throw WrongType(NUMBER, m_type); - } - - return *(double*)m_value; -} - - -double AnyVal::number(double defaultVal) const { - if (m_type != NUMBER) { - return defaultVal; - } else { - return *(double*)m_value; - } -} - - -const Rect2D& AnyVal::rect2D() const { - if (m_type != RECT2D) { - throw WrongType(RECT2D, m_type); - } - - return *(Rect2D*)m_value; -} - - -const Rect2D& AnyVal::rect2D(const Rect2D& defaultVal) const { - if (m_type != RECT2D) { - return defaultVal; - } else { - return *(Rect2D*)m_value; - } -} - - -const AABox& AnyVal::aabox() const { - if (m_type != AABOX) { - throw WrongType(AABOX, m_type); - } - - return *(AABox*)m_value; -} - - -const AABox& AnyVal::aabox(const AABox& defaultVal) const { - if (m_type != AABOX) { - return defaultVal; - } else { - return *(AABox*)m_value; - } -} - - -const Color1& AnyVal::color1() const { - if (m_type != COLOR1) { - throw WrongType(COLOR1, m_type); - } - - return *(Color1*)m_value; -} - - -const Color1& AnyVal::color1(const Color1& defaultVal) const { - if (m_type != COLOR1) { - return defaultVal; - } else { - return *(Color1*)m_value; - } -} - - -const Color3& AnyVal::color3() const { - if (m_type != COLOR3) { - throw WrongType(COLOR3, m_type); - } - - return *(Color3*)m_value; -} - - -const Color3& AnyVal::color3(const Color3& defaultVal) const { - if (m_type != COLOR3) { - return defaultVal; - } else { - return *(Color3*)m_value; - } -} - - -const Color4& AnyVal::color4() const { - if (m_type != COLOR4) { - throw WrongType(COLOR4, m_type); - } - - return *(Color4*)m_value; -} - - -const Color4& AnyVal::color4(const Color4& defaultVal) const { - if (m_type != COLOR4) { - return defaultVal; - } else { - return *(Color4*)m_value; - } -} - - -const Vector2& AnyVal::vector2() const { - if (m_type != VECTOR2) { - throw WrongType(VECTOR2, m_type); - } - - return *(Vector2*)m_value; -} - - -const Vector2& AnyVal::vector2(const Vector2& defaultVal) const { - if (m_type != VECTOR2) { - return defaultVal; - } else { - return *(Vector2*)m_value; - } -} - - -const Vector3& AnyVal::vector3() const { - if (m_type != VECTOR3) { - throw WrongType(VECTOR3, m_type); - } - - return *(Vector3*)m_value; -} - - -const Vector3& AnyVal::vector3(const Vector3& defaultVal) const { - if (m_type != VECTOR3) { - return defaultVal; - } else { - return *(Vector3*)m_value; - } -} - - -const Vector4& AnyVal::vector4() const { - if (m_type != VECTOR4) { - throw WrongType(VECTOR4, m_type); - } - - return *(Vector4*)m_value; -} - - -const Vector4& AnyVal::vector4(const Vector4& defaultVal) const { - if (m_type != VECTOR4) { - return defaultVal; - } else { - return *(Vector4*)m_value; - } -} - - -const CoordinateFrame& AnyVal::coordinateFrame() const { - if (m_type != COORDINATEFRAME) { - throw WrongType(COORDINATEFRAME, m_type); - } - - return *(CoordinateFrame*)m_value; -} - - -const CoordinateFrame& AnyVal::coordinateFrame(const CoordinateFrame& defaultVal) const { - if (m_type != COORDINATEFRAME) { - return defaultVal; - } else { - return *(CoordinateFrame*)m_value; - } -} - -const Matrix2& AnyVal::matrix2(const Matrix2& defaultVal) const { - if (m_type != MATRIX2) { - return defaultVal; - } else { - return *(Matrix2*)m_value; - } -} - - -const Matrix2& AnyVal::matrix2() const { - if (m_type != MATRIX2) { - throw WrongType(MATRIX2, m_type); - } - - return *(Matrix2*)m_value; -} - - -const Matrix3& AnyVal::matrix3(const Matrix3& defaultVal) const { - if (m_type != MATRIX3) { - return defaultVal; - } else { - return *(Matrix3*)m_value; - } -} - - -const Matrix3& AnyVal::matrix3() const { - if (m_type != MATRIX3) { - throw WrongType(MATRIX3, m_type); - } - - return *(Matrix3*)m_value; -} - - -const Matrix4& AnyVal::matrix4(const Matrix4& defaultVal) const { - if (m_type != MATRIX4) { - return defaultVal; - } else { - return *(Matrix4*)m_value; - } -} - - -const Matrix4& AnyVal::matrix4() const { - if (m_type != MATRIX4) { - throw WrongType(MATRIX4, m_type); - } - - return *(Matrix4*)m_value; -} - - -const Quat& AnyVal::quat(const Quat& defaultVal) const { - if (m_type != QUAT) { - return defaultVal; - } else { - return *(Quat*)m_value; - } -} - - -const Quat& AnyVal::quat() const { - if (m_type != QUAT) { - throw WrongType(QUAT, m_type); - } - - return *(Quat*)m_value; -} - - -const AnyVal& AnyVal::get(const std::string& key, const AnyVal& defaultVal) const { - if (m_type != TABLE) { - return defaultVal; - } - - const Table& t = *(const Table*)m_value; - - if (t.containsKey(key)) { - return t[key]; - } else { - return defaultVal; - } -} - - -const AnyVal& AnyVal::get(const std::string& key) const { - if (m_type != TABLE) { - throw WrongType(TABLE, m_type); - } - - const Table& t = *(const Table*)m_value; - - if (t.containsKey(key)) { - return t[key]; - } else { - throw KeyNotFound(key); - } -} - - -const AnyVal& AnyVal::get(int i, const AnyVal& defaultVal) const { - if (m_type != ARRAY) { - return defaultVal; - } - - const Array& a = *(const Array*)m_value; - - if ((i >= 0) && (i < a.size())) { - return a[i]; - } else { - return defaultVal; - } -} - - -const AnyVal& AnyVal::get(int i) const { - if (m_type != ARRAY) { - throw WrongType(ARRAY, m_type); - } - - const Array& a = *(const Array*)m_value; - - if ((i >= 0) && (i < a.size())) { - return a[i]; - } else { - throw IndexOutOfBounds(i, a.size()); - } -} - -} diff --git a/externals/g3dlite/G3D.lib/source/BinaryFormat.cpp b/externals/g3dlite/G3D.lib/source/BinaryFormat.cpp deleted file mode 100644 index a30ec0644ea..00000000000 --- a/externals/g3dlite/G3D.lib/source/BinaryFormat.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/** - @file BinaryFormat.cpp - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2005-06-10 - @edited 2005-06-10 - */ - -#include "G3D/BinaryFormat.h" - -namespace G3D { - -int32 byteSize(BinaryFormat f) { - switch (f) { - case BOOL8_BINFMT: - case UINT8_BINFMT: - case INT8_BINFMT: - return 1; - - case UINT16_BINFMT: - case INT16_BINFMT: - return 2; - - case FLOAT16_BINFMT: - return 2; - - case UINT32_BINFMT: - case INT32_BINFMT: - case FLOAT32_BINFMT: - return 4; - - case FLOAT64_BINFMT: - case UINT64_BINFMT: - case INT64_BINFMT: - return 8; - - case INT128_BINFMT: - case UINT128_BINFMT: - return 16; - - case VECTOR2_BINFMT: - return 2 * 4; - - case VECTOR2INT16_BINFMT: - return 2 * 2; - - case VECTOR3_BINFMT: - return 3 * 4; - - case VECTOR3INT16_BINFMT: - return 3 * 2; - - case VECTOR4_BINFMT: - return 4 * 4; - - case VECTOR4INT16_BINFMT: - return 4 * 4; - - case COLOR3_BINFMT: - return 3 * 4; - - case COLOR3UINT8_BINFMT: - return 3 * 1; - - case COLOR3INT16_BINFMT: - return 3 * 2; - - case COLOR4_BINFMT: - return 4 * 4; - - case COLOR4UINT8_BINFMT: - return 4 * 1; - - case COLOR4INT16_BINFMT: - return 4 * 2; - - default: - return -1; - } -} -} diff --git a/externals/g3dlite/G3D.lib/source/BinaryInput.cpp b/externals/g3dlite/G3D.lib/source/BinaryInput.cpp deleted file mode 100644 index 65a9976fe04..00000000000 --- a/externals/g3dlite/G3D.lib/source/BinaryInput.cpp +++ /dev/null @@ -1,568 +0,0 @@ -/** - @file BinaryInput.cpp - - @author Morgan McGuire, graphics3d.com - Copyright 2001-2007, Morgan McGuire. All rights reserved. - - @created 2001-08-09 - @edited 2005-02-24 - - -

-    {    
-    BinaryOutput b("c:/tmp/test.b", BinaryOutput::LITTLE_ENDIAN);
-
-    float f = 3.1415926;
-    int i = 1027221;
-    std::string s = "Hello World!";
-
-    b.writeFloat32(f);
-    b.writeInt32(i);
-    b.writeString(s);
-    b.commit();
-    
-
-    BinaryInput in("c:/tmp/test.b", BinaryInput::LITTLE_ENDIAN);
-
-    debugAssert(f == in.readFloat32());
-    int ii = in.readInt32();
-    debugAssert(i == ii);
-    debugAssert(s == in.readString());
-    }
-  
- */ - -#include "G3D/platform.h" -#include "G3D/BinaryInput.h" -#include "G3D/Array.h" -#include "G3D/fileutils.h" -#include "G3D/Log.h" -#include - -#include - -namespace G3D { - -void BinaryInput::readBool8(std::vector& out, int64 n) { - out.resize((int)n); - // std::vector optimizes bool in a way that prevents fast reading - for (int64 i = 0; i < n ; ++i) { - out[i] = readBool8(); - } -} - - -void BinaryInput::readBool8(Array& out, int64 n) { - out.resize(n); - readBool8(out.begin(), n); -} - - -#define IMPLEMENT_READER(ucase, lcase)\ -void BinaryInput::read##ucase(std::vector& out, int64 n) {\ - out.resize(n);\ - read##ucase(&out[0], n);\ -}\ -\ -\ -void BinaryInput::read##ucase(Array& out, int64 n) {\ - out.resize(n);\ - read##ucase(out.begin(), n);\ -} - - -IMPLEMENT_READER(UInt8, uint8) -IMPLEMENT_READER(Int8, int8) -IMPLEMENT_READER(UInt16, uint16) -IMPLEMENT_READER(Int16, int16) -IMPLEMENT_READER(UInt32, uint32) -IMPLEMENT_READER(Int32, int32) -IMPLEMENT_READER(UInt64, uint64) -IMPLEMENT_READER(Int64, int64) -IMPLEMENT_READER(Float32, float32) -IMPLEMENT_READER(Float64, float64) - -#undef IMPLEMENT_READER - -// Data structures that are one byte per element can be -// directly copied, regardles of endian-ness. -#define IMPLEMENT_READER(ucase, lcase)\ -void BinaryInput::read##ucase(lcase* out, int64 n) {\ - if (sizeof(lcase) == 1) {\ - readBytes(out, n);\ - } else {\ - for (int64 i = 0; i < n ; ++i) {\ - out[i] = read##ucase();\ - }\ - }\ -} - -IMPLEMENT_READER(Bool8, bool) -IMPLEMENT_READER(UInt8, uint8) -IMPLEMENT_READER(Int8, int8) - -#undef IMPLEMENT_READER - - -#define IMPLEMENT_READER(ucase, lcase)\ -void BinaryInput::read##ucase(lcase* out, int64 n) {\ - if (m_swapBytes) {\ - for (int64 i = 0; i < n; ++i) {\ - out[i] = read##ucase();\ - }\ - } else {\ - readBytes(out, sizeof(lcase) * n);\ - }\ -} - - -IMPLEMENT_READER(UInt16, uint16) -IMPLEMENT_READER(Int16, int16) -IMPLEMENT_READER(UInt32, uint32) -IMPLEMENT_READER(Int32, int32) -IMPLEMENT_READER(UInt64, uint64) -IMPLEMENT_READER(Int64, int64) -IMPLEMENT_READER(Float32, float32) -IMPLEMENT_READER(Float64, float64) - -#undef IMPLEMENT_READER - -void BinaryInput::loadIntoMemory(int64 startPosition, int64 minLength) { - // Load the next section of the file - debugAssertM(m_filename != "", "Read past end of file."); - - int64 absPos = m_alreadyRead + m_pos; - - if (m_bufferLength < minLength) { - // The current buffer isn't big enough to hold the chunk we want to read. - // This happens if there was little memory available during the initial constructor - // read but more memory has since been freed. - m_bufferLength = minLength; - debugAssert(m_freeBuffer); - m_buffer = (uint8*)System::realloc(m_buffer, m_bufferLength); - if (m_buffer == NULL) { - throw "Tried to read a larger memory chunk than could fit in memory. (2)"; - } - } - - m_alreadyRead = startPosition; - -# ifdef G3D_WIN32 - FILE* file = fopen(m_filename.c_str(), "rb"); - debugAssert(file); - int ret = fseek(file, (off_t)m_alreadyRead, SEEK_SET); - debugAssert(ret == 0); - size_t toRead = (size_t)G3D::min(m_bufferLength, m_length - m_alreadyRead); - ret = fread(m_buffer, 1, toRead, file); - debugAssert(ret == toRead); - fclose(file); - file = NULL; - -# else - FILE* file = fopen(m_filename.c_str(), "rb"); - debugAssert(file); - int ret = fseeko(file, (off_t)m_alreadyRead, SEEK_SET); - debugAssert(ret == 0); - size_t toRead = (size_t)G3D::min(m_bufferLength, m_length - m_alreadyRead); - ret = fread(m_buffer, 1, toRead, file); - debugAssert((size_t)ret == (size_t)toRead); - fclose(file); - file = NULL; -# endif - - m_pos = absPos - m_alreadyRead; - debugAssert(m_pos >= 0); -} - - - -const bool BinaryInput::NO_COPY = false; - -static bool needSwapBytes(G3DEndian fileEndian) { - return (fileEndian != System::machineEndian()); -} - - -/** Helper used by the constructors for decompression */ -static uint32 readUInt32(const uint8* data, bool swapBytes) { - if (swapBytes) { - uint8 out[4]; - out[0] = data[3]; - out[1] = data[2]; - out[2] = data[1]; - out[3] = data[0]; - return *((uint32*)out); - } else { - return *((uint32*)data); - } -} - - -void BinaryInput::setEndian(G3DEndian e) { - m_fileEndian = e; - m_swapBytes = needSwapBytes(m_fileEndian); -} - - -BinaryInput::BinaryInput( - const uint8* data, - int64 dataLen, - G3DEndian dataEndian, - bool compressed, - bool copyMemory) : - m_filename(""), - m_bitPos(0), - m_bitString(0), - m_beginEndBits(0), - m_alreadyRead(0), - m_bufferLength(0), - m_pos(0) { - - m_freeBuffer = copyMemory || compressed; - - setEndian(dataEndian); - - if (compressed) { - // Read the decompressed size from the first 4 bytes - m_length = G3D::readUInt32(data, m_swapBytes); - - debugAssert(m_freeBuffer); - m_buffer = (uint8*)System::alignedMalloc(m_length, 16); - - unsigned long L = m_length; - // Decompress with zlib - int64 result = uncompress(m_buffer, (unsigned long*)&L, data + 4, dataLen - 4); - m_length = L; - m_bufferLength = L; - debugAssert(result == Z_OK); (void)result; - - } else { - m_length = dataLen; - m_bufferLength = m_length; - if (! copyMemory) { - debugAssert(!m_freeBuffer); - m_buffer = const_cast(data); - } else { - debugAssert(m_freeBuffer); - m_buffer = (uint8*)System::alignedMalloc(m_length, 16); - System::memcpy(m_buffer, data, dataLen); - } - } -} - - -BinaryInput::BinaryInput( - const std::string& filename, - G3DEndian fileEndian, - bool compressed) : - m_filename(filename), - m_bitPos(0), - m_bitString(0), - m_beginEndBits(0), - m_alreadyRead(0), - m_length(0), - m_bufferLength(0), - m_buffer(NULL), - m_pos(0), - m_freeBuffer(true) { - - setEndian(fileEndian); - - // Update global file tracker - _internal::currentFilesUsed.insert(m_filename); - - - if (! fileExists(m_filename, false)) { - std::string zipfile; - std::string internalfile; - if (zipfileExists(m_filename, zipfile, internalfile)) { - // Load from zipfile - void* v; - size_t s; - zipRead(filename, v, s); - m_buffer = reinterpret_cast(v); - m_bufferLength = m_length = s; - if (compressed) { - decompress(); - } - m_freeBuffer = true; - } else { - Log::common()->printf("Warning: File not found: %s\n", m_filename.c_str()); - } - return; - } - - // Figure out how big the file is and verify that it exists. - m_length = fileLength(m_filename); - - // Read the file into memory - FILE* file = fopen(m_filename.c_str(), "rb"); - - if (! file || (m_length == -1)) { - throw format("File not found: \"%s\"", m_filename.c_str()); - return; - } - - if (! compressed && (m_length > INITIAL_BUFFER_LENGTH)) { - // Read only a subset of the file so we don't consume - // all available memory. - m_bufferLength = INITIAL_BUFFER_LENGTH; - } else { - // Either the length is fine or the file is compressed - // and requires us to read the whole thing for zlib. - m_bufferLength = m_length; - } - - debugAssert(m_freeBuffer); - m_buffer = (uint8*)System::alignedMalloc(m_bufferLength, 16); - if (m_buffer == NULL) { - if (compressed) { - throw "Not enough memory to load compressed file. (1)"; - } - - // Try to allocate a small array; not much memory is available. - // Give up if we can't allocate even 1k. - while ((m_buffer == NULL) && (m_bufferLength > 1024)) { - m_bufferLength /= 2; - m_buffer = (uint8*)System::alignedMalloc(m_bufferLength, 16); - } - } - debugAssert(m_buffer); - - fread(m_buffer, m_bufferLength, sizeof(int8), file); - fclose(file); - file = NULL; - - if (compressed) { - if (m_bufferLength != m_length) { - throw "Not enough memory to load compressed file. (2)"; - } - - decompress(); - } -} - -void BinaryInput::decompress() { - // Decompress - // Use the existing buffer as the source, allocate - // a new buffer to use as the destination. - - int64 tempLength = m_length; - m_length = G3D::readUInt32(m_buffer, m_swapBytes); - - // The file couldn't have better than 500:1 compression - alwaysAssertM(m_length < m_bufferLength * 500, "Compressed file header is corrupted"); - - uint8* tempBuffer = m_buffer; - m_buffer = (uint8*)System::alignedMalloc(m_length, 16); - - debugAssert(m_buffer); - debugAssert(isValidHeapPointer(tempBuffer)); - debugAssert(isValidHeapPointer(m_buffer)); - - unsigned long L = m_length; - int64 result = uncompress(m_buffer, &L, tempBuffer + 4, tempLength - 4); - m_length = L; - m_bufferLength = m_length; - - debugAssertM(result == Z_OK, "BinaryInput/zlib detected corruption in " + m_filename); - (void)result; - - System::alignedFree(tempBuffer); -} - - -void BinaryInput::readBytes(void* bytes, int64 n) { - prepareToRead(n); - debugAssert(isValidPointer(bytes)); - - memcpy(bytes, m_buffer + m_pos, n); - m_pos += n; -} - - -BinaryInput::~BinaryInput() { - - if (m_freeBuffer) { - System::alignedFree(m_buffer); - } - m_buffer = NULL; -} - - -uint64 BinaryInput::readUInt64() { - prepareToRead(8); - uint8 out[8]; - - if (m_swapBytes) { - out[0] = m_buffer[m_pos + 7]; - out[1] = m_buffer[m_pos + 6]; - out[2] = m_buffer[m_pos + 5]; - out[3] = m_buffer[m_pos + 4]; - out[4] = m_buffer[m_pos + 3]; - out[5] = m_buffer[m_pos + 2]; - out[6] = m_buffer[m_pos + 1]; - out[7] = m_buffer[m_pos + 0]; - } else { - *(uint64*)out = *(uint64*)(m_buffer + m_pos); - } - - m_pos += 8; - return *(uint64*)out; -} - - -std::string BinaryInput::readString(int64 n) { - prepareToRead(n); - debugAssertM((m_pos + n) <= m_length, "Read past end of file"); - - char *s = (char*)System::alignedMalloc(n + 1, 16); - assert(s != NULL); - - memcpy(s, m_buffer + m_pos, n); - // There may not be a null, so make sure - // we add one. - s[n] = '\0'; - - std::string out = s; - System::alignedFree(s); - s = NULL; - - m_pos += n; - - return out; - -} - - -std::string BinaryInput::readString() { - int64 n = 0; - - if ((m_pos + m_alreadyRead + n) < (m_length - 1)) { - prepareToRead(1); - } - - if ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) && - (m_buffer[m_pos + n] != '\0')) { - - ++n; - while ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) && - (m_buffer[m_pos + n] != '\0')) { - - prepareToRead(1); - ++n; - } - } - - // Consume NULL - ++n; - - return readString(n); -} - - -std::string BinaryInput::readStringEven() { - std::string x = readString(); - if (hasMore() && (G3D::isOdd(x.length() + 1))) { - skip(1); - } - return x; -} - - -std::string BinaryInput::readString32() { - int len = readUInt32(); - return readString(len); -} - - -Vector4 BinaryInput::readVector4() { - float x = readFloat32(); - float y = readFloat32(); - float z = readFloat32(); - float w = readFloat32(); - return Vector4(x, y, z, w); -} - - -Vector3 BinaryInput::readVector3() { - float x = readFloat32(); - float y = readFloat32(); - float z = readFloat32(); - return Vector3(x, y, z); -} - - -Vector2 BinaryInput::readVector2() { - float x = readFloat32(); - float y = readFloat32(); - return Vector2(x, y); -} - - -Color4 BinaryInput::readColor4() { - float r = readFloat32(); - float g = readFloat32(); - float b = readFloat32(); - float a = readFloat32(); - return Color4(r, g, b, a); -} - - -Color3 BinaryInput::readColor3() { - float r = readFloat32(); - float g = readFloat32(); - float b = readFloat32(); - return Color3(r, g, b); -} - - -void BinaryInput::beginBits() { - debugAssert(m_beginEndBits == 0); - m_beginEndBits = 1; - m_bitPos = 0; - - debugAssertM(hasMore(), "Can't call beginBits when at the end of a file"); - m_bitString = readUInt8(); -} - - -uint32 BinaryInput::readBits(int numBits) { - debugAssert(m_beginEndBits == 1); - - uint32 out = 0; - - const int total = numBits; - while (numBits > 0) { - if (m_bitPos > 7) { - // Consume a new byte for reading. We do this at the beginning - // of the loop so that we don't try to read past the end of the file. - m_bitPos = 0; - m_bitString = readUInt8(); - } - - // Slide the lowest bit of the bitString into - // the correct position. - out |= (m_bitString & 1) << (total - numBits); - - // Shift over to the next bit - m_bitString = m_bitString >> 1; - ++m_bitPos; - --numBits; - } - - return out; -} - - -void BinaryInput::endBits() { - debugAssert(m_beginEndBits == 1); - if (m_bitPos == 0) { - // Put back the last byte we read - --m_pos; - } - m_beginEndBits = 0; - m_bitPos = 0; -} - -} diff --git a/externals/g3dlite/G3D.lib/source/BinaryOutput.cpp b/externals/g3dlite/G3D.lib/source/BinaryOutput.cpp deleted file mode 100644 index 8fcc30e548f..00000000000 --- a/externals/g3dlite/G3D.lib/source/BinaryOutput.cpp +++ /dev/null @@ -1,518 +0,0 @@ -/** - @file BinaryOutput.cpp - - @author Morgan McGuire, graphics3d.com - Copyright 2002-2007, Morgan McGuire, All rights reserved. - - @created 2002-02-20 - @edited 2008-01-07 - */ - -#include "G3D/platform.h" -#include "G3D/BinaryOutput.h" -#include "G3D/fileutils.h" -#include "G3D/stringutils.h" -#include "G3D/Array.h" -#include - -#include - -// Largest memory buffer that the system will use for writing to -// disk. After this (or if the system runs out of memory) -// chunks of the file will be dumped to disk. -// -// Currently 400 MB -#define MAX_BINARYOUTPUT_BUFFER_SIZE 400000000 - -namespace G3D { - -void BinaryOutput::writeBool8(const std::vector& out, int n) { - for (int i = 0; i < n; ++i) { - writeBool8(out[i]); - } -} - - -void BinaryOutput::writeBool8(const Array& out, int n) { - writeBool8(out.getCArray(), n); -} - -#define IMPLEMENT_WRITER(ucase, lcase)\ -void BinaryOutput::write##ucase(const std::vector& out, int n) {\ - write##ucase(&out[0], n);\ -}\ -\ -\ -void BinaryOutput::write##ucase(const Array& out, int n) {\ - write##ucase(out.getCArray(), n);\ -} - - -IMPLEMENT_WRITER(UInt8, uint8) -IMPLEMENT_WRITER(Int8, int8) -IMPLEMENT_WRITER(UInt16, uint16) -IMPLEMENT_WRITER(Int16, int16) -IMPLEMENT_WRITER(UInt32, uint32) -IMPLEMENT_WRITER(Int32, int32) -IMPLEMENT_WRITER(UInt64, uint64) -IMPLEMENT_WRITER(Int64, int64) -IMPLEMENT_WRITER(Float32, float32) -IMPLEMENT_WRITER(Float64, float64) - -#undef IMPLEMENT_WRITER - -// Data structures that are one byte per element can be -// directly copied, regardles of endian-ness. -#define IMPLEMENT_WRITER(ucase, lcase)\ -void BinaryOutput::write##ucase(const lcase* out, int n) {\ - if (sizeof(lcase) == 1) {\ - writeBytes((void*)out, n);\ - } else {\ - for (int i = 0; i < n ; ++i) {\ - write##ucase(out[i]);\ - }\ - }\ -} - -IMPLEMENT_WRITER(Bool8, bool) -IMPLEMENT_WRITER(UInt8, uint8) -IMPLEMENT_WRITER(Int8, int8) - -#undef IMPLEMENT_WRITER - - -#define IMPLEMENT_WRITER(ucase, lcase)\ -void BinaryOutput::write##ucase(const lcase* out, int n) {\ - if (m_swapBytes) {\ - for (int i = 0; i < n; ++i) {\ - write##ucase(out[i]);\ - }\ - } else {\ - writeBytes((const void*)out, sizeof(lcase) * n);\ - }\ -} - - -IMPLEMENT_WRITER(UInt16, uint16) -IMPLEMENT_WRITER(Int16, int16) -IMPLEMENT_WRITER(UInt32, uint32) -IMPLEMENT_WRITER(Int32, int32) -IMPLEMENT_WRITER(UInt64, uint64) -IMPLEMENT_WRITER(Int64, int64) -IMPLEMENT_WRITER(Float32, float32) -IMPLEMENT_WRITER(Float64, float64) - -#undef IMPLEMENT_WRITER - - -void BinaryOutput::reallocBuffer(size_t bytes, size_t oldBufferLen) { - //debugPrintf("reallocBuffer(%d, %d)\n", bytes, oldBufferLen); - - size_t newBufferLen = (int)(m_bufferLen * 1.5) + 100; - uint8* newBuffer = NULL; - - if ((m_filename == "") || (newBufferLen < MAX_BINARYOUTPUT_BUFFER_SIZE)) { - // We're either writing to memory (in which case we *have* to try and allocate) - // or we've been asked to allocate a reasonable size buffer. - - //debugPrintf(" realloc(%d)\n", newBufferLen); - newBuffer = (uint8*)System::realloc(m_buffer, newBufferLen); - if (newBuffer != NULL) { - m_maxBufferLen = newBufferLen; - } - } - - if ((newBuffer == NULL) && (bytes > 0)) { - // Realloc failed; we're probably out of memory. Back out - // the entire call and try to dump some data to disk. - m_bufferLen = oldBufferLen; - reserveBytesWhenOutOfMemory(bytes); - } else { - m_buffer = newBuffer; - debugAssert(isValidHeapPointer(m_buffer)); - } -} - - -void BinaryOutput::reserveBytesWhenOutOfMemory(size_t bytes) { - if (m_filename == "") { - throw "Out of memory while writing to memory in BinaryOutput (no RAM left)."; - } else if ((int)bytes > (int)m_maxBufferLen) { - throw "Out of memory while writing to disk in BinaryOutput (could not create a large enough buffer)."; - } else { - - // Dump the contents to disk. In order to enable seeking backwards, - // we keep the last 10 MB in memory. - int writeBytes = m_bufferLen - 10 * 1024 * 1024; - - if (writeBytes < m_bufferLen / 3) { - // We're going to write less than 1/3 of the file; - // give up and just write the whole thing. - writeBytes = m_bufferLen; - } - debugAssert(writeBytes > 0); - - //debugPrintf("Writing %d bytes to disk\n", writeBytes); - - const char* mode = (m_alreadyWritten > 0) ? "ab" : "wb"; - FILE* file = fopen(m_filename.c_str(), mode); - debugAssert(file); - - size_t count = fwrite(m_buffer, 1, writeBytes, file); - debugAssert((int)count == writeBytes); (void)count; - - fclose(file); - file = NULL; - - // Record that we saved this data. - m_alreadyWritten += writeBytes; - m_bufferLen -= writeBytes; - m_pos -= writeBytes; - - debugAssert(m_bufferLen < m_maxBufferLen); - debugAssert(m_bufferLen >= 0); - debugAssert(m_pos >= 0); - debugAssert(m_pos <= m_bufferLen); - - // Shift the unwritten data back appropriately in the buffer. - debugAssert(isValidHeapPointer(m_buffer)); - System::memcpy(m_buffer, m_buffer + writeBytes, m_bufferLen); - debugAssert(isValidHeapPointer(m_buffer)); - - // *now* we allocate bytes (there should presumably be enough - // space in the buffer; if not, we'll come back through this - // code and dump the last 10MB to disk as well. Note that the - // bytes > maxBufferLen case above would already have triggered - // if this call couldn't succeed. - reserveBytes(bytes); - } -} - - -BinaryOutput::BinaryOutput() { - m_alreadyWritten = 0; - m_swapBytes = false; - m_pos = 0; - m_filename = ""; - m_buffer = NULL; - m_bufferLen = 0; - m_maxBufferLen = 0; - m_beginEndBits = 0; - m_bitString = 0; - m_bitPos = 0; - m_ok = true; - m_committed = false; -} - - -BinaryOutput::BinaryOutput( - const std::string& filename, - G3DEndian fileEndian) { - - m_pos = 0; - m_alreadyWritten = 0; - setEndian(fileEndian); - m_filename = filename; - m_buffer = NULL; - m_bufferLen = 0; - m_maxBufferLen = 0; - m_beginEndBits = 0; - m_bitString = 0; - m_bitPos = 0; - m_committed = false; - - m_ok = true; - /** Verify ability to write to disk */ - commit(false); - m_committed = false; -} - - -void BinaryOutput::reset() { - debugAssert(m_beginEndBits == 0); - alwaysAssertM(m_filename == "", - "Can only reset a BinaryOutput that writes to memory."); - - // Do not reallocate, just clear the size of the buffer. - m_pos = 0; - m_alreadyWritten = 0; - m_bufferLen = 0; - m_beginEndBits = 0; - m_bitString = 0; - m_bitPos = 0; - m_committed = false; -} - - -BinaryOutput::~BinaryOutput() { - debugAssert((m_buffer == NULL) || isValidHeapPointer(m_buffer)); - System::free(m_buffer); - m_buffer = NULL; - m_bufferLen = 0; - m_maxBufferLen = 0; -} - - -void BinaryOutput::setEndian(G3DEndian fileEndian) { - m_fileEndian = fileEndian; - m_swapBytes = (fileEndian != System::machineEndian()); -} - - -bool BinaryOutput::ok() const { - return m_ok; -} - - -void BinaryOutput::compress() { - if (m_alreadyWritten > 0) { - throw "Cannot compress huge files (part of this file has already been written to disk)."; - } - - // Old buffer size - int L = m_bufferLen; - uint8* convert = (uint8*)&L; - - // Zlib requires the output buffer to be this big - unsigned long newSize = iCeil(m_bufferLen * 1.01) + 12; - uint8* temp = (uint8*)System::malloc(newSize); - int result = compress2(temp, &newSize, m_buffer, m_bufferLen, 9); - - debugAssert(result == Z_OK); (void)result; - - // Write the header - if (m_swapBytes) { - m_buffer[0] = convert[3]; - m_buffer[1] = convert[2]; - m_buffer[2] = convert[1]; - m_buffer[3] = convert[0]; - } else { - m_buffer[0] = convert[0]; - m_buffer[1] = convert[1]; - m_buffer[2] = convert[2]; - m_buffer[3] = convert[3]; - } - - // Write the data - if ((int64)newSize + 4 > (int64)m_maxBufferLen) { - m_maxBufferLen = newSize + 4; - m_buffer = (uint8*)System::realloc(m_buffer, m_maxBufferLen); - } - m_bufferLen = newSize + 4; - System::memcpy(m_buffer + 4, temp, newSize); - m_pos = m_bufferLen; - - System::free(temp); -} - - -void BinaryOutput::commit(bool flush) { - debugAssertM(! m_committed, "Cannot commit twice"); - m_committed = true; - debugAssertM(m_beginEndBits == 0, "Missing endBits before commit"); - - // Make sure the directory exists. - std::string root, base, ext, path; - Array pathArray; - parseFilename(m_filename, root, pathArray, base, ext); - - path = root + stringJoin(pathArray, '/'); - if (! fileExists(path, false)) { - createDirectory(path); - } - - const char* mode = (m_alreadyWritten > 0) ? "ab" : "wb"; - - FILE* file = fopen(m_filename.c_str(), mode); - - m_ok = (file != NULL) && m_ok; - - if (m_ok) { - debugAssertM(file, std::string("Could not open '") + m_filename + "'"); - - m_alreadyWritten += m_bufferLen; - - fwrite(m_buffer, m_bufferLen, 1, file); - if (flush) { - fflush(file); - } - fclose(file); - file = NULL; - } -} - - -void BinaryOutput::commit( - uint8* out) { - debugAssertM(! m_committed, "Cannot commit twice"); - m_committed = true; - - System::memcpy(out, m_buffer, m_bufferLen); -} - - -void BinaryOutput::writeUInt16(uint16 u) { - reserveBytes(2); - - uint8* convert = (uint8*)&u; - - if (m_swapBytes) { - m_buffer[m_pos] = convert[1]; - m_buffer[m_pos + 1] = convert[0]; - } else { - *(uint16*)(m_buffer + m_pos) = u; - } - - m_pos += 2; -} - - -void BinaryOutput::writeUInt32(uint32 u) { - reserveBytes(4); - - uint8* convert = (uint8*)&u; - - debugAssert(m_beginEndBits == 0); - - if (m_swapBytes) { - m_buffer[m_pos] = convert[3]; - m_buffer[m_pos + 1] = convert[2]; - m_buffer[m_pos + 2] = convert[1]; - m_buffer[m_pos + 3] = convert[0]; - } else { - *(uint32*)(m_buffer + m_pos) = u; - } - - m_pos += 4; -} - - -void BinaryOutput::writeUInt64(uint64 u) { - reserveBytes(8); - - uint8* convert = (uint8*)&u; - - if (m_swapBytes) { - m_buffer[m_pos] = convert[7]; - m_buffer[m_pos + 1] = convert[6]; - m_buffer[m_pos + 2] = convert[5]; - m_buffer[m_pos + 3] = convert[4]; - m_buffer[m_pos + 4] = convert[3]; - m_buffer[m_pos + 5] = convert[2]; - m_buffer[m_pos + 6] = convert[1]; - m_buffer[m_pos + 7] = convert[0]; - } else { - *(uint64*)(m_buffer + m_pos) = u; - } - - m_pos += 8; -} - - -void BinaryOutput::writeString(const char* s) { - // +1 is because strlen doesn't count the null - int len = strlen(s) + 1; - - debugAssert(m_beginEndBits == 0); - reserveBytes(len); - System::memcpy(m_buffer + m_pos, s, len); - m_pos += len; -} - - -void BinaryOutput::writeStringEven(const char* s) { - // +1 is because strlen doesn't count the null - int len = strlen(s) + 1; - - reserveBytes(len); - System::memcpy(m_buffer + m_pos, s, len); - m_pos += len; - - // Pad with another NULL - if ((len % 2) == 1) { - writeUInt8(0); - } -} - - -void BinaryOutput::writeString32(const char* s) { - writeUInt32(strlen(s) + 1); - writeString(s); -} - - -void BinaryOutput::writeVector4(const Vector4& v) { - writeFloat32(v.x); - writeFloat32(v.y); - writeFloat32(v.z); - writeFloat32(v.w); -} - - -void BinaryOutput::writeVector3(const Vector3& v) { - writeFloat32(v.x); - writeFloat32(v.y); - writeFloat32(v.z); -} - - -void BinaryOutput::writeVector2(const Vector2& v) { - writeFloat32(v.x); - writeFloat32(v.y); -} - - -void BinaryOutput::writeColor4(const Color4& v) { - writeFloat32(v.r); - writeFloat32(v.g); - writeFloat32(v.b); - writeFloat32(v.a); -} - - -void BinaryOutput::writeColor3(const Color3& v) { - writeFloat32(v.r); - writeFloat32(v.g); - writeFloat32(v.b); -} - - -void BinaryOutput::beginBits() { - debugAssertM(m_beginEndBits == 0, "Already in beginBits...endBits"); - m_bitString = 0x00; - m_bitPos = 0; - m_beginEndBits = 1; -} - - -void BinaryOutput::writeBits(uint32 value, int numBits) { - - while (numBits > 0) { - // Extract the current bit of value and - // insert it into the current byte - m_bitString |= (value & 1) << m_bitPos; - ++m_bitPos; - value = value >> 1; - --numBits; - - if (m_bitPos > 7) { - // We've reached the end of this byte - writeUInt8(m_bitString); - m_bitString = 0x00; - m_bitPos = 0; - } - } -} - - -void BinaryOutput::endBits() { - debugAssertM(m_beginEndBits == 1, "Not in beginBits...endBits"); - if (m_bitPos > 0) { - writeUInt8(m_bitString); - } - m_bitString = 0; - m_bitPos = 0; - m_beginEndBits = 0; -} - -} diff --git a/externals/g3dlite/G3D.lib/source/Box.cpp b/externals/g3dlite/G3D.lib/source/Box.cpp deleted file mode 100644 index 4b6c56388ec..00000000000 --- a/externals/g3dlite/G3D.lib/source/Box.cpp +++ /dev/null @@ -1,393 +0,0 @@ -/** - @file Box.cpp - Box class - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2001-06-02 - @edited 2006-02-05 -*/ - -#include "G3D/Box.h" -#include "G3D/debug.h" -#include "G3D/Plane.h" -#include "G3D/AABox.h" -#include "G3D/CoordinateFrame.h" - -namespace G3D { - -/** - Sets a field on four vertices. Used by the constructor. - */ -#define setMany(i0, i1, i2, i3, field, extreme) \ - _corner[i0].field = _corner[i1].field = \ - _corner[i2].field = _corner[i3].field = \ - (extreme).field - -Box::Box() { -} - - -Box::Box(const AABox& b) { - init(b.low(), b.high()); -} - -Box::Box(class BinaryInput& b) { - deserialize(b); -} - - -void Box::serialize(class BinaryOutput& b) const { - int i; - for (i = 0; i < 8; ++i) { - _corner[i].serialize(b); - } - - // Other state can be reconstructed -} - - -void Box::deserialize(class BinaryInput& b) { - int i; - - _center = Vector3::zero(); - for (i = 0; i < 8; ++i) { - _corner[i].deserialize(b); - _center += _corner[i]; - } - - _center = _center / 8; - - // Reconstruct other state from the corners - _axis[0] = _corner[5] - _corner[4]; - _axis[1] = _corner[7] - _corner[4]; - _axis[2] = _corner[0] - _corner[4]; - - for (i = 0; i < 3; ++i) { - _extent[i] = _axis[i].magnitude(); - _axis[i] /= _extent[i]; - } - - _volume = _extent.x * _extent.y * _extent.z; - - _area = 2 * - (_extent.x * _extent.y + - _extent.y * _extent.z + - _extent.z * _extent.x); -} - - -Box::Box( - const Vector3& min, - const Vector3& max) { - - init(min.min(max), min.max(max)); - -} - -void Box::init( - const Vector3& min, - const Vector3& max) { - - debugAssert( - (min.x <= max.x) && - (min.y <= max.y) && - (min.z <= max.z)); - - setMany(0, 1, 2, 3, z, max); - setMany(4, 5, 6, 7, z, min); - - setMany(1, 2, 5, 6, x, max); - setMany(0, 3, 4, 7, x, min); - - setMany(3, 2, 6, 7, y, max); - setMany(0, 1, 5, 4, y, min); - - _extent = max - min; - - _axis[0] = Vector3::unitX(); - _axis[1] = Vector3::unitY(); - _axis[2] = Vector3::unitZ(); - - if (_extent.isFinite()) { - _volume = _extent.x * _extent.y * _extent.z; - } else { - _volume = G3D::inf(); - } - - debugAssert(! isNaN(_extent.x)); - - _area = 2 * - (_extent.x * _extent.y + - _extent.y * _extent.z + - _extent.z * _extent.x); - - _center = (max + min) / 2; - - // If the extent is infinite along an axis, make the center zero to avoid NaNs - for (int i = 0; i < 3; ++i) { - if (! G3D::isFinite(_extent[i])) { - _center[i] = 0.0f; - } - } -} - - -float Box::volume() const { - return _volume; -} - - -float Box::area() const { - return _area; -} - - -void Box::getLocalFrame(CoordinateFrame& frame) const { - - frame.rotation = Matrix3( - _axis[0][0], _axis[1][0], _axis[2][0], - _axis[0][1], _axis[1][1], _axis[2][1], - _axis[0][2], _axis[1][2], _axis[2][2]); - - frame.translation = _center; -} - - -CoordinateFrame Box::localFrame() const { - CoordinateFrame out; - getLocalFrame(out); - return out; -} - - -void Box::getFaceCorners(int f, Vector3& v0, Vector3& v1, Vector3& v2, Vector3& v3) const { - switch (f) { - case 0: - v0 = _corner[0]; v1 = _corner[1]; v2 = _corner[2]; v3 = _corner[3]; - break; - - case 1: - v0 = _corner[1]; v1 = _corner[5]; v2 = _corner[6]; v3 = _corner[2]; - break; - - case 2: - v0 = _corner[7]; v1 = _corner[6]; v2 = _corner[5]; v3 = _corner[4]; - break; - - case 3: - v0 = _corner[2]; v1 = _corner[6]; v2 = _corner[7]; v3 = _corner[3]; - break; - - case 4: - v0 = _corner[3]; v1 = _corner[7]; v2 = _corner[4]; v3 = _corner[0]; - break; - - case 5: - v0 = _corner[1]; v1 = _corner[0]; v2 = _corner[4]; v3 = _corner[5]; - break; - - default: - debugAssert((f >= 0) && (f < 6)); - } -} - - - -int Box::dummy = 0; - -bool Box::culledBy( - const Array& plane, - int& cullingPlane, - const uint32 _inMask, - uint32& childMask) const { - - uint32 inMask = _inMask; - assert(plane.size() < 31); - - childMask = 0; - - // See if there is one plane for which all of the - // vertices are in the negative half space. - for (int p = 0; p < plane.size(); ++p) { - - // Only test planes that are not masked - if ((inMask & 1) != 0) { - - Vector3 corner; - - int numContained = 0; - int v = 0; - - // We can early-out only if we have found one point on each - // side of the plane (i.e. if we are straddling). That - // occurs when (numContained < v) && (numContained > 0) - for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) { - if (plane[p].halfSpaceContains(_corner[v])) { - ++numContained; - } - } - - if (numContained == 0) { - // Plane p culled the box - cullingPlane = p; - - // The caller should not recurse into the children, - // since the parent is culled. If they do recurse, - // make them only test against this one plane, which - // will immediately cull the volume. - childMask = 1 << p; - return true; - - } else if (numContained < v) { - // The bounding volume straddled the plane; we have - // to keep testing against this plane - childMask |= (1 << p); - } - } - - // Move on to the next bit. - inMask = inMask >> 1; - } - - // None of the planes could cull this box - cullingPlane = -1; - return false; -} - - -bool Box::culledBy( - const Array& plane, - int& cullingPlane, - const uint32 _inMask) const { - - uint32 inMask = _inMask; - assert(plane.size() < 31); - - // See if there is one plane for which all of the - // vertices are in the negative half space. - for (int p = 0; p < plane.size(); ++p) { - - // Only test planes that are not masked - if ((inMask & 1) != 0) { - - bool culled = true; - - int v; - - // Assume this plane culls all points. See if there is a point - // not culled by the plane... early out when at least one point - // is in the positive half space. - for (v = 0; (v < 8) && culled; ++v) { - culled = ! plane[p].halfSpaceContains(corner(v)); - } - - if (culled) { - // Plane p culled the box - cullingPlane = p; - - return true; - } - } - - // Move on to the next bit. - inMask = inMask >> 1; - } - - // None of the planes could cull this box - cullingPlane = -1; - return false; -} - - -bool Box::contains( - const Vector3& point) const { - - // Form axes from three edges, transform the point into that - // space, and perform 3 interval tests - - Vector3 u = _corner[4] - _corner[0]; - Vector3 v = _corner[3] - _corner[0]; - Vector3 w = _corner[1] - _corner[0]; - - Matrix3 M = Matrix3(u.x, v.x, w.x, - u.y, v.y, w.y, - u.z, v.z, w.z); - - // M^-1 * (point - _corner[0]) = point in unit cube's object space - // compute the inverse of M - Vector3 osPoint = M.inverse() * (point - _corner[0]); - - return - (osPoint.x >= 0) && - (osPoint.y >= 0) && - (osPoint.z >= 0) && - (osPoint.x <= 1) && - (osPoint.y <= 1) && - (osPoint.z <= 1); -} - -#undef setMany - - -void Box::getRandomSurfacePoint(Vector3& P, Vector3& N) const { - float aXY = _extent.x * _extent.y; - float aYZ = _extent.y * _extent.z; - float aZX = _extent.z * _extent.x; - - float r = (float)uniformRandom(0, aXY + aYZ + aZX); - - // Choose evenly between positive and negative face planes - float d = (uniformRandom(0, 1) < 0.5f) ? -1.0f : 1.0f; - - // The probability of choosing a given face is proportional to - // its area. - if (r < aXY) { - P = _axis[0] * (float)uniformRandom(-0.5, 0.5) * _extent.x + - _axis[1] * (float)uniformRandom(-0.5, 0.5) * _extent.y + - _center + _axis[2] * d * _extent.z * 0.5f; - N = _axis[2] * d; - } else if (r < aYZ) { - P = _axis[1] * (float)uniformRandom(-0.5, 0.5) * _extent.y + - _axis[2] * (float)uniformRandom(-0.5, 0.5) * _extent.z + - _center + _axis[0] * d * _extent.x * 0.5f; - N = _axis[0] * d; - } else { - P = _axis[2] * (float)uniformRandom(-0.5, 0.5) * _extent.z + - _axis[0] *(float) uniformRandom(-0.5, 0.5) * _extent.x + - _center + _axis[1] * d * _extent.y * 0.5f; - N = _axis[1] * d; - } -} - - -Vector3 Box::randomInteriorPoint() const { - Vector3 sum = _center; - - for (int a = 0; a < 3; ++a) { - sum += _axis[a] * (float)uniformRandom(-0.5, 0.5) * _extent[a]; - } - - return sum; -} - -Box Box::inf() { - return Box(-Vector3::inf(), Vector3::inf()); -} - -void Box::getBounds(class AABox& aabb) const { - - Vector3 lo = _corner[0]; - Vector3 hi = lo; - - for (int v = 1; v < 8; ++v) { - const Vector3& C = _corner[v]; - lo = lo.min(C); - hi = hi.max(C); - } - - aabb = AABox(lo, hi); -} - - -} // namespace diff --git a/externals/g3dlite/G3D.lib/source/Capsule.cpp b/externals/g3dlite/G3D.lib/source/Capsule.cpp deleted file mode 100644 index fbcb56fe97b..00000000000 --- a/externals/g3dlite/G3D.lib/source/Capsule.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/** - @file Capsule.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-02-07 - @edited 2005-08-18 - - Copyright 2000-2005, Morgan McGuire. - All rights reserved. - */ - -#include "G3D/Capsule.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/LineSegment.h" -#include "G3D/Sphere.h" -#include "G3D/CoordinateFrame.h" -#include "G3D/Line.h" -#include "G3D/AABox.h" - -namespace G3D { - -Capsule::Capsule(class BinaryInput& b) { - deserialize(b); -} - - -Capsule::Capsule() { -} - - -Capsule::Capsule(const Vector3& _p1, const Vector3& _p2, float _r) - : p1(_p1), p2(_p2), _radius(_r) { -} - - -void Capsule::serialize(class BinaryOutput& b) const { - p1.serialize(b); - p2.serialize(b); - b.writeFloat64(_radius); -} - - -void Capsule::deserialize(class BinaryInput& b) { - p1.deserialize(b); - p2.deserialize(b); - _radius = b.readFloat64(); -} - - -Line Capsule::axis() const { - return Line::fromTwoPoints(p1, p2); -} - - -float Capsule::volume() const { - return - // Sphere volume - pow(_radius, 3) * pi() * 4 / 3 + - - // Cylinder volume - pow(_radius, 2) * (p1 - p2).magnitude(); -} - - -float Capsule::area() const { - - return - // Sphere area - pow(_radius, 2) * 4 * pi() + - - // Cylinder area - twoPi() * _radius * (p1 - p2).magnitude(); -} - - -void Capsule::getBounds(AABox& out) const { - Vector3 min = p1.min(p2) - (Vector3(1, 1, 1) * _radius); - Vector3 max = p1.max(p2) + (Vector3(1, 1, 1) * _radius); - - out = AABox(min, max); -} - - -bool Capsule::contains(const Vector3& p) const { - return LineSegment::fromTwoPoints(p1, p2).distanceSquared(p) <= square(radius()); -} - - -void Capsule::getRandomSurfacePoint(Vector3& p, Vector3& N) const { - float h = height(); - float r = radius(); - - // Create a random point on a standard capsule and then rotate to the global frame. - - // Relative areas - float capRelArea = sqrt(r) / 2.0f; - float sideRelArea = r * h; - - float r1 = uniformRandom(0, capRelArea * 2 + sideRelArea); - - if (r1 < capRelArea * 2) { - - // Select a point uniformly at random on a sphere - N = Sphere(Vector3::zero(), 1).randomSurfacePoint(); - p = N * r; - p.y += sign(p.y) * h / 2.0f; - } else { - // Side - float a = uniformRandom(0, (float)twoPi()); - N.x = cos(a); - N.y = 0; - N.z = sin(a); - p.x = N.x * r; - p.z = N.y * r; - p.y = uniformRandom(-h / 2.0f, h / 2.0f); - } - - // Transform to world space - CoordinateFrame cframe; - getReferenceFrame(cframe); - - p = cframe.pointToWorldSpace(p); - N = cframe.normalToWorldSpace(N); -} - - -void Capsule::getReferenceFrame(CoordinateFrame& cframe) const { - cframe.translation = center(); - - Vector3 Y = (p1 - p2).direction(); - Vector3 X = (abs(Y.dot(Vector3::unitX())) > 0.9) ? Vector3::unitY() : Vector3::unitX(); - Vector3 Z = X.cross(Y).direction(); - X = Y.cross(Z); - cframe.rotation.setColumn(0, X); - cframe.rotation.setColumn(1, Y); - cframe.rotation.setColumn(2, Z); -} - - -Vector3 Capsule::randomInteriorPoint() const { - float h = height(); - float r = radius(); - - // Create a random point in a standard capsule and then rotate to the global frame. - - Vector3 p; - - float hemiVolume = pi() * (r*r*r) * 4 / 6.0; - float cylVolume = pi() * square(r) * h; - - float r1 = uniformRandom(0, 2.0 * hemiVolume + cylVolume); - - if (r1 < 2.0 * hemiVolume) { - - p = Sphere(Vector3::zero(), r).randomInteriorPoint(); - - p.y += sign(p.y) * h / 2.0f; - - } else { - - // Select a point uniformly at random on a disk - float a = uniformRandom(0, (float)twoPi()); - float r2 = sqrt(uniformRandom(0, 1)) * r; - - p = Vector3(cos(a) * r2, - uniformRandom(-h / 2.0f, h / 2.0f), - sin(a) * r2); - } - - // Transform to world space - CoordinateFrame cframe; - getReferenceFrame(cframe); - - return cframe.pointToWorldSpace(p); -} - -} // namespace diff --git a/externals/g3dlite/G3D.lib/source/CollisionDetection.cpp b/externals/g3dlite/G3D.lib/source/CollisionDetection.cpp deleted file mode 100644 index 16650bc1a96..00000000000 --- a/externals/g3dlite/G3D.lib/source/CollisionDetection.cpp +++ /dev/null @@ -1,2152 +0,0 @@ -/** - @file CollisionDetection.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @cite Bounce direction based on Paul Nettle's ftp://ftp.3dmaileffects.com/pub/FluidStudios/CollisionDetection/Fluid_Studios_Generic_Collision_Detection_for_Games_Using_Ellipsoids.pdf and comments by Max McGuire. Ray-sphere code by Eric Haines. - - @created 2001-11-24 - @edited 2008-10-10 - */ - -#include "G3D/CoordinateFrame.h" -#include "G3D/platform.h" -#include "G3D/CollisionDetection.h" -#include "G3D/debugAssert.h" -#include "G3D/vectorMath.h" -#include "G3D/Capsule.h" -#include "G3D/Plane.h" -#include "G3D/Line.h" -#include "G3D/LineSegment.h" -#include "G3D/Sphere.h" -#include "G3D/Box.h" -#include "G3D/Triangle.h" -#include "G3D/Vector3.h" -#include "G3D/AABox.h" - -namespace G3D { - -bool CollisionDetection::ignoreBool; -Vector3 CollisionDetection::ignore; -Array CollisionDetection::ignoreArray; - - - -Vector3 CollisionDetection::separatingAxisForSolidBoxSolidBox( - const int separatingAxisIndex, - const Box & box1, - const Box & box2) { - debugAssert(separatingAxisIndex >= 0); - debugAssert(separatingAxisIndex < 15); - Vector3 axis; - if (separatingAxisIndex < 3) { - axis = box1.axis(separatingAxisIndex); - } else if (separatingAxisIndex < 6) { - axis = box2.axis(separatingAxisIndex - 3); - } else { - int box1Index = (separatingAxisIndex - 6) / 3; - int box2Index = (separatingAxisIndex - 6) % 3; - axis = cross(box1.axis(box1Index), box2.axis(box2Index)); - } - return axis; -} - -#ifdef _MSC_VER -# pragma warning (push) -# pragma warning (disable : 4244) -#endif - -float CollisionDetection::projectedDistanceForSolidBoxSolidBox( - const int separatingAxisIndex, - const Vector3 & a, - const Vector3 & b, - const Vector3 & D, - const double* c, - const double* ca, - const double* ad, - const double* bd) -{ - (void)D; - - float R0 = 0.0f; - float R1 = 0.0f; - float R = 0.0f; - switch (separatingAxisIndex) { - case 0: - // A0 - R0 = a[0]; - R1 = b[0] * ca[0] + b[1] * ca[1] + b[2] * ca[2]; - R = fabs(ad[0]); - break; - case 1: - // A1 - R0 = a[1]; - R1 = b[0] * ca[3] + b[1] * ca[4] + b[2] * ca[5]; - R = fabs(ad[1]); - break; - case 2: - // A2 - R0 = a[2]; - R1 = b[0] * ca[6] + b[1] * ca[7] + b[2] * ca[8]; - R = fabs(ad[2]); - break; - case 3: - // B0 - R0 = a[0] * ca[0] + a[1] * ca[3] + a[2] * ca[6]; - R1 = b[0]; - R = fabs(bd[0]); - break; - case 4: - // B1 - R0 = a[0] * ca[1] + a[1] * ca[4] + a[2] * ca[7]; - R1 = b[1]; - R = fabs(bd[1]); - break; - case 5: - // B2 - R0 = a[0] * ca[2] + a[1] * ca[5] + a[2] * ca[8]; - R1 = b[2]; - R = fabs(bd[2]); - break; - case 6: - // A0 x B0 - R0 = a[1] * ca[6] + a[2] * ca[3]; - R1 = b[1] * ca[2] + b[2] * ca[1]; - R = fabs(c[3] * ad[2] - c[6] * ad[1]); - break; - case 7: - // A0 x B1 - R0 = a[1] * ca[7] + a[2] * ca[4]; - R1 = b[0] * ca[2] + b[2] * ca[0]; - R = fabs(c[4] * ad[2] - c[7] * ad[1]); - break; - case 8: - // A0 x B2 - R0 = a[1] * ca[8] + a[2] * ca[5]; - R1 = b[0] * ca[1] + b[1] * ca[0]; - R = fabs(c[5] * ad[2] - c[8] * ad[1]); - break; - case 9: - // A1 x B0 - R0 = a[0] * ca[6] + a[2] * ca[0]; - R1 = b[1] * ca[5] + b[2] * ca[4]; - R = fabs(c[6] * ad[0] - c[0] * ad[2]); - break; - case 10: - // A1 x B1 - R0 = a[0] * ca[7] + a[2] * ca[1]; - R1 = b[0] * ca[5] + b[2] * ca[3]; - R = fabs(c[7] * ad[0] - c[1] * ad[2]); - break; - case 11: - // A1 x B2 - R0 = a[0] * ca[8] + a[2] * ca[2]; - R1 = b[0] * ca[4] + b[1] * ca[3]; - R = fabs(c[8] * ad[0] - c[2] * ad[2]); - break; - case 12: - // A2 x B0 - R0 = a[0] * ca[3] + a[1] * ca[0]; - R1 = b[1] * ca[8] + b[2] * ca[7]; - R = fabs(c[0] * ad[1] - c[3] * ad[0]); - break; - case 13: - // A2 x B1 - R0 = a[0] * ca[4] + a[1] * ca[1]; - R1 = b[0] * ca[8] + b[2] * ca[6]; - R = fabs(c[1] * ad[1] - c[4] * ad[0]); - break; - case 14: - // A2 x B2 - R0 = a[0] * ca[5] + a[1] * ca[2]; - R1 = b[0] * ca[7] + b[1] * ca[6]; - R = fabs(c[2] * ad[1] - c[5] * ad[0]); - break; - default: - debugAssertM(false, "fell through switch statement"); - } - - return (R - (R0 + R1)); -} - - -bool CollisionDetection::parallelAxisForSolidBoxSolidBox( - const double* ca, - const double epsilon, - int & axis1, - int & axis2) { - const double parallelDot = 1.0 - epsilon; - for (int i = 0; i < 9; i++) { - if (ca[i] >= parallelDot) { - axis1 = i / 3; - axis2 = i % 3; - return true; - } - } - return false; -} - - - - -void CollisionDetection::fillSolidBoxSolidBoxInfo( - const Box & box1, - const Box & box2, - Vector3 & a, - Vector3 & b, - Vector3 & D, - double* c, - double* ca, - double* ad, - double* bd) { - // length between center and each side of box1 and box2 - a = box1.extent() * 0.5; - b = box2.extent() * 0.5; - - // difference between centers of box1 and box2 - D = box2.center() - box1.center(); - - // store the value of all possible dot products between the - // axes of box1 and box2, c_{row, col} in the Eberly paper - // corresponds to c[row * 3 + col] for this 9 element array. - // - // c[] holds signed values, ca[] hold absolute values - for (int i = 0; i < 9; i++) { - c[i] = dot(box1.axis(i / 3), box2.axis(i % 3)); - ca[i] = fabs(c[i]); - } - - // store all possible dot products between the axes of box1 and D, - // as well as the axes of box2 and D - for (int i = 0; i < 3; i++) { - ad[i] = dot(box1.axis(i), D); - bd[i] = dot(box2.axis(i), D); - } -} - - - -bool CollisionDetection::conservativeBoxBoxTest( - const Vector3 & a, const Vector3 & b, const Vector3 & D) { - // do a quick bounding sphere test because it is relatively - // cheap, (three dot products, two sqrts, and a few others) - double boxRadius1 = a.magnitude(); - double boxRadius2 = b.magnitude(); - return (D.squaredMagnitude() < square(boxRadius1 + boxRadius2)); -} - - - - -bool CollisionDetection::fixedSolidBoxIntersectsFixedSolidBox( - const Box& box1, - const Box& box2, - const int lastSeparatingAxis) { - // for explanations of the variable please refer to the - // paper and fillSolidBoxSolidBoxInfo() - Vector3 a; - Vector3 b; - Vector3 D; - double c[9]; - double ca[9]; - double ad[3]; - double bd[3]; - - fillSolidBoxSolidBoxInfo(box1, box2, a, b, D, c, ca, ad, bd); - - int dummy1, dummy2; - bool parallelAxes = parallelAxisForSolidBoxSolidBox(ca, 0.00001, - dummy1, dummy2); - - // check the separating axis from the last time step - if (lastSeparatingAxis != -1 && - (lastSeparatingAxis < 6 || !parallelAxes)) { - double projectedDistance = projectedDistanceForSolidBoxSolidBox( - lastSeparatingAxis, a, b, D, c, ca, ad, bd); - - // the separating axis from the last time step is still - // valid, the boxes do not intersect - if (projectedDistance > 0.0) { - return false; - } - } - - // test if the boxes can be separated by a plane normal to - // any of the three axes of box1, any of the three axes of box2, - // or any of the 9 possible cross products of axes from box1 - // and box2 - for (int i = 0; i < 15; i++) { - // do not need to check edge-edge cases if any two of - // the axes are parallel - if (parallelAxes && i == 6) { - return true; - } - - double projectedDistance = - projectedDistanceForSolidBoxSolidBox(i, a, b, D, c, ca, ad, bd); - - // found a separating axis, the boxes do not intersect - if (projectedDistance > 0.0) { - return false; - } - } - - return true; -} - - - -void CollisionDetection::closestPointsBetweenLineAndLine( - const Line & line1, - const Line & line2, - Vector3 & closest1, - Vector3 & closest2) { - // TODO make accessors for Line that don't make a copy of data - Vector3 P0 = line1.point(); - Vector3 u = line1.direction(); - Vector3 Q0 = line2.point(); - Vector3 v = line2.direction(); - Vector3 w0 = P0 - Q0; - - // a = 1.0, c = 1.0 - double b = dot(u, v); - double d = dot(u, w0); - double e = dot(v, w0); - double D = 1.0 - b * b; - double sc, tc; - - static const double epsilon = 0.00001; - - if (D < epsilon) { - // lines are parallel, choose P0 as one point, find the point - // on line2 that is closest to P0 - sc = 0.0; - tc = (b > 1.0) ? (d / b) : (e / 1.0); - } else { - // lines are not parallel - sc = (b * e - 1.0 * d) / D; - tc = (1.0 * e - b * d) / D; - } - - closest1 = P0 + (sc * u); - closest2 = Q0 + (tc * v); -} - - - -float CollisionDetection::penetrationDepthForFixedBoxFixedBox( - const Box& box1, - const Box& box2, - Array& contactPoints, - Array& contactNormals, - const int lastSeparatingAxis) { - - contactPoints.resize(0, DONT_SHRINK_UNDERLYING_ARRAY); - contactNormals.resize(0, DONT_SHRINK_UNDERLYING_ARRAY); - - Vector3 a; - Vector3 b; - Vector3 D; - double c[9]; - double ca[9]; - double ad[3]; - double bd[3]; - - debugAssert(lastSeparatingAxis >= -1); - debugAssert(lastSeparatingAxis < 15); - - fillSolidBoxSolidBoxInfo(box1, box2, a, b, D, c, ca, ad, bd); - - int axis1, axis2; - bool parallelAxes = parallelAxisForSolidBoxSolidBox(ca, 0.00001, - axis1, axis2); - - - // check the separating axis from the last time step - if (lastSeparatingAxis != -1 && - (lastSeparatingAxis < 6 || !parallelAxes)) { - float projectedDistance = projectedDistanceForSolidBoxSolidBox( - lastSeparatingAxis, a, b, D, c, ca, ad, bd); - - // the separating axis from the last time step is still - // valid, the boxes do not intersect - if (projectedDistance > 0.0) { - return -projectedDistance; - } - } - - // test if the boxes can be separated by a plane normal to - // any of the three axes of box1, any of the three axes of box2, - // (test 9 possible cross products later) - float penetration = -(float)G3D::inf(); - int penetrationAxisIndex = -1; - - for (int i = 0; i < 6; i++) { - float projectedDistance = - projectedDistanceForSolidBoxSolidBox(i, a, b, D, c, ca, ad, bd); - - // found a separating axis, the boxes do not intersect - if (projectedDistance > 0.0) { - return -projectedDistance; - } - - // keep track of the axis that is least violated - if (projectedDistance > penetration) { - penetration = projectedDistance; - penetrationAxisIndex = i; - } - } - - - // for each edge-edge case we have to adjust the magnitude of - // penetration since we did not include the dot(L, L) denominator - // that can be smaller than 1.0 for the edge-edge cases. - if (!parallelAxes) { - double edgeDistances[9]; - - // run through edge-edge cases to see if we can find a separating axis - for (int i = 6; i < 15; i++) { - float projectedDistance = - projectedDistanceForSolidBoxSolidBox(i, a, b, D, c, ca, ad, bd); - - // found a separating axis, the boxes do not intersect, - // correct magnitude and return projected distance - if (projectedDistance > 0.0) { - Vector3 L = separatingAxisForSolidBoxSolidBox(i, box1, box2); - projectedDistance /= dot(L, L); - return -projectedDistance; - } - - edgeDistances[i - 6] = projectedDistance; - } - - // no separating axis found, the boxes do intersect, - // correct the magnitudes of the projectedDistance values - for (int i = 6; i < 15; i++) { - // find the negative penetration value with the smallest magnitude, - // the adjustment done for the edge-edge cases only increases - // magnitude by dividing by a number smaller than 1 and greater than 0 - float projectedDistance = (float)edgeDistances[i - 6]; - if (projectedDistance > penetration) { - Vector3 L = separatingAxisForSolidBoxSolidBox(i, box1, box2); - projectedDistance /= dot(L, L); - if (projectedDistance > penetration) { - penetration = projectedDistance; - penetrationAxisIndex = i; - } - } - } - } - - // get final separating axis vector - Vector3 L = separatingAxisForSolidBoxSolidBox(penetrationAxisIndex, - box1, box2); - - // set L to be the normal that faces away from box1 - if (dot(L, D) < 0) { - L = -L; - } - - Vector3 contactPoint; - - if (penetrationAxisIndex < 6) { - // vertex to face collision, find deepest colliding vertex - const Box* vertexBox; - const Box* faceBox; - Vector3 faceNormal = L; - - // L will be the outward facing normal for the faceBox - if (penetrationAxisIndex < 3) { - faceBox = & box1; - vertexBox = & box2; - if (dot(L, D) < 0) { - faceNormal = -L; - } - } else { - faceBox = & box2; - vertexBox = & box1; - if (dot(L, D) > 0) { - faceNormal = -L; - } - } - - // find the vertex that is farthest away in the direction - // face normal direction - int deepestPointIndex = 0; - float deepestPointDot = dot(faceNormal, vertexBox->corner(0)); - for (int i = 1; i < 8; i++) { - float dotProduct = dot(faceNormal, vertexBox->corner(i)); - if (dotProduct < deepestPointDot) { - deepestPointDot = dotProduct; - deepestPointIndex = i; - } - } - - // return the point half way between the deepest point and the - // contacting face - contactPoint = vertexBox->corner(deepestPointIndex) + - (-penetration * 0.5 * faceNormal); - } else { - // edge-edge case, find the two ege lines - int edge1 = (penetrationAxisIndex - 6) / 3; - int edge2 = (penetrationAxisIndex - 6) % 3; - Vector3 linePoint1 = box1.center(); - Vector3 linePoint2 = box2.center(); - Vector3 lineDir1; - Vector3 lineDir2; - - // find edge line by finding the edge axis, and the - // other two axes that are closest to the other box - for (int i = 0; i < 3; i++ ) { - if (i == edge1) { - lineDir1 = box1.axis(i); - } else { - Vector3 axis = box1.axis(i); - if (dot(axis, L) < 0) { - axis = -axis; - } - linePoint1 += axis * a[i]; - } - - if (i == edge2) { - lineDir2 = box2.axis(i); - } else { - Vector3 axis = box2.axis(i); - if (dot(axis, L) > 0) { - axis = -axis; - } - linePoint2 += axis * b[i]; - } - } - - // make lines from the two closest edges, and find - // the points that on each line that are closest to the other - Line line1 = Line::fromPointAndDirection(linePoint1, lineDir1); - Line line2 = Line::fromPointAndDirection(linePoint2, lineDir2); - Vector3 closest1; - Vector3 closest2; - - closestPointsBetweenLineAndLine(line1, line2, closest1, closest2); - - // take the average of the two closest edge points for the final - // contact point - contactPoint = (closest1 + closest2) * 0.5; - } - - contactPoints.push(contactPoint); - contactNormals.push(L); - - return -penetration; - -} - - - - -float CollisionDetection::penetrationDepthForFixedSphereFixedBox( - const Sphere& sphere, - const Box& box, - Array& contactPoints, - Array& contactNormals) { - - contactPoints.resize(0, DONT_SHRINK_UNDERLYING_ARRAY); - contactNormals.resize(0, DONT_SHRINK_UNDERLYING_ARRAY); - - // In its local coordinate frame, the box measures - // 2 * halfExtent[a] along dimesion a. - Vector3 halfExtent(box.extent(0), box.extent(1), box.extent(2)); - halfExtent *= 0.5f; - - CoordinateFrame boxFrame; - box.getLocalFrame(boxFrame); - - // Transform the sphere to the box's coordinate frame. - Vector3 center = boxFrame.pointToObjectSpace(sphere.center); - - // Find the square of the distance from the sphere to the box - - - // Distance along each axis from the closest side of the box - // to the sphere center. Negative values are *inside* the box. - Vector3 distOutsideBox; - - // Divide space up into the 27 regions corresponding - // to {+|-|0}X, {+|-|0}Y, {+|-|0}Z and classify the - // sphere center into one of them. - Vector3 centerRegion; - - // In the edge collision case, the edge is between vertices - // (constant + variable) and (constant - variable). - Vector3 constant, variable; - - int numNonZero = 0; - - // Iterate over axes - for (int a = 0; a < 3; ++a) { - // For each (box side), see which direction the sphere - // is outside the box (positive or negative). Add the - // square of that distance to the total distance from - // the box. - - float distanceFromLow = -halfExtent[a] - center[a]; - float distanceFromHigh = center[a] - halfExtent[a]; - - if (fabsf(distanceFromLow) < fabsf(distanceFromHigh)) { - distOutsideBox[a] = distanceFromLow; - } else { - distOutsideBox[a] = distanceFromHigh; - } - - if (distanceFromLow < 0.0) { - if (distanceFromHigh < 0.0) { - // Inside the box - centerRegion[a] = 0.0; - variable[a] = 1.0; - } else { - // Off the high side - centerRegion[a] = 1.0; - constant[a] = halfExtent[a]; - ++numNonZero; - } - } else if (distanceFromHigh < 0.0) { - // Off the low side - centerRegion[a] = -1.0; - constant[a] = -halfExtent[a]; - ++numNonZero; - } else { - debugAssertM(false, - "distanceFromLow and distanceFromHigh cannot both be positive"); - } - } - - // Squared distance between the outside of the box and the - // sphere center. - float d2 = Vector3::zero().max(distOutsideBox).squaredMagnitude(); - - if (d2 > square(sphere.radius)) { - // There is no penetration because the distance is greater - // than the radius of the sphere. This is the common case - // and we quickly exit. - return -1; - } - - // We know there is some penetration but need to classify it. - // - // Examine the region that contains the center of the sphere. If - // there is exactly one non-zero axis, the collision is with a - // plane. If there are exactly two non-zero axes, the collision - // is with an edge. If all three axes are non-zero, the collision is - // with a vertex. If there are no non-zero axes, the center is inside - // the box. - - double depth = -1; - switch (numNonZero) { - case 3: // Vertex collision - // The collision point is the vertex at constant, the normal - // is the vector from there to the sphere center. - contactNormals.append(boxFrame.normalToWorldSpace(constant - center)); - contactPoints.append(boxFrame.pointToWorldSpace(constant)); - depth = sphere.radius - sqrt(d2); - break; - - case 2: // Edge collision - { - // TODO: unwrapping the edge constructor and closest point - // code will probably make it faster. - - // Determine the edge - Line line = Line::fromPointAndDirection(constant, variable); - - // Penetration depth: - depth = sphere.radius - sqrt(d2); - - // The contact point is the closes point to the sphere on the line - Vector3 X = line.closestPoint(center); - contactNormals.append(boxFrame.normalToWorldSpace(X - center).direction()); - contactPoints.append(boxFrame.pointToWorldSpace(X)); - } - break; - - case 1: // Plane collision - { - // The plane normal is the centerRegion vector, - // so the sphere normal is the negative. Take - // it to world space from box-space. - - // Center region doesn't need to be normalized because - // it is known to contain only one non-zero value - // and that value is +/- 1. - Vector3 N = boxFrame.normalToWorldSpace(-centerRegion); - contactNormals.append(N); - - // Penetration depth: - depth = sphere.radius - sqrtf(d2); - - // Compute the contact point from the penetration depth - contactPoints.append(sphere.center + N * (sphere.radius - depth)); - } - break; - - case 0: // Volume collision - - // The sphere center is inside the box. This is an easy case - // to handle. Note that all axes of distOutsideBox must - // be negative. - - // Arbitratily choose the sphere center as a contact point - contactPoints.append(sphere.center); - - // Find the least-negative penetration axis. - // - // We could have computed this during the loop over the axes, - // but since volume collisions are rare (they only occur with - // large time steps), this case will seldom be executed and - // should not be optimized at the expense of the others. - if (distOutsideBox.x > distOutsideBox.y) { - if (distOutsideBox.x > distOutsideBox.z) { - // Smallest penetration on x-axis - // Chose normal based on which side we're closest to. - // Keep in mind that this is a normal to the sphere, - // so it is the inverse of the box normal. - if (center.x > 0) { - contactNormals.append(boxFrame.normalToWorldSpace(-Vector3::unitX())); - } else { - contactNormals.append(boxFrame.normalToWorldSpace(Vector3::unitX())); - } - depth = -distOutsideBox.x; - } else { - // Smallest penetration on z-axis - goto ZAXIS; - } - } else if (distOutsideBox.y > distOutsideBox.z) { - // Smallest penetration on y-axis - // Chose normal based on which side we're closest to. - // Keep in mind that this is a normal to the sphere, - // so it is the inverse of the box normal. - if (center.y > 0) { - contactNormals.append(boxFrame.normalToWorldSpace(-Vector3::unitY())); - } else { - contactNormals.append(boxFrame.normalToWorldSpace(Vector3::unitY())); - } - depth = -distOutsideBox.y; - } else { - // Smallest on z-axis -ZAXIS: - // Chose normal based on which side we're closest to. - // Keep in mind that this is a normal to the sphere, - // so it is the inverse of the box normal. - if (center.z > 0) { - contactNormals.append(boxFrame.normalToWorldSpace(-Vector3::unitZ())); - } else { - contactNormals.append(boxFrame.normalToWorldSpace(Vector3::unitZ())); - } - depth = -distOutsideBox.z; - } - break; - - default: - debugAssertM(false, "Fell through switch"); - break; - } - - return depth; -} - - -float CollisionDetection::penetrationDepthForFixedSphereFixedSphere( - const Sphere& sphereA, - const Sphere& sphereB, - Array& contactPoints, - Array& contactNormals) { - - Vector3 axis = sphereB.center - sphereA.center; - double radius = sphereA.radius + sphereB.radius; - double mag = axis.magnitude(); - axis /= mag; - double depth = -(mag - radius); - - contactPoints.resize(0, DONT_SHRINK_UNDERLYING_ARRAY); - contactNormals.resize(0, DONT_SHRINK_UNDERLYING_ARRAY); - - if (depth >= 0) { - contactPoints.append(sphereA.center + axis * (sphereA.radius - depth / 2)); - contactNormals.append(axis); - } - - return depth; -} - - -float CollisionDetection::penetrationDepthForFixedSphereFixedPlane( - const Sphere& sphereA, - const Plane& planeB, - Array& contactPoints, - Array& contactNormals) { - - Vector3 N; - double d; - - planeB.getEquation(N, d); - - double depth = -(sphereA.center.dot(N) + d - sphereA.radius); - - contactPoints.resize(0, DONT_SHRINK_UNDERLYING_ARRAY); - contactNormals.resize(0, DONT_SHRINK_UNDERLYING_ARRAY); - - if (depth >= 0) { - contactPoints.append(N * (depth - sphereA.radius) + sphereA.center); - contactNormals.append(N); - } - - return depth; -} - - -float CollisionDetection::penetrationDepthForFixedBoxFixedPlane( - const Box& box, - const Plane& plane, - Array& contactPoints, - Array& contactNormals) { - - Vector3 N; - double d; - - plane.getEquation(N, d); - - contactPoints.resize(0, DONT_SHRINK_UNDERLYING_ARRAY); - contactNormals.resize(0, DONT_SHRINK_UNDERLYING_ARRAY); - - float lowest = (float)inf(); - for (int i = 0; i < 8; ++i) { - const Vector3 vertex = box.corner(i); - - float x = vertex.dot(N) + (float)d; - - if (x <= 0) { - // All vertices below the plane should be contact points. - contactPoints.append(vertex); - contactNormals.append(-N); - } - - lowest = min(lowest, x); - } - - // Depth should be a positive number - return -lowest; -} - - -float CollisionDetection::collisionTimeForMovingPointFixedPlane( - const Vector3& point, - const Vector3& velocity, - const Plane& plane, - Vector3& location, - Vector3& outNormal) { - - // Solve for the time at which normal.dot(point + velocity) + d == 0. - double d; - Vector3 normal; - plane.getEquation(normal, d); - - float vdotN = velocity.dot(normal); - float pdotN = point.dot(normal); - - if (fuzzyEq(pdotN + d, 0)) { - // The point is *in* the plane. - location = point; - outNormal = normal; - return 0; - } - - if (vdotN >= 0) { - // no collision will occur - location = Vector3::inf(); - return (float)inf(); - } - - float t = -(pdotN + d) / vdotN; - if (t < 0) { - location = Vector3::inf(); - return (float)inf(); - } else { - location = point + velocity * t; - outNormal = normal; - return t; - } -} - - -float CollisionDetection::collisionTimeForMovingPointFixedSphere( - const Vector3& point, - const Vector3& velocity, - const Sphere& sphere, - Vector3& location, - Vector3& outNormal) { - - double speed = velocity.magnitude(); - Vector3 direction = velocity / speed; - - Vector3 L = sphere.center - point; - double d = L.dot(direction); - - double L2 = L.dot(L); - double R2 = sphere.radius * sphere.radius; - double D2 = d * d; - - if ((d < 0) && (L2 > R2)) { - location = Vector3::inf(); - return inf(); - } - - double M2 = L2 - D2; - - if (M2 > R2) { - location = Vector3::inf(); - return inf(); - } - - double q = sqrt(R2 - M2); - double time; - - if (L2 > R2) { - time = d - q; - } else { - time = d + q; - } - - time /= speed; - - location = point + velocity * time; - outNormal = (location - sphere.center).direction(); - - return time; -} - - -float CollisionDetection::collisionTimeForMovingSphereFixedSphere( - const Sphere& movingSphere, - const Vector3& velocity, - const Sphere& fixedSphere, - Vector3& location, - Vector3& outNormal) { - - double time = collisionTimeForMovingPointFixedSphere(movingSphere.center, velocity, Sphere(fixedSphere.center, fixedSphere.radius + movingSphere.radius), location, outNormal); - - if (time < inf()) { - // Location is now the center of the moving sphere at the collision time. - // Adjust for the size of the moving sphere. Two spheres always collide - // along a line between their centers. - location += (location - fixedSphere.center) * movingSphere.radius / fixedSphere.radius; - } - - return time; -} - - -/* -float CollisionDetection::collisionTimeForMovingPointFixedTriangle( - const Vector3& point, - const Vector3& velocity, - const Triangle& triangle, - Vector3& outLocation, - Vector3& outNormal) { - - double time = collisionTimeForMovingPointFixedPlane(point, velocity, triangle.plane(), outLocation, outNormal); - - if (time == inf()) { - // No collision with the plane of the triangle. - return inf(); - } - - if (isPointInsideTriangle(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2), triangle.normal(), outLocation, triangle.primaryAxis())) { - // Collision occured inside the triangle - return time; - } else { - // Missed the triangle - outLocation = Vector3::inf(); - return inf(); - } -}*/ - -/* -float CollisionDetection::collisionTimeForMovingPointFixedTriangle( - const Vector3& orig, - const Vector3& dir, - const Vector3& vert0, - const Vector3& vert1, - const Vector3& vert2) { - - // Barycenteric coords - double u, v; - #define EPSILON 0.000001 - #define CROSS(dest,v1,v2) \ - dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \ - dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \ - dest[2]=v1[0]*v2[1]-v1[1]*v2[0]; - - #define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]) - - #define SUB(dest,v1,v2) \ - dest[0]=v1[0]-v2[0]; \ - dest[1]=v1[1]-v2[1]; \ - dest[2]=v1[2]-v2[2]; - - double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3]; - - // find vectors for two edges sharing vert0 - SUB(edge1, vert1, vert0); - SUB(edge2, vert2, vert0); - - // begin calculating determinant - also used to calculate U parameter - CROSS(pvec, dir, edge2); - - // if determinant is near zero, ray lies in plane of triangle - const double det = DOT(edge1, pvec); - - if (det < EPSILON) { - return inf(); - } - - // calculate distance from vert0 to ray origin - SUB(tvec, orig, vert0); - - // calculate U parameter and test bounds - u = DOT(tvec, pvec); - if ((u < 0.0) || (u > det)) { - // Hit the plane outside the triangle - return inf(); - } - - // prepare to test V parameter - CROSS(qvec, tvec, edge1); - - // calculate V parameter and test bounds - v = DOT(dir, qvec); - if ((v < 0.0) || (u + v > det)) { - // Hit the plane outside the triangle - return inf(); - } - - // calculate t, scale parameters, ray intersects triangle - // If we want u,v, we can compute this - // double t = DOT(edge2, qvec); - //const double inv_det = 1.0 / det; - //t *= inv_det; - //u *= inv_det; - //v *= inv_det; - // return t; - - // Case where we don't need correct (u, v): - - const double t = DOT(edge2, qvec); - - if (t >= 0) { - // Note that det must be positive - return t / det; - } else { - // We had to travel backwards in time to intersect - return inf(); - } - - #undef EPSILON - #undef CROSS - #undef DOT - #undef SUB -} -*/ - -float CollisionDetection::collisionTimeForMovingPointFixedBox( - const Vector3& point, - const Vector3& velocity, - const Box& box, - Vector3& location, - Vector3& outNormal) { - - double bestTime; - - Vector3 normal; - Vector3 v[4]; - - // Prime the loop - int f = 0; - box.getFaceCorners(f, v[0], v[1], v[2], v[3]); - bestTime = collisionTimeForMovingPointFixedRectangle(point, velocity, v[0], v[1], v[2], v[3], location, normal); - outNormal = normal; - - // Check other faces - for (f = 1; f < 6; ++f) { - Vector3 pos; - box.getFaceCorners(f, v[0], v[1], v[2], v[3]); - float time = collisionTimeForMovingPointFixedRectangle(point, velocity, v[0], v[1], v[2], v[3], pos, normal); - if (time < bestTime) { - bestTime = time; - outNormal = normal; - location = pos; - } - } - - return bestTime; -} - - -float CollisionDetection::collisionTimeForMovingPointFixedAABox( - const Vector3& origin, - const Vector3& dir, - const AABox& box, - Vector3& location, - bool& Inside, - Vector3& normal) { - - if (collisionLocationForMovingPointFixedAABox(origin, dir, box, location, Inside, normal)) { - return (location - origin).magnitude(); - } else { - return (float)inf(); - } -} - - -bool CollisionDetection::collisionLocationForMovingPointFixedAABox( - const Vector3& origin, - const Vector3& dir, - const AABox& box, - Vector3& location, - bool& Inside, - Vector3& normal) { - - // Integer representation of a floating-point value. - #define IR(x) ((uint32&)x) - - Inside = true; - const Vector3& MinB = box.low(); - const Vector3& MaxB = box.high(); - Vector3 MaxT(-1.0f, -1.0f, -1.0f); - - // Find candidate planes. - for (int i = 0; i < 3; ++i) { - if (origin[i] < MinB[i]) { - location[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]) { - location[i] = MaxB[i]; - Inside = false; - - // Calculate T distances to candidate planes - if (IR(dir[i])) { - MaxT[i] = (MaxB[i] - origin[i]) / dir[i]; - } - } - } - - if (Inside) { - // Ray origin inside bounding box - location = origin; - return false; - } - - // Get largest of the maxT's for final choice of intersection - int 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) { - // Miss the box - return false; - } - - for (int i = 0; i < 3; ++i) { - if (i != WhichPlane) { - location[i] = origin[i] + MaxT[WhichPlane] * dir[i]; - if ((location[i] < MinB[i]) || - (location[i] > MaxB[i])) { - // On this plane we're outside the box extents, so - // we miss the box - return false; - } - } - } - - // Choose the normal to be the plane normal facing into the ray - normal = Vector3::zero(); - normal[WhichPlane] = (dir[WhichPlane] > 0) ? -1.0 : 1.0; - - return true; - - #undef IR -} - - - -float CollisionDetection::collisionTimeForMovingPointFixedRectangle( - const Vector3& point, - const Vector3& velocity, - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& v3, - Vector3& location, - Vector3& outNormal) { - - Plane plane = Plane(v0, v1, v2); - - float time = collisionTimeForMovingPointFixedPlane(point, velocity, plane, location, outNormal); - - if (time == inf()) { - // No collision is ever going to happen - return time; - } - - if (isPointInsideRectangle(v0, v1, v2, v3, plane.normal(), location)) { - // The intersection point is inside the rectangle; that is the location where - // the point hits the rectangle. - return time; - } else { - return inf(); - } -} - -/** Used by findRayCapsuleIntersection. - @cite From magic software http://www.magic-software.com/Source/Intersection3D/MgcIntr3DLinCap.cpp */ -static int findRayCapsuleIntersectionAux( - const Vector3& rkOrigin, - const Vector3& rkDirection, - const Capsule& rkCapsule, - double afT[2]) { - - Vector3 capsuleDirection = rkCapsule.point(1) - rkCapsule.point(0); - - // set up quadratic Q(t) = a*t^2 + 2*b*t + c - Vector3 kU, kV, kW = capsuleDirection; - float fWLength = kW.unitize(); - Vector3::generateOrthonormalBasis(kU, kV, kW); - Vector3 kD(kU.dot(rkDirection), kV.dot(rkDirection), kW.dot(rkDirection)); - float fDLength = kD.unitize(); - - float fEpsilon = 1e-6f; - - float fInvDLength = 1.0f/fDLength; - Vector3 kDiff = rkOrigin - rkCapsule.point(0); - Vector3 kP(kU.dot(kDiff),kV.dot(kDiff),kW.dot(kDiff)); - float fRadiusSqr = square(rkCapsule.radius()); - - float fInv, fA, fB, fC, fDiscr, fRoot, fT, fTmp; - - // Is the velocity parallel to the capsule direction? (or zero) - if ((abs(kD.z) >= 1.0f - fEpsilon) || (fDLength < fEpsilon)) { - - float fAxisDir = rkDirection.dot(capsuleDirection); - - fDiscr = fRadiusSqr - kP.x*kP.x - kP.y*kP.y; - if ((fAxisDir < 0) && (fDiscr >= 0.0f)) { - // Velocity anti-parallel to the capsule direction - fRoot = sqrt(fDiscr); - afT[0] = (kP.z + fRoot)*fInvDLength; - afT[1] = -(fWLength - kP.z + fRoot)*fInvDLength; - return 2; - } else if ((fAxisDir > 0) && (fDiscr >= 0.0f)) { - // Velocity parallel to the capsule direction - fRoot = sqrt(fDiscr); - afT[0] = -(kP.z + fRoot)*fInvDLength; - afT[1] = (fWLength - kP.z + fRoot)*fInvDLength; - return 2; - } else { - // sphere heading wrong direction, or no velocity at all - return 0; - } - } - - // test intersection with infinite cylinder - fA = kD.x*kD.x + kD.y*kD.y; - fB = kP.x*kD.x + kP.y*kD.y; - fC = kP.x*kP.x + kP.y*kP.y - fRadiusSqr; - fDiscr = fB*fB - fA*fC; - if (fDiscr < 0.0f) { - // line does not intersect infinite cylinder - return 0; - } - - int iQuantity = 0; - - if (fDiscr > 0.0f) { - // line intersects infinite cylinder in two places - fRoot = sqrt(fDiscr); - fInv = 1.0f/fA; - fT = (-fB - fRoot)*fInv; - fTmp = kP.z + fT*kD.z; - if ((0.0f <= fTmp) && (fTmp <= fWLength)) { - afT[iQuantity] = fT * fInvDLength; - iQuantity++; - } - - fT = (-fB + fRoot)*fInv; - fTmp = kP.z + fT*kD.z; - - if ((0.0f <= fTmp) && (fTmp <= fWLength)) { - afT[iQuantity++] = fT*fInvDLength; - } - - if (iQuantity == 2) { - // line intersects capsule wall in two places - return 2; - } - } else { - // line is tangent to infinite cylinder - fT = -fB/fA; - fTmp = kP.z + fT*kD.z; - if ((0.0f <= fTmp) && (fTmp <= fWLength)) { - afT[0] = fT*fInvDLength; - return 1; - } - } - - // test intersection with bottom hemisphere - // fA = 1 - fB += kP.z*kD.z; - fC += kP.z*kP.z; - fDiscr = fB*fB - fC; - if (fDiscr > 0.0f) { - fRoot = sqrt(fDiscr); - fT = -fB - fRoot; - fTmp = kP.z + fT*kD.z; - if (fTmp <= 0.0f) { - afT[iQuantity++] = fT*fInvDLength; - if (iQuantity == 2) { - return 2; - } - } - - fT = -fB + fRoot; - fTmp = kP.z + fT*kD.z; - if (fTmp <= 0.0f) { - afT[iQuantity++] = fT*fInvDLength; - if (iQuantity == 2) { - return 2; - } - } - } else if (fDiscr == 0.0f) { - fT = -fB; - fTmp = kP.z + fT*kD.z; - if (fTmp <= 0.0f) { - afT[iQuantity++] = fT*fInvDLength; - if (iQuantity == 2) { - return 2; - } - } - } - - // test intersection with top hemisphere - // fA = 1 - fB -= kD.z*fWLength; - fC += fWLength*(fWLength - 2.0f*kP.z); - - fDiscr = fB*fB - fC; - if (fDiscr > 0.0f) { - fRoot = sqrt(fDiscr); - fT = -fB - fRoot; - fTmp = kP.z + fT*kD.z; - if (fTmp >= fWLength) { - afT[iQuantity++] = fT*fInvDLength; - if (iQuantity == 2) { - return 2; - } - } - - fT = -fB + fRoot; - fTmp = kP.z + fT*kD.z; - if (fTmp >= fWLength) { - afT[iQuantity++] = fT*fInvDLength; - if (iQuantity == 2) { - return 2; - } - } - } else if (fDiscr == 0.0f) { - fT = -fB; - fTmp = kP.z + fT*kD.z; - if (fTmp >= fWLength) { - afT[iQuantity++] = fT*fInvDLength; - if (iQuantity == 2) { - return 2; - } - } - } - - return iQuantity; -} - - -/** Used by collisionTimeForMovingPointFixedCapsule. - @cite From magic software http://www.magic-software.com/Source/Intersection3D/MgcIntr3DLinCap.cpp - - @param rkRay The ray - @param rkCapsule The capsule - @param riQuantity The number of intersections found - @param akPoint The intersections found - @return True if there is at least one intersection - */ -static bool findRayCapsuleIntersection( - const Ray& rkRay, - const Capsule& rkCapsule, - int& riQuantity, - Vector3 akPoint[2]) { - - double afT[2]; - riQuantity = findRayCapsuleIntersectionAux(rkRay.origin, rkRay.direction, rkCapsule, afT); - - // Only return intersections that occur in the future - int iClipQuantity = 0; - int i; - for (i = 0; i < riQuantity; i++) { - if (afT[i] >= 0.0f) { - akPoint[iClipQuantity] = rkRay.origin + afT[i] * rkRay.direction; - iClipQuantity++; - } - } - - riQuantity = iClipQuantity; - return (riQuantity > 0); -} - -float CollisionDetection::collisionTimeForMovingPointFixedCapsule( - const Vector3& _point, - const Vector3& velocity, - const Capsule& capsule, - Vector3& location, - Vector3& outNormal) { - - float timeScale = velocity.magnitude(); - - if (timeScale == 0.0f) { - timeScale = 1; - } - - Vector3 direction = velocity / timeScale; - int numIntersections; - Vector3 intersection[2]; - findRayCapsuleIntersection(Ray::fromOriginAndDirection(_point, direction), capsule, numIntersections, intersection); - - if (numIntersections == 2) { - // A collision can only occur if there are two intersections. If there is one - // intersection, that one is exiting the capsule. - - // Find the entering intersection (the first one that occurs). - float d0 = (intersection[0] - _point).squaredMagnitude(); - float d1 = (intersection[1] - _point).squaredMagnitude(); - - // Compute the surface normal (if we aren't ignoring the result) - if (&outNormal != &ignore) { - Vector3 p2 = LineSegment::fromTwoPoints(capsule.point(0), capsule.point(1)).closestPoint(_point); - outNormal = (_point - p2).direction(); - } - - if (d0 > d1) { - location = intersection[1]; - return sqrt(d1) / timeScale; - } else { - location = intersection[0]; - return sqrt(d0) / timeScale; - } - } else { - // No entering intersection discovered; return no intersection. - location = Vector3::inf(); - return inf(); - } -} - - -float CollisionDetection::collisionTimeForMovingSphereFixedPlane( - const Sphere& sphere, - const Vector3& velocity, - const Plane& plane, - Vector3& location, - Vector3& outNormal) { - - if (sphere.radius == 0) { - // Optimization for zero radius sphere - return collisionTimeForMovingPointFixedPlane(sphere.center, velocity, plane, location, outNormal); - } - - // The collision point on the sphere will be the point at - // center - (radius * normal). Collisions only occur when - // the sphere is travelling into the plane. - - double d; - plane.getEquation(outNormal, d); - - double vdotN = velocity.dot(outNormal); - - if (fuzzyGt(vdotN, 0)) { - // No collision when the sphere is moving towards a backface. - location = Vector3::inf(); - return (float)inf(); - } - - float cdotN = sphere.center.dot(outNormal); - - // Distance from the center to the plane - float distance = cdotN + (float)d; - - // Where is the collision on the sphere? - Vector3 point = sphere.center - (sphere.radius * outNormal); - - if (fuzzyLe(G3D::abs(distance), sphere.radius)) { - // Already interpenetrating - location = sphere.center - distance * outNormal; - return 0; - } else { - return collisionTimeForMovingPointFixedPlane(point, velocity, plane, location, outNormal); - } - -} - - -float CollisionDetection::collisionTimeForMovingSphereFixedTriangle( - const class Sphere& sphere, - const Vector3& velocity, - const Triangle& triangle, - Vector3& outLocation, - float b[3]) { - - Vector3 dummy; - float time = collisionTimeForMovingSphereFixedPlane(sphere, velocity, triangle.plane(), - outLocation, dummy); - - if (time == inf()) { - // No collision is ever going to happen - return time; - } - - // We will hit the plane of the triangle at *time*. See if - // the intersection point actually is within the triangle. - - if (isPointInsideTriangle(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2), triangle.normal(), - outLocation, b, triangle.primaryAxis())) { - - // The intersection point is inside the triangle; that is the location where - // the sphere hits the triangle. - -# ifdef G3D_DEBUG - { - // Internal consistency checks - debugAssertM(b[0] >= 0.0 && b[0] <= 1.0f, "Intersection is outside triangle."); - debugAssertM(b[1] >= 0.0 && b[1] <= 1.0f, "Intersection is outside triangle."); - debugAssertM(b[2] >= 0.0 && b[2] <= 1.0f, "Intersection is outside triangle."); - Vector3 blend = - b[0] * triangle.vertex(0) + - b[1] * triangle.vertex(1) + - b[2] * triangle.vertex(2); - debugAssertM(blend.fuzzyEq(outLocation), "Barycentric coords don't match intersection."); - // Call again so that we can debug the problem - // isPointInsideTriangle(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2), triangle.normal(), - // outLocation, b, triangle.primaryAxis()); - } -# endif - - return time; - } - - // The collision (if it exists) is with a point on the triangle perimeter. - // Switch over to moving the triangle towards a fixed sphere and see at what time - // they will hit. - - // Closest point on the triangle to the sphere intersection with the plane. - int edgeIndex; - const Vector3& point = closestPointOnTrianglePerimeter(triangle._vertex, triangle.edgeDirection, - triangle.edgeMagnitude, outLocation, edgeIndex); - - float t = 0; - if (! sphere.contains(point)) { - // The point is outside the sphere--see when it will hit - t = collisionTimeForMovingPointFixedSphere(point, -velocity, sphere, dummy, dummy); - } - - if (t < inf()) { - outLocation = point; - // Compute Barycentric coords - - // Index of the next vertex - static const int next[] = {1, 2, 0}; - - // Project along the edge in question. - // Avoid sqrt by taking advantage of the existing edgeDirection unit vector. - b[next[edgeIndex]] = (outLocation - triangle._vertex[edgeIndex]).dot - (triangle.edgeDirection[edgeIndex]) / triangle.edgeMagnitude[edgeIndex]; - - b[edgeIndex] = 1.0f - b[next[edgeIndex]]; - - b[next[next[edgeIndex]]] = 0.0f; - -# ifdef G3D_DEBUG - { - // Internal consistency checks - for (int i = 0; i < 3; ++i) { - debugAssertM(fuzzyGe(b[i], 0.0f) && fuzzyLe(b[i], 1.0f), "Intersection is outside triangle."); - } - Vector3 blend = - b[0] * triangle.vertex(0) + - b[1] * triangle.vertex(1) + - b[2] * triangle.vertex(2); - debugAssertM(blend.fuzzyEq(outLocation), - format("Barycentric coords don't match intersection. %s != %s", - blend.toString().c_str(), - outLocation.toString().c_str())); - - // Call again so that we can debug the problem - collisionTimeForMovingPointFixedSphere(point, -velocity, sphere, dummy, dummy); - } -# endif - - // Due to tiny roundoffs, these values might be slightly out of bounds. - // Ensure that they are legal. Note that the above debugging code - // verifies that we are not clamping truly illegal values. - for (int i = 0; i < 3; ++i) { - b[i] = clamp(b[i], 0.0f, 1.0f); - } - } - - // The collision occured at the point, if it occured. The normal - // was the plane normal, computed above. - - return t; -} - - -float CollisionDetection::collisionTimeForMovingSphereFixedRectangle( - const Sphere& sphere, - const Vector3& velocity, - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& v3, - Vector3& location, - Vector3& outNormal) { - - Plane plane(v0, v1, v2); - - float time = collisionTimeForMovingSphereFixedPlane(sphere, velocity, plane, location, outNormal); - - if (time == inf()) { - // No collision is ever going to happen - return time; - } - - if (isPointInsideRectangle(v0, v1, v2, v3, plane.normal(), location)) { - // The intersection point is inside the rectangle; that is the location where - // the sphere hits the rectangle. - return time; - } - - // Switch over to moving the rectangle towards a fixed sphere and see at what time - // they will hit. - - Vector3 point = closestPointToRectanglePerimeter(v0, v1, v2, v3, sphere.center); - - Vector3 dummy; - double t = collisionTimeForMovingPointFixedSphere(point, -velocity, sphere, location, dummy); - - // Normal is the plane normal, location is the original location of the point. - location = point; - - return t; -} - - -float CollisionDetection::collisionTimeForMovingSphereFixedBox( - const Sphere& sphere, - const Vector3& velocity, - const Box& box, - Vector3& location, - Vector3& outNormal) { - - if (fixedSolidSphereIntersectsFixedSolidBox(sphere, box)) { - // TODO: Compute more useful location and normal? - location = sphere.center; - outNormal = Vector3::zero(); - return 0; - } - - float bestTime; - - Vector3 v[4]; - int f = 0; - box.getFaceCorners(f, v[0], v[1], v[2], v[3]); - bestTime = collisionTimeForMovingSphereFixedRectangle(sphere, velocity, v[0], v[1], v[2], v[3], location, outNormal); - - for (f = 1; f < 6; ++f) { - Vector3 pos, normal; - box.getFaceCorners(f, v[0], v[1], v[2], v[3]); - float time = collisionTimeForMovingSphereFixedRectangle(sphere, velocity, v[0], v[1], v[2], v[3], pos, normal); - if (time < bestTime) { - bestTime = time; - location = pos; - outNormal = normal; - } - } - - return bestTime; -} - - -float CollisionDetection::collisionTimeForMovingSphereFixedCapsule( - const Sphere& sphere, - const Vector3& velocity, - const Capsule& capsule, - Vector3& location, - Vector3& outNormal) { - - (void)outNormal; - - Capsule _capsule(capsule.point(0), capsule.point(1), capsule.radius() + sphere.radius); - - Vector3 normal; - double time = collisionTimeForMovingPointFixedCapsule(sphere.center, velocity, _capsule, location, normal); - - if (time < inf()) { - // Location is now the position of the center of the sphere at the time of collision. - // We have to adjust the collision location for the size of the sphere. - location -= sphere.radius * normal; - } - - return time; -} - - -Vector3 CollisionDetection::bounceDirection( - const Sphere& sphere, - const Vector3& velocity, - const float collisionTime, - const Vector3& collisionLocation, - const Vector3& collisionNormal) { - - // Location when the collision occurs - Vector3 sphereLocation = sphere.center + velocity * collisionTime; - - Vector3 normal = (sphereLocation - collisionLocation); - if (fuzzyEq(normal.squaredMagnitude(), 0)) { - normal = collisionNormal; - } else { - normal.unitize(); - } - - Vector3 direction = velocity.direction(); - - // Reflect direction about the normal - return direction - 2.0 * normal * normal.dot(direction); -} - - -Vector3 CollisionDetection::slideDirection( - const Sphere& sphere, - const Vector3& velocity, - const float collisionTime, - const Vector3& collisionLocation) { - - Vector3 sphereLocation = sphere.center + velocity * collisionTime; - Vector3 normal = (sphereLocation - collisionLocation).direction(); - Vector3 direction = velocity.direction(); - - // subtract off the part in the direction away from the normal. - return direction - normal * normal.dot(direction); -} - - -Vector3 CollisionDetection::closestPointOnLineSegment( - const Vector3& v0, - const Vector3& v1, - const Vector3& point) { - - const Vector3& edge = (v1 - v0); - float edgeLength = edge.magnitude(); - - if (edgeLength == 0) { - // The line segment is a point - return v0; - } - - return closestPointOnLineSegment(v0, v1, edge / edgeLength, edgeLength, point); -} - - -Vector3 CollisionDetection::closestPointOnLineSegment( - const Vector3& v0, - const Vector3& v1, - const Vector3& edgeDirection, - const float edgeLength, - const Vector3& point) { - - debugAssert((v1 - v0).direction().fuzzyEq(edgeDirection)); - debugAssert(fuzzyEq((v1 - v0).magnitude(), edgeLength)); - - // Vector towards the point - const Vector3& c = point - v0; - - // Projected onto the edge itself - float t = edgeDirection.dot(c); - - if (t <= 0) { - // Before the start - return v0; - } else if (t >= edgeLength) { - // After the end - return v1; - } else { - // At distance t along the edge - return v0 + edgeDirection * t; - } -} - - -Vector3 CollisionDetection::closestPointOnTrianglePerimeter( - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& point) { - - Vector3 v[3] = {v0, v1, v2}; - Vector3 edgeDirection[3] = {(v1 - v0), (v2 - v1), (v0 - v2)}; - float edgeLength[3]; - - for (int i = 0; i < 3; ++i) { - edgeLength[i] = edgeDirection[i].magnitude(); - edgeDirection[i] /= edgeLength[i]; - } - - int edgeIndex; - return closestPointOnTrianglePerimeter(v, edgeDirection, edgeLength, point, edgeIndex); -} - - -Vector3 CollisionDetection::closestPointOnTrianglePerimeter( - const Vector3 v[3], - const Vector3 edgeDirection[3], - const float edgeLength[3], - const Vector3& point, - int& edgeIndex) { - - // Closest point on segment from v[i] to v[i + 1] - Vector3 r[3]; - - // Distance squared from r[i] to point - float d[3]; - - // Index of the next point - static const int next[] = {1, 2, 0}; - - for (int i = 0; i < 3; ++i) { - r[i] = closestPointOnLineSegment(v[i], v[next[i]], edgeDirection[i], edgeLength[i], point); - d[i] = (r[i] - point).squaredMagnitude(); - } - - if (d[0] < d[1]) { - if (d[0] < d[2]) { - // Between v0 and v1 - edgeIndex = 0; - } else { - // Between v2 and v0 - edgeIndex = 2; - } - } else { - if (d[1] < d[2]) { - // Between v1 and v2 - edgeIndex = 1; - } else { - // Between v2 and v0 - edgeIndex = 2; - } - } - -# ifdef G3D_DEBUG - { - Vector3 diff = r[edgeIndex] - v[edgeIndex]; - debugAssertM(fuzzyEq(diff.direction().dot(edgeDirection[edgeIndex]), 1.0f) || - diff.fuzzyEq(Vector3::zero()), "Point not on correct triangle edge"); - float frac = diff.dot(edgeDirection[edgeIndex])/edgeLength[edgeIndex]; - debugAssertM(frac >= -0.000001, "Point off low side of edge."); - debugAssertM(frac <= 1.000001, "Point off high side of edge."); - } -# endif - - return r[edgeIndex]; -} - - -bool CollisionDetection::isPointInsideTriangle( - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& normal, - const Vector3& point, - float b[3], - Vector3::Axis primaryAxis) { - - if (primaryAxis == Vector3::DETECT_AXIS) { - primaryAxis = normal.primaryAxis(); - } - - // Check that the point is within the triangle using a Barycentric - // coordinate test on a two dimensional plane. - int i, j; - - switch (primaryAxis) { - case Vector3::X_AXIS: - i = Vector3::Y_AXIS; - j = Vector3::Z_AXIS; - break; - - case Vector3::Y_AXIS: - i = Vector3::Z_AXIS; - j = Vector3::X_AXIS; - break; - - case Vector3::Z_AXIS: - i = Vector3::X_AXIS; - j = Vector3::Y_AXIS; - break; - - default: - // This case is here to supress a warning on Linux - i = j = 0; - debugAssertM(false, "Should not get here."); - break; - } - - // See if all barycentric coordinates are non-negative - - // 2D area via cross product -# define AREA2(d, e, f) (((e)[i] - (d)[i]) * ((f)[j] - (d)[j]) - ((f)[i] - (d)[i]) * ((e)[j] - (d)[j])) - - // Area of the polygon - float area = AREA2(v0, v1, v2); - if (area == 0) { - // This triangle has zero area, so the point must not - // be in it unless the triangle point is the test point. - return (v0 == point); - } - - debugAssert(area != 0); - - float invArea = 1.0f / area; - - // (avoid normalization until absolutely necessary) - b[0] = AREA2(point, v1, v2) * invArea; - - if ((b[0] < 0.0f) || (b[0] > 1.0f)) { - return false; - } - - b[1] = AREA2(v0, point, v2) * invArea; - if ((b[1] < 0.0f) || (b[1] > 1.0f)) { - return false; - } - - b[2] = 1.0f - b[0] - b[1]; - -# undef AREA2 - - return (b[2] >= 0.0f) && (b[2] <= 1.0f); -} - - -bool CollisionDetection::isPointInsideRectangle( - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& v3, - const Vector3& normal, - const Vector3& point) { - - return isPointInsideTriangle(v0, v1, v2, normal, point) || - isPointInsideTriangle(v2, v3, v0, normal, point); -} - - -Vector3 CollisionDetection::closestPointToRectanglePerimeter( - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& v3, - const Vector3& point) { - - Vector3 r0 = closestPointOnLineSegment(v0, v1, point); - Vector3 r1 = closestPointOnLineSegment(v1, v2, point); - Vector3 r2 = closestPointOnLineSegment(v2, v3, point); - Vector3 r3 = closestPointOnLineSegment(v3, v0, point); - - double d0 = (r0 - point).squaredMagnitude(); - double d1 = (r1 - point).squaredMagnitude(); - double d2 = (r2 - point).squaredMagnitude(); - double d3 = (r3 - point).squaredMagnitude(); - - if (d0 < d1) { - if (d0 < d2) { - if (d0 < d3) { - return r0; - } else { - return r3; - } - } else { - if (d2 < d3) { - return r2; - } else { - return r3; - } - } - } else { - if (d1 < d2) { - if (d1 < d3) { - return r1; - } else { - return r3; - } - } else { - if (d2 < d3) { - return r2; - } else { - return r3; - } - } - } -} - - -Vector3 CollisionDetection::closestPointToRectangle( - const Vector3& v0, - const Vector3& v1, - const Vector3& v2, - const Vector3& v3, - const Vector3& point) { - - Plane plane(v0, v1, v2); - - // Project the point into the plane - double a, b, c, d; - plane.getEquation(a, b, c, d); - - double distance = a*point.x + b*point.y + c*point.z + d; - Vector3 planePoint = point - distance * plane.normal(); - - if (isPointInsideRectangle(v0, v1, v2, v3, plane.normal(), planePoint)) { - return planePoint; - } else { - return closestPointToRectanglePerimeter(v0, v1, v2, v3, planePoint); - } -} - - -bool CollisionDetection::fixedSolidSphereIntersectsFixedSolidSphere( - const Sphere& sphere1, - const Sphere& sphere2) { - - return (sphere1.center - sphere2.center).squaredMagnitude() < square(sphere1.radius + sphere2.radius); -} - - -bool CollisionDetection::fixedSolidSphereIntersectsFixedSolidBox( - const Sphere& sphere, - const Box& box) { - - // If the center of the sphere is within the box, the whole - // sphere is within the box. - if (box.contains(sphere.center)) { - return true; - } - - float r2 = square(sphere.radius); - - // Find the closest point on the surface of the box to the sphere. If - // this point is within the sphere's radius, they intersect. - int f; - for (f = 0; f < 6; ++f) { - Vector3 v0, v1, v2, v3; - box.getFaceCorners(f, v0, v1, v2, v3); - if ((closestPointToRectangle(v0, v1, v2, v3, sphere.center) - sphere.center).squaredMagnitude() <= r2) { - return true; - } - } - - return false; -} - - -bool CollisionDetection::movingSpherePassesThroughFixedBox( - const Sphere& sphere, - const Vector3& velocity, - const Box& box, - double timeLimit) { - - // If they intersect originally, they definitely pass through each other. - if (fixedSolidSphereIntersectsFixedSolidBox(sphere, box)) { - return true; - } - - // See if the sphere hits the box during the time period. - Vector3 dummy1, dummy2; - - return (collisionTimeForMovingSphereFixedBox(sphere, velocity, box, dummy1, dummy2) < timeLimit); -} - - -bool CollisionDetection::movingSpherePassesThroughFixedSphere( - const Sphere& sphere, - const Vector3& velocity, - const Sphere& fixedSphere, - double timeLimit) { - - if (fixedSolidSphereIntersectsFixedSolidSphere(sphere, fixedSphere)) { - return true; - } - - // Extend the fixed sphere by the radius of the moving sphere - Sphere bigFixed(fixedSphere.center, fixedSphere.radius + sphere.radius); - Vector3 dummy1, dummy2; - - // If the sphere collides with the other sphere during the time limit, it passes through - return (collisionTimeForMovingPointFixedSphere(sphere.center, velocity, bigFixed, dummy1, dummy2) < timeLimit); -} - - - -bool CollisionDetection::fixedSolidSphereIntersectsFixedTriangle( - const Sphere& sphere, - const Triangle& triangle) { - - // How far is the sphere from the plane of the triangle - const Plane& plane = triangle.plane(); - - // Does the closest point to the sphere center lie within the triangle? - Vector3 v = plane.closestPoint(sphere.center); - - // Is the closest point to the plane within the sphere? - if ((v - sphere.center).squaredLength() <= square(sphere.radius)) { - // Is it also within the triangle? - float b[3]; - if (isPointInsideTriangle(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2), triangle.normal(), - v, b, triangle.primaryAxis())){ - // The closest point is inside the triangle - return true; - } - } - - // ignored - int edgeIndex; - - v = closestPointOnTrianglePerimeter(triangle._vertex, triangle.edgeDirection, triangle.edgeMagnitude, sphere.center, edgeIndex); - - // Is the closest point within the sphere? - return ((v - sphere.center).squaredLength() <= square(sphere.radius)); -} - - -} // namespace -#ifdef _MSC_VER -#pragma warning (pop) -#endif diff --git a/externals/g3dlite/G3D.lib/source/Color1.cpp b/externals/g3dlite/G3D.lib/source/Color1.cpp deleted file mode 100644 index 7e058a27d1a..00000000000 --- a/externals/g3dlite/G3D.lib/source/Color1.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - @file Color1.cpp - - Color class. - - @author Morgan McGuire, matrix@graphics3d.com - - @created 2007-01-30 - @edited 2007-01-30 - */ - -#include "G3D/platform.h" -#include "G3D/Color1.h" -#include "G3D/Color1uint8.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - -namespace G3D { - -Color1::Color1(BinaryInput& bi) { - deserialize(bi); -} - - -void Color1::deserialize(BinaryInput& bi) { - value = bi.readFloat32(); -} - - -void Color1::serialize(BinaryOutput& bo) const { - bo.writeFloat32(value); -} - - -Color1::Color1(const class Color1uint8& other) { - value = other.value / 255.0f; -} - -} // namespace G3D - diff --git a/externals/g3dlite/G3D.lib/source/Color1uint8.cpp b/externals/g3dlite/G3D.lib/source/Color1uint8.cpp deleted file mode 100644 index 0fd00693d4c..00000000000 --- a/externals/g3dlite/G3D.lib/source/Color1uint8.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/** - @file Color1uint8.cpp - - @author Morgan McGuire, matrix@graphics3d.com - - @created 2007-01-30 - @edited 2007-01-30 - */ - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Color1uint8.h" -#include "G3D/Color1.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - -namespace G3D { - -Color1uint8::Color1uint8(const class Color1& c) : value(iClamp(iFloor(c.value * 256), 0, 255)) { -} - - -Color1uint8::Color1uint8(class BinaryInput& bi) { - deserialize(bi); -} - - -void Color1uint8::serialize(class BinaryOutput& bo) const { - bo.writeUInt8(value); -} - - -void Color1uint8::deserialize(class BinaryInput& bi) { - value = bi.readUInt8(); -} - - -} diff --git a/externals/g3dlite/G3D.lib/source/Color3.cpp b/externals/g3dlite/G3D.lib/source/Color3.cpp deleted file mode 100644 index 8183d8a0f62..00000000000 --- a/externals/g3dlite/G3D.lib/source/Color3.cpp +++ /dev/null @@ -1,321 +0,0 @@ -/** - @file Color3.cpp - - Color class. - - @author Morgan McGuire, matrix@graphics3d.com - @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com - - - @created 2001-06-02 - @edited 2006-01-13 - */ - -#include "G3D/platform.h" -#include -#include "G3D/Color3.h" -#include "G3D/Vector3.h" -#include "G3D/format.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/Color3uint8.h" - -namespace G3D { - -const Color3& Color3::red() { - static Color3 c(1.0f, 0.0f, 0.0f); - return c; -} - - -const Color3& Color3::green() { - static Color3 c(0.0f, 1.0f, 0.0f); - return c; -} - - -const Color3& Color3::blue() { - static Color3 c(0.0f, 0.0f, 1.0f); - return c; -} - - -const Color3& Color3::purple() { - static Color3 c(0.7f, 0.0f, 1.0f); - return c; -} - - -const Color3& Color3::cyan() { - static Color3 c(0.0f, 0.7f, 1.0f); - return c; -} - - -const Color3& Color3::yellow() { - static Color3 c(1.0f, 1.0f, 0.0f); - return c; -} - - -const Color3& Color3::brown() { - static Color3 c(0.5f, 0.5f, 0.0f); - return c; -} - - -const Color3& Color3::orange() { - static Color3 c(1.0f, 0.5f, 0.0f); - return c; -} - - -const Color3& Color3::black() { - static Color3 c(0.0f, 0.0f, 0.0f); - return c; -} - -const Color3& Color3::zero() { - static Color3 c(0.0f, 0.0f, 0.0f); - return c; -} - - -const Color3& Color3::one() { - static Color3 c(1.0f, 1.0f, 1.0f); - return c; -} - - -const Color3& Color3::gray() { - static Color3 c(0.7f, 0.7f, 0.7f); - return c; -} - - -const Color3& Color3::white() { - static Color3 c(1, 1, 1); - return c; -} - - -Color3::Color3(BinaryInput& bi) { - deserialize(bi); -} - - -void Color3::deserialize(BinaryInput& bi) { - r = bi.readFloat32(); - g = bi.readFloat32(); - b = bi.readFloat32(); -} - - -void Color3::serialize(BinaryOutput& bo) const { - bo.writeFloat32(r); - bo.writeFloat32(g); - bo.writeFloat32(b); -} - - -const Color3& Color3::wheelRandom() { - static const Color3 colorArray[8] = - {Color3::blue(), Color3::red(), Color3::green(), - Color3::orange(), Color3::yellow(), - Color3::cyan(), Color3::purple(), Color3::brown()}; - - return colorArray[iRandom(0, 7)]; -} - - -size_t Color3::hashCode() const { - unsigned int rhash = (*(int*)(void*)(&r)); - unsigned int ghash = (*(int*)(void*)(&g)); - unsigned int bhash = (*(int*)(void*)(&b)); - - return rhash + (ghash * 37) + (bhash * 101); -} - - -Color3::Color3(const Vector3& v) { - r = v.x; - g = v.y; - b = v.z; -} - - -Color3::Color3(const class Color3uint8& other) { - r = other.r / 255.0f; - g = other.g / 255.0f; - b = other.b / 255.0f; -} - - -Color3 Color3::fromARGB(uint32 x) { - return Color3((float)((x >> 16) & 0xFF), (float)((x >> 8) & 0xFF), (float)(x & 0xFF)) / 255.0f; -} - -//---------------------------------------------------------------------------- - - -Color3 Color3::random() { - return Color3(uniformRandom(), - uniformRandom(), - uniformRandom()).direction(); -} - -//---------------------------------------------------------------------------- -Color3 Color3::operator/ (float fScalar) const { - Color3 kQuot; - - if (fScalar != 0.0f) { - float fInvScalar = 1.0f / fScalar; - kQuot.r = fInvScalar * r; - kQuot.g = fInvScalar * g; - kQuot.b = fInvScalar * b; - return kQuot; - - } else { - - return Color3((float)G3D::inf(), (float)G3D::inf(), (float)G3D::inf()); - } -} - -//---------------------------------------------------------------------------- -Color3& Color3::operator/= (float fScalar) { - if (fScalar != 0.0f) { - float fInvScalar = 1.0f / fScalar; - r *= fInvScalar; - g *= fInvScalar; - b *= fInvScalar; - } else { - r = (float)G3D::inf(); - g = (float)G3D::inf(); - b = (float)G3D::inf(); - } - - return *this; -} - -//---------------------------------------------------------------------------- -float Color3::unitize (float fTolerance) { - float fLength = length(); - - if ( fLength > fTolerance ) { - float fInvLength = 1.0f / fLength; - r *= fInvLength; - g *= fInvLength; - b *= fInvLength; - } else { - fLength = 0.0f; - } - - return fLength; -} - -//---------------------------------------------------------------------------- -Color3 Color3::fromHSV(const Vector3& _hsv) { - debugAssertM((_hsv.x <= 1.0f && _hsv.x >= 0.0f) - && (_hsv.y <= 1.0f && _hsv.y >= 0.0f) - && ( _hsv.z <= 1.0f && _hsv.z >= 0.0f), "H,S,V must be between [0,1]"); - const int i = G3D::iFloor(6.0*_hsv.x); - const float f = 6.0f * _hsv.x - i; - const float m = _hsv.z * (1.0f - (_hsv.y)); - const float n = _hsv.z * (1.0f - (_hsv.y * f)); - const float k = _hsv.z * (1.0f - (_hsv.y * (1 - f))); - switch(i) { - case 0: - return Color3(_hsv.z, k, m); - - case 1: - return Color3(n, _hsv.z, m); - - case 2: - return Color3(m, _hsv.z, k); - - case 3: - return Color3(m, n, _hsv.z); - - case 4: - return Color3(k, m, _hsv.z); - - case 5: - return Color3(_hsv.z, m, n); - - default: - debugAssertM(false, "fell through switch.."); - } - return Color3::black(); -} - - -Vector3 Color3::toHSV(const Color3& _rgb) { - debugAssertM((_rgb.r <= 1.0f && _rgb.r >= 0.0f) - && (_rgb.g <= 1.0f && _rgb.g >= 0.0f) - && (_rgb.b <= 1.0f && _rgb.b >= 0.0f), "R,G,B must be between [0,1]"); - Vector3 hsv = Vector3::zero(); - hsv.z = G3D::max(G3D::max(_rgb.r, _rgb.g), _rgb.b); - if (G3D::fuzzyEq(hsv.z, 0.0f)) { - return hsv; - } - - const float x = G3D::min(G3D::min(_rgb.r, _rgb.g), _rgb.b); - hsv.y = (hsv.z - x) / hsv.z; - - if (G3D::fuzzyEq(hsv.y, 0.0f)) { - return hsv; - } - - Vector3 rgbN; - rgbN.x = (hsv.z - _rgb.r) / (hsv.z - x); - rgbN.y = (hsv.z - _rgb.g) / (hsv.z - x); - rgbN.z = (hsv.z - _rgb.b) / (hsv.z - x); - - if (_rgb.r == hsv.z) { // note from the max we know that it exactly equals one of the three. - hsv.x = (_rgb.g == x)? 5.0f + rgbN.z : 1.0f - rgbN.y; - } else if (_rgb.g == hsv.z) { - hsv.x = (_rgb.b == x)? 1.0f + rgbN.x : 3.0f - rgbN.z; - } else { - hsv.x = (_rgb.r == x)? 3.0f + rgbN.y : 5.0f - rgbN.x; - } - - hsv.x /= 6.0f; - - return hsv; -} - -Color3 Color3::jetColorMap(const float& val) { - debugAssertM(val <= 1.0f && val >= 0.0f , "value should be in [0,1]"); - - //truncated triangles where sides have slope 4 - Color3 jet; - - jet.r = G3D::min(4.0f * val - 1.5f,-4.0f * val + 4.5f) ; - jet.g = G3D::min(4.0f * val - 0.5f,-4.0f * val + 3.5f) ; - jet.b = G3D::min(4.0f * val + 0.5f,-4.0f * val + 2.5f) ; - - - jet.r = G3D::clamp(jet.r, 0.0f, 1.0f); - jet.g = G3D::clamp(jet.g, 0.0f, 1.0f); - jet.b = G3D::clamp(jet.b, 0.0f, 1.0f); - - return jet; -} - - - - - -std::string Color3::toString() const { - return G3D::format("(%g, %g, %g)", r, g, b); -} - -//---------------------------------------------------------------------------- - -Color3 Color3::rainbowColorMap(float hue) { - return fromHSV(Vector3(hue, 1.0f, 1.0f)); -} - - -}; // namespace - diff --git a/externals/g3dlite/G3D.lib/source/Color3uint8.cpp b/externals/g3dlite/G3D.lib/source/Color3uint8.cpp deleted file mode 100644 index 837bf1b2c8b..00000000000 --- a/externals/g3dlite/G3D.lib/source/Color3uint8.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/** - @file Color3uint8.cpp - - @author Morgan McGuire, matrix@graphics3d.com - - @created 2003-04-07 - @edited 2006-01-07 - */ - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Color3uint8.h" -#include "G3D/Color3.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - -namespace G3D { - -Color3uint8::Color3uint8(const class Color3& c) { - r = iMin(255, iFloor(c.r * 256)); - g = iMin(255, iFloor(c.g * 256)); - b = iMin(255, iFloor(c.b * 256)); -} - - -Color3uint8::Color3uint8(class BinaryInput& bi) { - deserialize(bi); -} - - -void Color3uint8::serialize(class BinaryOutput& bo) const { - bo.writeUInt8(r); - bo.writeUInt8(g); - bo.writeUInt8(b); -} - - -void Color3uint8::deserialize(class BinaryInput& bi) { - r = bi.readUInt8(); - g = bi.readUInt8(); - b = bi.readUInt8(); -} - - -} diff --git a/externals/g3dlite/G3D.lib/source/Color4.cpp b/externals/g3dlite/G3D.lib/source/Color4.cpp deleted file mode 100644 index ed2e91291a1..00000000000 --- a/externals/g3dlite/G3D.lib/source/Color4.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/** - @file Color4.cpp - - Color class. - - @author Morgan McGuire, matrix@graphics3d.com - @cite Portions by Laura Wollstadt, graphics3d.com - @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com - - - @created 2002-06-25 - @edited 2006-01-10 - */ - -#include -#include "G3D/Color4.h" -#include "G3D/Color4uint8.h" -#include "G3D/Vector4.h" -#include "G3D/format.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - -namespace G3D { - -const Color4& Color4::zero() { - static Color4 c(0.0f, 0.0f, 0.0f, 0.0f); - return c; -} - - -const Color4& Color4::inf() { - static Color4 c((float)G3D::inf(), (float)G3D::inf(), (float)G3D::inf(), (float)G3D::inf()); - return c; -} - - -const Color4& Color4::clear() { - return Color4::zero(); -} - - -Color4::Color4(const Vector4& v) { - r = v.x; - g = v.y; - b = v.z; - a = v.w; -} - - -Color4::Color4(const Color4uint8& c) : r(c.r), g(c.g), b(c.b), a(c.a) { - *this /= 255.0f; -} - -size_t Color4::hashCode() const { - unsigned int rhash = (*(int*)(void*)(&r)); - unsigned int ghash = (*(int*)(void*)(&g)); - unsigned int bhash = (*(int*)(void*)(&b)); - unsigned int ahash = (*(int*)(void*)(&a)); - - return rhash + (ghash * 37) + (bhash * 101) + (ahash * 241); -} - -Color4 Color4::fromARGB(uint32 x) { - return Color4( - (float)((x >> 16) & 0xFF), - (float)((x >> 8) & 0xFF), - (float)(x & 0xFF), - (float)((x >> 24) & 0xFF)) / 255.0; -} - - -Color4::Color4(BinaryInput& bi) { - deserialize(bi); -} - - -void Color4::deserialize(BinaryInput& bi) { - r = bi.readFloat32(); - g = bi.readFloat32(); - b = bi.readFloat32(); - a = bi.readFloat32(); -} - - -void Color4::serialize(BinaryOutput& bo) const { - bo.writeFloat32(r); - bo.writeFloat32(g); - bo.writeFloat32(b); - bo.writeFloat32(a); -} - - -//---------------------------------------------------------------------------- - -Color4 Color4::operator/ (float fScalar) const { - Color4 kQuot; - - if (fScalar != 0.0f) { - float fInvScalar = 1.0f / fScalar; - kQuot.r = fInvScalar * r; - kQuot.g = fInvScalar * g; - kQuot.b = fInvScalar * b; - kQuot.a = fInvScalar * a; - return kQuot; - - } else { - - return Color4::inf(); - } -} - -//---------------------------------------------------------------------------- - -Color4& Color4::operator/= (float fScalar) { - if (fScalar != 0.0f) { - float fInvScalar = 1.0f / fScalar; - r *= fInvScalar; - g *= fInvScalar; - b *= fInvScalar; - a *= fInvScalar; - } else { - r = (float)G3D::inf(); - g = (float)G3D::inf(); - b = (float)G3D::inf(); - a = (float)G3D::inf(); - } - - return *this; -} - -//---------------------------------------------------------------------------- - -std::string Color4::toString() const { - return G3D::format("(%g, %g, %g, %g)", r, g, b, a); -} - -//---------------------------------------------------------------------------- - -}; // namespace - diff --git a/externals/g3dlite/G3D.lib/source/Color4uint8.cpp b/externals/g3dlite/G3D.lib/source/Color4uint8.cpp deleted file mode 100644 index 8c8636a742e..00000000000 --- a/externals/g3dlite/G3D.lib/source/Color4uint8.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - @file Color4uint8.cpp - - @author Morgan McGuire, matrix@graphics3d.com - - @created 2003-04-07 - @edited 2006-01-07 - */ -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Color4uint8.h" -#include "G3D/Color4.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - -namespace G3D { - -Color4uint8::Color4uint8(const class Color4& c) { - r = iMin(255, iFloor(c.r * 256)); - g = iMin(255, iFloor(c.g * 256)); - b = iMin(255, iFloor(c.b * 256)); - a = iMin(255, iFloor(c.a * 256)); -} - - -Color4uint8::Color4uint8(class BinaryInput& bi) { - deserialize(bi); -} - - -void Color4uint8::serialize(class BinaryOutput& bo) const { - bo.writeUInt8(r); - bo.writeUInt8(g); - bo.writeUInt8(b); - bo.writeUInt8(a); -} - - -void Color4uint8::deserialize(class BinaryInput& bi) { - r = bi.readUInt8(); - g = bi.readUInt8(); - b = bi.readUInt8(); - a = bi.readUInt8(); -} - - -} diff --git a/externals/g3dlite/G3D.lib/source/Cone.cpp b/externals/g3dlite/G3D.lib/source/Cone.cpp deleted file mode 100644 index 99b29b5b0af..00000000000 --- a/externals/g3dlite/G3D.lib/source/Cone.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/** - @file Cone.cpp - - Cone class - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2001-07-09 - @edited 2006-01-29 -*/ - -#include "G3D/platform.h" -#include "G3D/Cone.h" -#include "G3D/Line.h" -#include "G3D/Sphere.h" -#include "G3D/Box.h" - -namespace G3D { - -Cone::Cone(const Vector3 &tip, const Vector3 &direction, float angle) { - this->tip = tip; - this->direction = direction.direction(); - this->angle = angle; - - debugAssert(angle >= 0); - debugAssert(angle <= pi()); -} - -/** - Forms the smallest cone that contains the box. Undefined if - the tip is inside or on the box. - */ -Cone::Cone(const Vector3& tip, const Box& box) { - this->tip = tip; - this->direction = (box.center() - tip).direction(); - - // Find the biggest angle - float smallestDotProduct = direction.dot((box.corner(0) - tip).direction()); - - for (int i = 1; i < 8; ++i) { - float dp = direction.dot((box.corner(i) - tip).direction()); - - debugAssert(dp > 0); - - if (dp < smallestDotProduct) { - smallestDotProduct = dp; - } - } - - angle = acosf(smallestDotProduct); -} - - -bool Cone::intersects(const Sphere& b) const { - // If the bounding sphere contains the tip, then - // they definitely touch. - if (b.contains(this->tip)) { - return true; - } - - // Move the tip backwards, effectively making the cone bigger - // to account for the radius of the sphere. - - Vector3 tip = this->tip - direction * b.radius / sinf(angle); - - return Cone(tip, direction, angle).contains(b.center); -} - - -bool Cone::contains(const Vector3& v) const { - - Vector3 d = (v - tip).direction(); - - float x = d.dot(direction); - - return (x > 0) && (x >= cosf(angle)); -} - -}; // namespace diff --git a/externals/g3dlite/G3D.lib/source/ConvexPolyhedron.cpp b/externals/g3dlite/G3D.lib/source/ConvexPolyhedron.cpp deleted file mode 100644 index 76dbe21a7c4..00000000000 --- a/externals/g3dlite/G3D.lib/source/ConvexPolyhedron.cpp +++ /dev/null @@ -1,449 +0,0 @@ -/** - @file ConvexPolyhedron.cpp - - @author Morgan McGuire, morgan@graphics3d.com - - @created 2001-11-11 - @edited 2006-01-10 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#include "G3D/platform.h" -#include "G3D/ConvexPolyhedron.h" -#include "G3D/debug.h" - -namespace G3D { - -ConvexPolygon::ConvexPolygon(const Array& __vertex) : _vertex(__vertex) { - // Intentionally empty -} - - -bool ConvexPolygon::isEmpty() const { - return (_vertex.length() == 0) || (getArea() <= fuzzyEpsilon); -} - - -float ConvexPolygon::getArea() const { - - if (_vertex.length() < 3) { - return 0; - } - - float sum = 0; - - int length = _vertex.length(); - // Split into triangle fan, compute individual area - for (int v = 2; v < length; v++) { - int i0 = 0; - int i1 = v - 1; - int i2 = v; - - sum += (_vertex[i1] - _vertex[i0]).cross(_vertex[i2] - _vertex[i0]).magnitude() / 2; - } - - return sum; -} - -void ConvexPolygon::cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon &below) { - DirectedEdge edge; - cut(plane, above, below, edge); -} - -void ConvexPolygon::cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon &below, DirectedEdge &newEdge) { - above._vertex.resize(0); - below._vertex.resize(0); - - if (isEmpty()) { - //debugPrintf("Empty\n"); - return; - } - - int v = 0; - int length = _vertex.length(); - - - Vector3 polyNormal = normal(); - Vector3 planeNormal= plane.normal(); - - // See if the polygon is *in* the plane. - if (planeNormal.fuzzyEq(polyNormal) || planeNormal.fuzzyEq(-polyNormal)) { - // Polygon is parallel to the plane. It must be either above, - // below, or in the plane. - - double a, b, c, d; - Vector3 pt = _vertex[0]; - - plane.getEquation(a,b,c,d); - float r = (float)(a * pt.x + b * pt.y + c * pt.z + d); - - if (fuzzyGe(r, 0)) { - // The polygon is entirely in the plane. - //debugPrintf("Entirely above\n"); - above = *this; - return; - } else { - //debugPrintf("Entirely below (1)\n"); - below = *this; - return; - } - } - - - // Number of edges crossing the plane. Used for - // debug assertions. - int count = 0; - - // True when the last _vertex we looked at was above the plane - bool lastAbove = plane.halfSpaceContains(_vertex[v]); - - if (lastAbove) { - above._vertex.append(_vertex[v]); - } else { - below._vertex.append(_vertex[v]); - } - - for (v = 1; v < length; v++) { - bool isAbove = plane.halfSpaceContains(_vertex[v]); - - if (lastAbove ^ isAbove) { - // Switched sides. - // Create an interpolated point that lies - // in the plane, between the two points. - Line line = Line::fromTwoPoints(_vertex[v - 1], _vertex[v]); - Vector3 interp = line.intersection(plane); - - if (! interp.isFinite()) { - - // Since the polygon is not in the plane (we checked above), - // it must be the case that this edge (and only this edge) - // is in the plane. This only happens when the polygon is - // entirely below the plane except for one edge. This edge - // forms a degenerate polygon, so just treat the whole polygon - // as below the plane. - below = *this; - above._vertex.resize(0); - //debugPrintf("Entirely below\n"); - return; - } - - above._vertex.append(interp); - below._vertex.append(interp); - if (lastAbove) { - newEdge.stop = interp; - } else { - newEdge.start = interp; - } - count++; - } - - lastAbove = isAbove; - if (lastAbove) { - above._vertex.append(_vertex[v]); - } else { - below._vertex.append(_vertex[v]); - } - } - - // Loop back to the first point, seeing if an interpolated point is - // needed. - bool isAbove = plane.halfSpaceContains(_vertex[0]); - if (lastAbove ^ isAbove) { - Line line = Line::fromTwoPoints(_vertex[length - 1], _vertex[0]); - Vector3 interp = line.intersection(plane); - if (! interp.isFinite()) { - // Since the polygon is not in the plane (we checked above), - // it must be the case that this edge (and only this edge) - // is in the plane. This only happens when the polygon is - // entirely below the plane except for one edge. This edge - // forms a degenerate polygon, so just treat the whole polygon - // as below the plane. - below = *this; - above._vertex.resize(0); - //debugPrintf("Entirely below\n"); - return; - } - - above._vertex.append(interp); - below._vertex.append(interp); - debugAssertM(count < 2, "Convex polygons may only intersect planes at two edges."); - if (lastAbove) { - newEdge.stop = interp; - } else { - newEdge.start = interp; - } - count++; - } - - debugAssertM((count == 2) || (count == 0), "Convex polygons may only intersect planes at two edges."); -} - -ConvexPolygon ConvexPolygon::inverse() const { - ConvexPolygon result; - int length = _vertex.length(); - result._vertex.resize(length); - - for (int v = 0; v < length; v++) { - result._vertex[v] = _vertex[length - v - 1]; - } - - return result; -} - -void ConvexPolygon::removeDuplicateVertices(){ - // Any valid polygon should have 3 or more vertices, but why take chances? - if(_vertex.size() >= 2){ - - // Remove duplicate vertices. - for(int i=0;i<_vertex.size()-1;++i){ - if(_vertex[i].fuzzyEq(_vertex[i+1])){ - _vertex.remove(i+1); - --i; // Don't move forward. - } - } - - // Check the last vertex against the first. - if(_vertex[_vertex.size()-1].fuzzyEq(_vertex[0])){ - _vertex.pop(); - } - } -} - -////////////////////////////////////////////////////////////////////////////// - -ConvexPolyhedron::ConvexPolyhedron(const Array& _face) : face(_face) { - // Intentionally empty -} - -float ConvexPolyhedron::getVolume() const { - - if (face.length() < 4) { - return 0; - } - - // The volume of any pyramid is 1/3 * h * base area. - // Discussion at: http://nrich.maths.org/mathsf/journalf/oct01/art1/ - - float sum = 0; - - // Choose the first _vertex of the first face as the origin. - // This lets us skip one face, too, and avoids negative heights. - Vector3 v0 = face[0]._vertex[0]; - for (int f = 1; f < face.length(); f++) { - const ConvexPolygon& poly = face[f]; - - float height = (poly._vertex[0] - v0).dot(poly.normal()); - float base = poly.getArea(); - - sum += height * base; - } - - return sum / 3; -} - -bool ConvexPolyhedron::isEmpty() const { - return (face.length() == 0) || (getVolume() <= fuzzyEpsilon); -} - -void ConvexPolyhedron::cut(const Plane& plane, ConvexPolyhedron &above, ConvexPolyhedron &below) { - above.face.resize(0); - below.face.resize(0); - - Array edge; - - int f; - - // See if the plane cuts this polyhedron at all. Detect when - // the polyhedron is entirely to one side or the other. - //{ - int numAbove = 0, numIn = 0, numBelow = 0; - bool ruledOut = false; - double d; - Vector3 abc; - plane.getEquation(abc, d); - - // This number has to be fairly large to prevent precision problems down - // the road. - const float eps = 0.005f; - for (f = face.length() - 1; (f >= 0) && (!ruledOut); f--) { - const ConvexPolygon& poly = face[f]; - for (int v = poly._vertex.length() - 1; (v >= 0) && (!ruledOut); v--) { - double r = abc.dot(poly._vertex[v]) + d; - if (r > eps) { - numAbove++; - } else if (r < -eps) { - numBelow++; - } else { - numIn++; - } - - ruledOut = (numAbove != 0) && (numBelow !=0); - } - } - - if (numBelow == 0) { - above = *this; - return; - } else if (numAbove == 0) { - below = *this; - return; - } - //} - - // Clip each polygon, collecting split edges. - for (f = face.length() - 1; f >= 0; f--) { - ConvexPolygon a, b; - DirectedEdge e; - face[f].cut(plane, a, b, e); - - bool aEmpty = a.isEmpty(); - bool bEmpty = b.isEmpty(); - - //debugPrintf("\n"); - if (! aEmpty) { - //debugPrintf(" Above %f\n", a.getArea()); - above.face.append(a); - } - - if (! bEmpty) { - //debugPrintf(" Below %f\n", b.getArea()); - below.face.append(b); - } - - if (! aEmpty && ! bEmpty) { - //debugPrintf(" == Split\n"); - edge.append(e); - } else { - // Might be the case that the polygon is entirely on - // one side of the plane yet there is an edge we need - // because it touches the plane. - // - // Extract the non-empty _vertex list and examine it. - // If we find exactly one edge in the plane, add that edge. - const Array& _vertex = (aEmpty ? b._vertex : a._vertex); - int L = _vertex.length(); - int count = 0; - for (int v = 0; v < L; v++) { - if (plane.fuzzyContains(_vertex[v]) && plane.fuzzyContains(_vertex[(v + 1) % L])) { - e.start = _vertex[v]; - e.stop = _vertex[(v + 1) % L]; - count++; - } - } - - if (count == 1) { - edge.append(e); - } - } - } - - if (above.face.length() == 1) { - // Only one face above means that this entire - // polyhedron is below the plane. Move that face over. - below.face.append(above.face[0]); - above.face.resize(0); - } else if (below.face.length() == 1) { - // This shouldn't happen, but it arises in practice - // from numerical imprecision. - above.face.append(below.face[0]); - below.face.resize(0); - } - - if ((above.face.length() > 0) && (below.face.length() > 0)) { - // The polyhedron was actually cut; create a cap polygon - ConvexPolygon cap; - - // Collect the final polgyon by sorting the edges - int numVertices = edge.length(); -/*debugPrintf("\n"); -for (int xx=0; xx < numVertices; xx++) { - std::string s1 = edge[xx].start.toString(); - std::string s2 = edge[xx].stop.toString(); - debugPrintf("%s -> %s\n", s1.c_str(), s2.c_str()); -} -*/ - - // Need at least three points to make a polygon - debugAssert(numVertices >= 3); - - Vector3 last_vertex = edge.last().stop; - cap._vertex.append(last_vertex); - - // Search for the next _vertex. Because of accumulating - // numerical error, we have to find the closest match, not - // just the one we expect. - for (int v = numVertices - 1; v >= 0; v--) { - // matching edge index - int index = 0; - int num = edge.length(); - double distance = (edge[index].start - last_vertex).squaredMagnitude(); - for (int e = 1; e < num; e++) { - double d = (edge[e].start - last_vertex).squaredMagnitude(); - - if (d < distance) { - // This is the new closest one - index = e; - distance = d; - } - } - - // Don't tolerate ridiculous error. - debugAssertM(distance < 0.02, "Edge missing while closing polygon."); - - last_vertex = edge[index].stop; - cap._vertex.append(last_vertex); - } - - //debugPrintf("\n"); - //debugPrintf("Cap (both) %f\n", cap.getArea()); - above.face.append(cap); - below.face.append(cap.inverse()); - } - - // Make sure we put enough faces on each polyhedra - debugAssert((above.face.length() == 0) || (above.face.length() >= 4)); - debugAssert((below.face.length() == 0) || (below.face.length() >= 4)); -} - -/////////////////////////////////////////////// - -ConvexPolygon2D::ConvexPolygon2D(const Array& pts, bool reverse) : m_vertex(pts) { - if (reverse) { - m_vertex.reverse(); - } -} - - -bool ConvexPolygon2D::contains(const Vector2& p, bool reverse) const { - // Compute the signed area of each polygon from p to an edge. - // If the area is non-negative for all polygons then p is inside - // the polygon. (To adapt this algorithm for a concave polygon, - // the *sum* of the areas must be non-negative). - - float r = reverse ? -1 : 1; - - for (int i0 = 0; i0 < m_vertex.size(); ++i0) { - int i1 = (i0 + 1) % m_vertex.size(); - const Vector2& v0 = m_vertex[i0]; - const Vector2& v1 = m_vertex[i1]; - - Vector2 e0 = v0 - p; - Vector2 e1 = v1 - p; - - // Area = (1/2) cross product, negated to be ccw in - // a 2D space; we neglect the 1/2 - float area = -(e0.x * e1.y - e0.y * e1.x); - - if (area * r < 0) { - return false; - } - } - - return true; -} - - -} - diff --git a/externals/g3dlite/G3D.lib/source/CoordinateFrame.cpp b/externals/g3dlite/G3D.lib/source/CoordinateFrame.cpp deleted file mode 100644 index b6e94fe5857..00000000000 --- a/externals/g3dlite/G3D.lib/source/CoordinateFrame.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/** - @file CoordinateFrame.cpp - - Coordinate frame class - - @maintainer Morgan McGuire, morgan@cs.williams.edu - - @created 2001-06-02 - @edited 2008-07-13 -*/ - -#include "G3D/platform.h" -#include "G3D/CoordinateFrame.h" -#include "G3D/Quat.h" -#include "G3D/Matrix4.h" -#include "G3D/Box.h" -#include "G3D/AABox.h" -#include "G3D/Sphere.h" -#include "G3D/Triangle.h" -#include "G3D/Ray.h" -#include "G3D/Capsule.h" -#include "G3D/Cylinder.h" -#include "G3D/UprightFrame.h" - -namespace G3D { - -CoordinateFrame::CoordinateFrame(const class UprightFrame& f) { - *this = f.toCoordinateFrame(); -} - - -CoordinateFrame CoordinateFrame::fromXYZYPRRadians(float x, float y, float z, float yaw, - float pitch, float roll) { - Matrix3 rotation = Matrix3::fromAxisAngle(Vector3::unitY(), yaw); - - rotation = Matrix3::fromAxisAngle(rotation.column(0), pitch) * rotation; - rotation = Matrix3::fromAxisAngle(rotation.column(2), roll) * rotation; - - const Vector3 translation(x, y, z); - - return CoordinateFrame(rotation, translation); -} - - -void CoordinateFrame::getXYZYPRRadians(float& x, float& y, float& z, - float& yaw, float& pitch, float& roll) const { - x = translation.x; - y = translation.y; - z = translation.z; - - const Vector3& look = lookVector(); - - if (abs(look.y) > 0.99f) { - // Looking nearly straight up or down - - yaw = G3D::pi() + atan2(look.x, look.z); - pitch = asin(look.y); - roll = 0.0f; - - } else { - - // Yaw cannot be affected by others, so pull it first - yaw = G3D::pi() + atan2(look.x, look.z); - - // Pitch is the elevation of the yaw vector - pitch = asin(look.y); - - Vector3 actualRight = rightVector(); - Vector3 expectedRight = look.cross(Vector3::unitY()); - - roll = 0;//acos(actualRight.dot(expectedRight)); TODO - } -} - - -void CoordinateFrame::getXYZYPRDegrees(float& x, float& y, float& z, - float& yaw, float& pitch, float& roll) const { - getXYZYPRRadians(x, y, z, yaw, pitch, roll); - yaw = toDegrees(yaw); - pitch = toDegrees(pitch); - roll = toDegrees(roll); -} - - -CoordinateFrame CoordinateFrame::fromXYZYPRDegrees(float x, float y, float z, - float yaw, float pitch, float roll) { - return fromXYZYPRRadians(x, y, z, toRadians(yaw), toRadians(pitch), toRadians(roll)); -} - - -Ray CoordinateFrame::lookRay() const { - return Ray::fromOriginAndDirection(translation, lookVector()); -} - - -bool CoordinateFrame::fuzzyEq(const CoordinateFrame& other) const { - - for (int c = 0; c < 3; ++c) { - for (int r = 0; r < 3; ++r) { - if (! G3D::fuzzyEq(other.rotation[r][c], rotation[r][c])) { - return false; - } - } - if (! G3D::fuzzyEq(translation[c], other.translation[c])) { - return false; - } - } - - return true; -} - - -bool CoordinateFrame::fuzzyIsIdentity() const { - const Matrix3& I = Matrix3::identity(); - - for (int c = 0; c < 3; ++c) { - for (int r = 0; r < 3; ++r) { - if (fuzzyNe(I[r][c], rotation[r][c])) { - return false; - } - } - if (fuzzyNe(translation[c], 0)) { - return false; - } - } - - return true; -} - - -bool CoordinateFrame::isIdentity() const { - return - (translation == Vector3::zero()) && - (rotation == Matrix3::identity()); -} - - -Matrix4 CoordinateFrame::toMatrix4() const { - return Matrix4(*this); -} - - -std::string CoordinateFrame::toXML() const { - return G3D::format( - "\n %lf,%lf,%lf,%lf,\n %lf,%lf,%lf,%lf,\n %lf,%lf,%lf,%lf,\n %lf,%lf,%lf,%lf\n\n", - rotation[0][0], rotation[0][1], rotation[0][2], translation.x, - rotation[1][0], rotation[1][1], rotation[1][2], translation.y, - rotation[2][0], rotation[2][1], rotation[2][2], translation.z, - 0.0, 0.0, 0.0, 1.0); -} - - -Plane CoordinateFrame::toObjectSpace(const Plane& p) const { - Vector3 N, P; - double d; - p.getEquation(N, d); - P = N * (float)d; - P = pointToObjectSpace(P); - N = normalToObjectSpace(N); - return Plane(N, P); -} - - -Plane CoordinateFrame::toWorldSpace(const Plane& p) const { - Vector3 N, P; - double d; - p.getEquation(N, d); - P = N * (float)d; - P = pointToWorldSpace(P); - N = normalToWorldSpace(N); - return Plane(N, P); -} - - -Triangle CoordinateFrame::toObjectSpace(const Triangle& t) const { - return Triangle(pointToObjectSpace(t.vertex(0)), - pointToObjectSpace(t.vertex(1)), - pointToObjectSpace(t.vertex(2))); -} - - -Triangle CoordinateFrame::toWorldSpace(const Triangle& t) const { - return Triangle(pointToWorldSpace(t.vertex(0)), - pointToWorldSpace(t.vertex(1)), - pointToWorldSpace(t.vertex(2))); -} - - -Cylinder CoordinateFrame::toWorldSpace(const Cylinder& c) const { - return Cylinder( - pointToWorldSpace(c.point(0)), - pointToWorldSpace(c.point(1)), - c.radius()); -} - - -Capsule CoordinateFrame::toWorldSpace(const Capsule& c) const { - return Capsule( - pointToWorldSpace(c.point(0)), - pointToWorldSpace(c.point(1)), - c.radius()); -} - - -Box CoordinateFrame::toWorldSpace(const AABox& b) const { - return toWorldSpace(Box(b)); -} - - -Box CoordinateFrame::toWorldSpace(const Box& b) const { - Box out(b); - - for (int i = 0; i < 8; ++i) { - out._corner[i] = pointToWorldSpace(out._corner[i]); - debugAssert(! isNaN(out._corner[i].x)); - } - - for (int i = 0; i < 3; ++i) { - out._axis[i] = vectorToWorldSpace(out._axis[i]); - } - - out._center = pointToWorldSpace(out._center); - - return out; -} - - -Box CoordinateFrame::toObjectSpace(const Box &b) const { - return inverse().toWorldSpace(b); -} - - -Box CoordinateFrame::toObjectSpace(const AABox& b) const { - return toObjectSpace(Box(b)); -} - - -CoordinateFrame::CoordinateFrame(class BinaryInput& b) : rotation(Matrix3::zero()) { - deserialize(b); -} - - -void CoordinateFrame::deserialize(class BinaryInput& b) { - rotation.deserialize(b); - translation.deserialize(b); -} - - -void CoordinateFrame::serialize(class BinaryOutput& b) const { - rotation.serialize(b); - translation.serialize(b); -} - - -Sphere CoordinateFrame::toWorldSpace(const Sphere &b) const { - return Sphere(pointToWorldSpace(b.center), b.radius); -} - - -Sphere CoordinateFrame::toObjectSpace(const Sphere &b) const { - return Sphere(pointToObjectSpace(b.center), b.radius); -} - - -Ray CoordinateFrame::toWorldSpace(const Ray& r) const { - return Ray::fromOriginAndDirection(pointToWorldSpace(r.origin), vectorToWorldSpace(r.direction)); -} - - -Ray CoordinateFrame::toObjectSpace(const Ray& r) const { - return Ray::fromOriginAndDirection(pointToObjectSpace(r.origin), vectorToObjectSpace(r.direction)); -} - - -void CoordinateFrame::lookAt(const Vector3 &target) { - lookAt(target, Vector3::unitY()); -} - - -void CoordinateFrame::lookAt( - const Vector3& target, - Vector3 up) { - - up = up.direction(); - - Vector3 look = (target - translation).direction(); - if (fabs(look.dot(up)) > .99f) { - up = Vector3::unitX(); - if (fabs(look.dot(up)) > .99f) { - up = Vector3::unitY(); - } - } - - up -= look * look.dot(up); - up.unitize(); - - Vector3 z = -look; - Vector3 x = -z.cross(up); - x.unitize(); - - Vector3 y = z.cross(x); - - rotation.setColumn(0, x); - rotation.setColumn(1, y); - rotation.setColumn(2, z); -} - - -CoordinateFrame CoordinateFrame::lerp( - const CoordinateFrame& other, - float alpha) const { - - if (alpha == 1.0f) { - return other; - } else if (alpha == 0.0f) { - return *this; - } else { - Quat q1 = Quat(this->rotation); - Quat q2 = Quat(other.rotation); - - return CoordinateFrame( - q1.slerp(q2, alpha).toRotationMatrix(), - this->translation * (1 - alpha) + other.translation * alpha); - } -} - - -void CoordinateFrame::pointToWorldSpace(const Array& v, Array& vout) const { - vout.resize(v.size()); - - for (int i = v.size() - 1; i >= 0; --i) { - vout[i] = pointToWorldSpace(v[i]); - } -} - - -void CoordinateFrame::normalToWorldSpace(const Array& v, Array& vout) const { - vout.resize(v.size()); - - for (int i = v.size() - 1; i >= 0; --i) { - vout[i] = normalToWorldSpace(v[i]); - } -} - - -void CoordinateFrame::vectorToWorldSpace(const Array& v, Array& vout) const { - vout.resize(v.size()); - - for (int i = v.size() - 1; i >= 0; --i) { - vout[i] = vectorToWorldSpace(v[i]); - } -} - - -void CoordinateFrame::pointToObjectSpace(const Array& v, Array& vout) const { - vout.resize(v.size()); - - for (int i = v.size() - 1; i >= 0; --i) { - vout[i] = pointToObjectSpace(v[i]); - } -} - - -void CoordinateFrame::normalToObjectSpace(const Array& v, Array& vout) const { - vout.resize(v.size()); - - for (int i = v.size() - 1; i >= 0; --i) { - vout[i] = normalToObjectSpace(v[i]); - } -} - - -void CoordinateFrame::vectorToObjectSpace(const Array& v, Array& vout) const { - vout.resize(v.size()); - - for (int i = v.size() - 1; i >= 0; --i) { - vout[i] = vectorToObjectSpace(v[i]); - } -} - -} // namespace diff --git a/externals/g3dlite/G3D.lib/source/Crypto.cpp b/externals/g3dlite/G3D.lib/source/Crypto.cpp deleted file mode 100644 index 09aee2c265d..00000000000 --- a/externals/g3dlite/G3D.lib/source/Crypto.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/** - @file Crypto.cpp - - @author Morgan McGuire, matrix@graphics3d.com - - - @created 2006-03-28 - @edited 2006-04-06 - */ - -#include "G3D/platform.h" -#include "G3D/Crypto.h" -#include "G3D/g3dmath.h" -#include - -namespace G3D { - - -int Crypto::smallPrime(int n) { - debugAssert(n < numSmallPrimes() && n >= 0); - - // From: - // http://primes.utm.edu/lists/small/1000.txt - - static const int table[] = { - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, - 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, - 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, - 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, - 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, - 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, - 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, - 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, - 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, - 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, - 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, - 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, - 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, - 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, - 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, - 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, - 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, - 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, - 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, - 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, - 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, - 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, - 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, - 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, - 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, - 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, - 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, - 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, - 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, - 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, - 1993, 1997, 1999}; - - return table[n]; -} - - -int Crypto::numSmallPrimes() { - return 303; -} - -uint32 Crypto::crc32(const void* byte, size_t numBytes) { - return ::crc32(::crc32(0, Z_NULL, 0), static_cast(byte), numBytes); -} - -} // G3D diff --git a/externals/g3dlite/G3D.lib/source/Crypto_md5.cpp b/externals/g3dlite/G3D.lib/source/Crypto_md5.cpp deleted file mode 100644 index 4aa24c39f9c..00000000000 --- a/externals/g3dlite/G3D.lib/source/Crypto_md5.cpp +++ /dev/null @@ -1,471 +0,0 @@ -/** - @file Crypto_md5.cpp - - @author Morgan McGuire, matrix@graphics3d.com - Copyright 2006-2007, Morgan McGuire. All rights reserved. - - @created 2006-03-28 - @edited 2006-04-06 - */ - -#include "G3D/platform.h" -#include "G3D/Crypto.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - -#include - -namespace G3D { - - -MD5Hash::MD5Hash(class BinaryInput& b) { - deserialize(b); -} - - -void MD5Hash::deserialize(class BinaryInput& b) { - b.readBytes(value, 16); -} - - -void MD5Hash::serialize(class BinaryOutput& b) const { - b.writeBytes(value, 16); -} - - -typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ - -/* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ -} md5_state_t; - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Initialize the algorithm. */ -static void md5_init(md5_state_t *pms); - -/* Append a string to the message. */ -static void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); - -/* Finish the message and return the digest. */ -void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); -#ifdef __cplusplus -} -#endif - - - -MD5Hash Crypto::md5(const void* data, size_t n) { - md5_state_t state; - md5_init(&state); - md5_append(&state, (const uint8*)data, (int)n); - - MD5Hash h; - md5_finish(&state, &(h[0])); - return h; -} - -/* - Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. - - 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. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - - The original and principal author of md5.c is L. Peter Deutsch - . Other authors are noted in the change history - that follows (in reverse chronological order): - - 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order - either statically or dynamically; added missing #include - in library. - 2002-03-11 lpd Corrected argument list for main(), and added int return - type, in test program and T value program. - 2002-02-21 lpd Added missing #include in test program. - 2000-07-03 lpd Patched to eliminate warnings about "constant is - unsigned in ANSI C, signed in traditional"; made test program - self-checking. - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). - 1999-05-03 lpd Original version. - */ - -/* - * This package supports both compile-time and run-time determination of CPU - * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be - * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is - * defined as non-zero, the code will be compiled to run only on big-endian - * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to - * run on either big- or little-endian CPUs, but will run slightly less - * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. - */ - - -#if defined(G3D_LINUX) || defined(G3D_OSX) -# if defined(G3D_OSX_PPC) -# include -# elif defined(G3D_OSX_INTEL) -# include -# elif defined(__linux__) -# include -# elif defined(__FreeBSD__) -# include -# endif -#else -# define BYTE_ORDER 0 -#endif - -#define T_MASK ((md5_word_t)~0) -#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) -#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) -#define T3 0x242070db -#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) -#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) -#define T6 0x4787c62a -#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) -#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) -#define T9 0x698098d8 -#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) -#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) -#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) -#define T13 0x6b901122 -#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) -#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) -#define T16 0x49b40821 -#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) -#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) -#define T19 0x265e5a51 -#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) -#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) -#define T22 0x02441453 -#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) -#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) -#define T25 0x21e1cde6 -#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) -#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) -#define T28 0x455a14ed -#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) -#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) -#define T31 0x676f02d9 -#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) -#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) -#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) -#define T35 0x6d9d6122 -#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) -#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) -#define T38 0x4bdecfa9 -#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) -#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) -#define T41 0x289b7ec6 -#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) -#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) -#define T44 0x04881d05 -#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) -#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) -#define T47 0x1fa27cf8 -#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) -#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) -#define T50 0x432aff97 -#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) -#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) -#define T53 0x655b59c3 -#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) -#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) -#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) -#define T57 0x6fa87e4f -#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) -#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) -#define T60 0x4e0811a1 -#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) -#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) -#define T63 0x2ad7d2bb -#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) - - -static void -md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) -{ - md5_word_t - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; - md5_word_t t; -#if BYTE_ORDER > 0 - /* Define storage only for big-endian CPUs. */ - md5_word_t X[16]; -#else - /* Define storage for little-endian or both types of CPUs. */ - md5_word_t xbuf[16]; - const md5_word_t *X; -#endif - - { -#if BYTE_ORDER == 0 - /* - * Determine dynamically whether this is a big-endian or - * little-endian machine, since we can use a more efficient - * algorithm on the latter. - */ - static const int w = 1; - - if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ -#endif -#if BYTE_ORDER <= 0 /* little-endian */ - { - /* - * On little-endian machines, we can process properly aligned - * data without copying it. - */ - if (!((data - (const md5_byte_t *)0) & 3)) { - /* data are properly aligned */ - X = (const md5_word_t *)data; - } else { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } - } -#endif -#if BYTE_ORDER == 0 - else /* dynamic big-endian */ -#endif -#if BYTE_ORDER >= 0 /* big-endian */ - { - /* - * On big-endian machines, we must arrange the bytes in the - * right order. - */ - const md5_byte_t *xp = data; - int i; - -# if BYTE_ORDER == 0 - X = xbuf; /* (dynamic only) */ -# else -# define xbuf X /* (static only) */ -# endif - for (i = 0; i < 16; ++i, xp += 4) - xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - } -#endif - } - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + F(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 7, T1); - SET(d, a, b, c, 1, 12, T2); - SET(c, d, a, b, 2, 17, T3); - SET(b, c, d, a, 3, 22, T4); - SET(a, b, c, d, 4, 7, T5); - SET(d, a, b, c, 5, 12, T6); - SET(c, d, a, b, 6, 17, T7); - SET(b, c, d, a, 7, 22, T8); - SET(a, b, c, d, 8, 7, T9); - SET(d, a, b, c, 9, 12, T10); - SET(c, d, a, b, 10, 17, T11); - SET(b, c, d, a, 11, 22, T12); - SET(a, b, c, d, 12, 7, T13); - SET(d, a, b, c, 13, 12, T14); - SET(c, d, a, b, 14, 17, T15); - SET(b, c, d, a, 15, 22, T16); -#undef SET - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + G(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 1, 5, T17); - SET(d, a, b, c, 6, 9, T18); - SET(c, d, a, b, 11, 14, T19); - SET(b, c, d, a, 0, 20, T20); - SET(a, b, c, d, 5, 5, T21); - SET(d, a, b, c, 10, 9, T22); - SET(c, d, a, b, 15, 14, T23); - SET(b, c, d, a, 4, 20, T24); - SET(a, b, c, d, 9, 5, T25); - SET(d, a, b, c, 14, 9, T26); - SET(c, d, a, b, 3, 14, T27); - SET(b, c, d, a, 8, 20, T28); - SET(a, b, c, d, 13, 5, T29); - SET(d, a, b, c, 2, 9, T30); - SET(c, d, a, b, 7, 14, T31); - SET(b, c, d, a, 12, 20, T32); -#undef SET - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + H(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 5, 4, T33); - SET(d, a, b, c, 8, 11, T34); - SET(c, d, a, b, 11, 16, T35); - SET(b, c, d, a, 14, 23, T36); - SET(a, b, c, d, 1, 4, T37); - SET(d, a, b, c, 4, 11, T38); - SET(c, d, a, b, 7, 16, T39); - SET(b, c, d, a, 10, 23, T40); - SET(a, b, c, d, 13, 4, T41); - SET(d, a, b, c, 0, 11, T42); - SET(c, d, a, b, 3, 16, T43); - SET(b, c, d, a, 6, 23, T44); - SET(a, b, c, d, 9, 4, T45); - SET(d, a, b, c, 12, 11, T46); - SET(c, d, a, b, 15, 16, T47); - SET(b, c, d, a, 2, 23, T48); -#undef SET - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + I(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 6, T49); - SET(d, a, b, c, 7, 10, T50); - SET(c, d, a, b, 14, 15, T51); - SET(b, c, d, a, 5, 21, T52); - SET(a, b, c, d, 12, 6, T53); - SET(d, a, b, c, 3, 10, T54); - SET(c, d, a, b, 10, 15, T55); - SET(b, c, d, a, 1, 21, T56); - SET(a, b, c, d, 8, 6, T57); - SET(d, a, b, c, 15, 10, T58); - SET(c, d, a, b, 6, 15, T59); - SET(b, c, d, a, 13, 21, T60); - SET(a, b, c, d, 4, 6, T61); - SET(d, a, b, c, 11, 10, T62); - SET(c, d, a, b, 2, 15, T63); - SET(b, c, d, a, 9, 21, T64); -#undef SET - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; -} - -void -md5_init(md5_state_t *pms) -{ - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; - pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; - pms->abcd[3] = 0x10325476; -} - -void -md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) -{ - const md5_byte_t *p = data; - int left = nbytes; - int offset = (pms->count[0] >> 3) & 63; - md5_word_t nbits = (md5_word_t)(nbytes << 3); - - if (nbytes <= 0) - return; - - /* Update the message length. */ - pms->count[1] += nbytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - pms->count[1]++; - - /* Process an initial partial block. */ - if (offset) { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); -} - -void -md5_finish(md5_state_t *pms, md5_byte_t digest[16]) -{ - static const md5_byte_t pad[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - md5_byte_t data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - md5_append(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); -} - -} diff --git a/externals/g3dlite/G3D.lib/source/Cylinder.cpp b/externals/g3dlite/G3D.lib/source/Cylinder.cpp deleted file mode 100644 index bdc7d56be23..00000000000 --- a/externals/g3dlite/G3D.lib/source/Cylinder.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/** - @file Cylinder.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-02-07 - @edited 2006-02-18 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#include "G3D/platform.h" -#include "G3D/Cylinder.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/LineSegment.h" -#include "G3D/CoordinateFrame.h" -#include "G3D/Line.h" -#include "G3D/AABox.h" - -namespace G3D { - -Cylinder::Cylinder(class BinaryInput& b) { - deserialize(b); -} - - -Cylinder::Cylinder() { -} - - -Cylinder::Cylinder(const Vector3& _p1, const Vector3& _p2, float _r) - : p1(_p1), p2(_p2), mRadius(_r) { -} - - -void Cylinder::serialize(class BinaryOutput& b) const { - p1.serialize(b); - p2.serialize(b); - b.writeFloat64(mRadius); -} - - -void Cylinder::deserialize(class BinaryInput& b) { - p1.deserialize(b); - p2.deserialize(b); - mRadius = b.readFloat64(); -} - - -Line Cylinder::axis() const { - return Line::fromTwoPoints(p1, p2); -} - - - -float Cylinder::radius() const { - return mRadius; -} - - -float Cylinder::volume() const { - return - (float)pi() * square(mRadius) * (p1 - p2).magnitude(); -} - - -float Cylinder::area() const { - return - // Sides - (twoPi() * mRadius) * height() + - - // Caps - twoPi() * square(mRadius); -} - -void Cylinder::getBounds(AABox& out) const { - Vector3 min = p1.min(p2) - (Vector3(1, 1, 1) * mRadius); - Vector3 max = p1.max(p2) + (Vector3(1, 1, 1) * mRadius); - out = AABox(min, max); -} - -bool Cylinder::contains(const Vector3& p) const { - return LineSegment::fromTwoPoints(p1, p2).distanceSquared(p) <= square(mRadius); -} - - -void Cylinder::getReferenceFrame(CoordinateFrame& cframe) const { - cframe.translation = center(); - - Vector3 Y = (p1 - p2).direction(); - Vector3 X = (abs(Y.dot(Vector3::unitX())) > 0.9) ? Vector3::unitY() : Vector3::unitX(); - Vector3 Z = X.cross(Y).direction(); - X = Y.cross(Z); - cframe.rotation.setColumn(0, X); - cframe.rotation.setColumn(1, Y); - cframe.rotation.setColumn(2, Z); -} - - -void Cylinder::getRandomSurfacePoint(Vector3& p, Vector3& N) const { - float h = height(); - float r = radius(); - - // Create a random point on a standard cylinder and then rotate to the global frame. - - // Relative areas (factor of 2PI already taken out) - float capRelArea = square(r) / 2.0f; - float sideRelArea = r * h; - - float r1 = uniformRandom(0, capRelArea * 2 + sideRelArea); - - if (r1 < capRelArea * 2) { - - // Select a point uniformly at random on a disk - // @cite http://mathworld.wolfram.com/DiskPointPicking.html - float a = uniformRandom(0, (float)twoPi()); - float r2 = sqrt(uniformRandom(0, 1)) * r; - p.x = cos(a) * r2; - p.z = sin(a) * r2; - - N.x = 0; - N.z = 0; - if (r1 < capRelArea) { - // Top - p.y = h / 2.0f; - N.y = 1; - } else { - // Bottom - p.y = -h / 2.0f; - N.y = -1; - } - } else { - // Side - float a = uniformRandom(0, (float)twoPi()); - N.x = cos(a); - N.y = 0; - N.z = sin(a); - p.x = N.x * r; - p.z = N.y * r; - p.y = uniformRandom(-h / 2.0f, h / 2.0f); - } - - // Transform to world space - CoordinateFrame cframe; - getReferenceFrame(cframe); - - p = cframe.pointToWorldSpace(p); - N = cframe.normalToWorldSpace(N); -} - - -Vector3 Cylinder::randomInteriorPoint() const { - float h = height(); - float r = radius(); - - // Create a random point in a standard cylinder and then rotate to the global frame. - - // Select a point uniformly at random on a disk - // @cite http://mathworld.wolfram.com/DiskPointPicking.html - float a = uniformRandom(0, (float)twoPi()); - float r2 = sqrt(uniformRandom(0, 1)) * r; - - Vector3 p( cos(a) * r2, - uniformRandom(-h / 2.0f, h / 2.0f), - sin(a) * r2); - - // Transform to world space - CoordinateFrame cframe; - getReferenceFrame(cframe); - - return cframe.pointToWorldSpace(p); -} - -} // namespace diff --git a/externals/g3dlite/G3D.lib/source/Discovery.cpp b/externals/g3dlite/G3D.lib/source/Discovery.cpp deleted file mode 100644 index 2c27c5bf2b9..00000000000 --- a/externals/g3dlite/G3D.lib/source/Discovery.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/** - @file Discovery.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-06-26 - @edited 2005-02-24 - */ - -#include "G3D/Discovery.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - -#include - -namespace G3D { - -/////////////////////////////////////////////////////////////////////////////////////////// - -void DiscoveryAdvertisement::serialize(BinaryOutput& b) const { - address.serialize(b); -} - -void DiscoveryAdvertisement::deserialize(BinaryInput& b) { - address.deserialize(b); - lastUpdateTime = System::time(); -} - - -/////////////////////////////////////////////////////////////////////////////////////////// - -void DiscoveryServerAddressMessage::serialize(BinaryOutput& b) const { - b.writeString(G3D_DISCOVERY_PROTOCOL_NAME); - b.writeInt32(G3D_DISCOVERY_PROTOCOL_VERSION); - b.writeString(settings->appProtocolName); - b.writeInt32(settings->appProtocolVersion); - - // Send addresses - b.writeInt32(address.size()); - for (int i = 0; i < address.size(); ++i) { - address[i].serialize(b); - } -} - - -void DiscoveryServerAddressMessage::deserialize(BinaryInput& b) { - address.clear(); - correctProtocol = false; - serverProtocolVersion[0] = 0; - serverProtocolVersion[1] = 0; - - // Verify that we are on the same protocol - if (b.readString(strlen(G3D_DISCOVERY_PROTOCOL_NAME) + 1) != G3D_DISCOVERY_PROTOCOL_NAME) { - return; - } - - serverProtocolVersion[0] = b.readInt32(); - if (serverProtocolVersion[0] != G3D_DISCOVERY_PROTOCOL_VERSION) { - return; - } - - if (b.readString() != settings->appProtocolName) { - return; - } - - serverProtocolVersion[1] = b.readInt32(); - if (serverProtocolVersion[1] != settings->appProtocolVersion) { - return; - } - - correctProtocol = true; - - address.resize(b.readInt32()); - for (int i = 0; i < address.size(); ++i) { - address[i].deserialize(b); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////// - -void DiscoveryServer::sendAnnouncement() const { - NetAddress broadcast(NetworkDevice::instance()->broadcastAddressArray()[0], settings->serverBroadcastPort); - - net->send(broadcast, SERVER_BROADCAST_MESSAGE, addressMessage); - - const_cast(this)->lastBroadcast = System::time(); -} - - -void DiscoveryServer::sendShutDown() const { - NetAddress broadcast(NetworkDevice::instance()->broadcastAddressArray()[0], settings->serverBroadcastPort); - ShutdownMessage s; - net->send(broadcast, SERVER_SHUTDOWN_MESSAGE, s); -} - - -bool DiscoveryServer::ok() const { - return listener->ok() && net->ok(); -} - - -void DiscoveryServer::init( - const DiscoverySettings* _settings, - DiscoveryAdvertisement* _advertisement) { - - Discovery::init(_settings); - - advertisement = _advertisement; - addressMessage.settings = settings; - NetworkDevice::instance()->localHostAddresses(addressMessage.address); - - // Set the port number - for (int i = 0; i < addressMessage.address.size(); ++i) { - addressMessage.address[i] = - NetAddress(addressMessage.address[i].ip(), - settings->serverAdvertisementPort); - } - - net = LightweightConduit::create(settings->clientBroadcastPort, true, true); - - listener = NetListener::create(settings->serverAdvertisementPort); - - // Send initial announcement - sendAnnouncement(); -} - - -void DiscoveryServer::doNetwork() { - const RealTime UNSOLICITED_BROADCAST_PERIOD = 60; - - // Check for client broadcast requests - - if (net->messageWaiting()) { - // Some client broadcast that it is looking for servers. - // Respond by sending out our announcement to everyone - // (avoids having to figure out if the message return address - // is correct). - NetAddress dummy; - net->receive(dummy); - sendAnnouncement(); - } else if (System::time() > lastBroadcast + UNSOLICITED_BROADCAST_PERIOD) { - sendAnnouncement(); - } - - // Handle incoming connections - - if (listener->clientWaiting()) { - // Respond to this client - ReliableConduitRef client = listener->waitForConnection(); - client->send(SERVER_BROADCAST_MESSAGE, *advertisement); - } -} - - -void DiscoveryServer::cleanup() { - sendShutDown(); -} - -////////////////////////////////////////////////////////////////////////////////// - -std::string IncompatibleServerDescription::toString() const { - return std::string("Incompatible server at ") + address.toString() + - format(", version %d.%d", protocolVersion[0], protocolVersion[1]); -} - -////////////////////////////////////////////////////////////////////////////////// - - -} - diff --git a/externals/g3dlite/G3D.lib/source/GCamera.cpp b/externals/g3dlite/G3D.lib/source/GCamera.cpp deleted file mode 100644 index e70188377e6..00000000000 --- a/externals/g3dlite/G3D.lib/source/GCamera.cpp +++ /dev/null @@ -1,399 +0,0 @@ -/** - @file GCamera.cpp - - @author Morgan McGuire, matrix@graphics3d.com - @author Jeff Marsceill, 08jcm@williams.edu - - @created 2005-07-20 - @edited 2007-07-24 -*/ -#include "G3D/GCamera.h" -#include "G3D/platform.h" -#include "G3D/Rect2D.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/Ray.h" -#include "G3D/Matrix4.h" - -namespace G3D { - -GCamera::GCamera() { - setNearPlaneZ(-0.1f); - setFarPlaneZ(-(float)inf()); - setFieldOfView((float)toRadians(55.0f), VERTICAL); -} - - -GCamera::~GCamera() { -} - -void GCamera::getCoordinateFrame(CoordinateFrame& c) const { - c = m_cframe; -} - -void GCamera::setCoordinateFrame(const CoordinateFrame& c) { - m_cframe = c; -} - -void GCamera::setFieldOfView(float angle, FOVDirection dir) { - debugAssert((angle < pi()) && (angle > 0)); - - m_fieldOfView = angle; - m_direction = dir; -} - -float GCamera::imagePlaneDepth() const{ - return -m_nearPlaneZ; -} - -float GCamera::viewportWidth(const Rect2D& viewport) const { - // Compute the side of a square at the near plane based on our field of view - float s = 2.0f * -m_nearPlaneZ * tan(m_fieldOfView * 0.5f); - - if (m_direction == VERTICAL) { - s *= viewport.width() / viewport.height(); - } - - return s; -} - -float GCamera::viewportHeight(const Rect2D& viewport) const { - // Compute the side of a square at the near plane based on our field of view - float s = 2.0f * -m_nearPlaneZ * tan(m_fieldOfView * 0.5f); - - if (m_direction == HORIZONTAL) { - s *= viewport.height() / viewport.width(); - } - - return s; -} - -Ray GCamera::worldRay(float x, float y, const Rect2D& viewport) const { - - int screenWidth = iFloor(viewport.width()); - int screenHeight = iFloor(viewport.height()); - - Ray out; - out.origin = m_cframe.translation; - - float cx = screenWidth / 2.0f; - float cy = screenHeight / 2.0f; - - out.direction = Vector3( (x - cx) * viewportWidth(viewport) / screenWidth, - -(y - cy) * viewportHeight(viewport) / screenHeight, - (m_nearPlaneZ) ); - - out.direction = m_cframe.vectorToWorldSpace(out.direction); - - // Normalize the direction (we didn't do it before) - out.direction = out.direction.direction(); - - return out; -} - -/** -This is the matrix that a RenderDevice (or OpenGL) uses as the projection matrix. -@sa RenderDevice::setProjectionAndCameraMatrix, RenderDevice::setProjectionMatrix, Matrix4::perspectiveProjection -*/ -void GCamera::getProjectUnitMatrix(const Rect2D& viewport, Matrix4& P) const{ - - float screenWidth = viewport.width(); - float screenHeight = viewport.height(); - - float r, l, t, b, n, f, x, y; - - if(m_direction == VERTICAL){ - y = -m_nearPlaneZ * tan(m_fieldOfView / 2); - x = y * (screenWidth / screenHeight); - } - else{ //m_direction == HORIZONTAL - x = -m_nearPlaneZ * tan(m_fieldOfView / 2); - y = x * (screenHeight / screenWidth); - } - - n = -m_nearPlaneZ; - f = -m_farPlaneZ; - r = x; - l = -x; - t = y; - b = -y; - - P = Matrix4::perspectiveProjection(l, r, b, t, n, f); -} - -Vector3 GCamera::projectUnit(const Vector3& point, const Rect2D& viewport) const { - Matrix4 M; - getProjectUnitMatrix(viewport, M); - - Vector4 cameraSpacePoint(coordinateFrame().pointToObjectSpace(point), 1.0f); - const Vector4& screenSpacePoint = M * cameraSpacePoint; - - return Vector3(screenSpacePoint.xyz() / screenSpacePoint.w); -} - -Vector3 GCamera::project(const Vector3& point, - const Rect2D& viewport) const { - - // Find the point in the homogeneous cube - const Vector3& cube = projectUnit(point, viewport); - - return convertFromUnitToNormal(cube, viewport); -} - -Vector3 GCamera::unprojectUnit(const Vector3& v, const Rect2D& viewport) const { - - const Vector3& projectedPoint = convertFromUnitToNormal(v, viewport); - - return unproject(projectedPoint, viewport); -} - - -Vector3 GCamera::unproject(const Vector3& v, const Rect2D& viewport) const { - - const float n = m_nearPlaneZ; - const float f = m_farPlaneZ; - - float z; - - if (-f >= inf()) { - // Infinite far plane - z = 1.0f / (((-1.0f / n) * v.z) + 1.0f / n); - } else { - z = 1.0f / ((((1.0f / f) - (1.0f / n)) * v.z) + 1.0f / n); - } - - const Ray& ray = worldRay(v.x, v.y, viewport); - - // Find out where the ray reaches the specified depth. - const Vector3& out = ray.origin + ray.direction * -z / (ray.direction.dot(m_cframe.lookVector())); - - return out; -} - -float GCamera::worldToScreenSpaceArea(float area, float z, const Rect2D& viewport) const { - if (z >= 0) { - return (float)inf(); - } - return area * (float)square(imagePlaneDepth() / z); -} - - -void GCamera::getClipPlanes( - const Rect2D& viewport, - Array& clip) const { - - Frustum fr; - frustum(viewport, fr); - clip.resize(fr.faceArray.size(), DONT_SHRINK_UNDERLYING_ARRAY); - for (int f = 0; f < clip.size(); ++f) { - clip[f] = fr.faceArray[f].plane; - } -} - -GCamera::Frustum GCamera::frustum(const Rect2D& viewport) const { - Frustum f; - frustum(viewport, f); - return f; -} - -void GCamera::frustum(const Rect2D& viewport, Frustum& fr) const { - - // The volume is the convex hull of the vertices definining the view - // frustum and the light source point at infinity. - - const float x = viewportWidth(viewport) / 2; - const float y = viewportHeight(viewport) / 2; - const float z = m_nearPlaneZ; - const float w = z / -m_farPlaneZ; - float fovx; - - fovx = m_fieldOfView; - if (m_direction == VERTICAL) { - fovx *= x / y; - } - - // Near face (ccw from UR) - fr.vertexPos.append( - Vector4( x, y, z, 1), - Vector4(-x, y, z, 1), - Vector4(-x, -y, z, 1), - Vector4( x, -y, z, 1)); - - // Far face (ccw from UR, from origin) - fr.vertexPos.append( - Vector4( x, y, z, w), - Vector4(-x, y, z, w), - Vector4(-x, -y, z, w), - Vector4( x, -y, z, w)); - - Frustum::Face face; - - // Near plane (wind backwards so normal faces into frustum) - // Recall that nearPlane, farPlane are positive numbers, so - // we need to negate them to produce actual z values. - face.plane = Plane(Vector3(0,0,-1), Vector3(0,0,m_nearPlaneZ)); - face.vertexIndex[0] = 3; - face.vertexIndex[1] = 2; - face.vertexIndex[2] = 1; - face.vertexIndex[3] = 0; - fr.faceArray.append(face); - - // Right plane - face.plane = Plane(Vector3(-cosf(fovx/2), 0, -sinf(fovx/2)), Vector3::zero()); - face.vertexIndex[0] = 0; - face.vertexIndex[1] = 4; - face.vertexIndex[2] = 7; - face.vertexIndex[3] = 3; - fr.faceArray.append(face); - - // Left plane - face.plane = Plane(Vector3(-fr.faceArray.last().plane.normal().x, 0, fr.faceArray.last().plane.normal().z), Vector3::zero()); - face.vertexIndex[0] = 5; - face.vertexIndex[1] = 1; - face.vertexIndex[2] = 2; - face.vertexIndex[3] = 6; - fr.faceArray.append(face); - - // Top plane - face.plane = Plane(Vector3(0, -cosf(m_fieldOfView/2.0f), -sinf(m_fieldOfView/2.0f)), Vector3::zero()); - face.vertexIndex[0] = 1; - face.vertexIndex[1] = 5; - face.vertexIndex[2] = 4; - face.vertexIndex[3] = 0; - fr.faceArray.append(face); - - // Bottom plane - face.plane = Plane(Vector3(0, -fr.faceArray.last().plane.normal().y, fr.faceArray.last().plane.normal().z), Vector3::zero()); - face.vertexIndex[0] = 2; - face.vertexIndex[1] = 3; - face.vertexIndex[2] = 7; - face.vertexIndex[3] = 6; - fr.faceArray.append(face); - - // Far plane - if (-m_farPlaneZ < inf()) { - face.plane = Plane(Vector3(0, 0, 1), Vector3(0, 0, m_farPlaneZ)); - face.vertexIndex[0] = 4; - face.vertexIndex[1] = 5; - face.vertexIndex[2] = 6; - face.vertexIndex[3] = 7; - fr.faceArray.append(face); - } - - // Transform vertices to world space - for (int v = 0; v < fr.vertexPos.size(); ++v) { - fr.vertexPos[v] = m_cframe.toWorldSpace(fr.vertexPos[v]); - } - - // Transform planes to world space - for (int p = 0; p < fr.faceArray.size(); ++p) { - // Since there is no scale factor, we don't have to - // worry about the inverse transpose of the normal. - Vector3 normal; - float d; - - fr.faceArray[p].plane.getEquation(normal, d); - - Vector3 newNormal = m_cframe.rotation * normal; - - if (isFinite(d)) { - d = (newNormal * -d + m_cframe.translation).dot(newNormal); - fr.faceArray[p].plane = Plane(newNormal, newNormal * d); - } else { - // When d is infinite, we can't multiply 0's by it without - // generating NaNs. - fr.faceArray[p].plane = Plane::fromEquation(newNormal.x, newNormal.y, newNormal.z, d); - } - } -} - -void GCamera::getNearViewportCorners( - const Rect2D& viewport, - Vector3& outUR, - Vector3& outUL, - Vector3& outLL, - Vector3& outLR) const { - - // Must be kept in sync with getFrustum() - const float w = viewportWidth(viewport) / 2.0f; - const float h = viewportHeight(viewport) / 2.0f; - const float z = nearPlaneZ(); - - // Compute the points - outUR = Vector3( w, h, z); - outUL = Vector3(-w, h, z); - outLL = Vector3(-w, -h, z); - outLR = Vector3( w, -h, z); - - // Take to world space - outUR = m_cframe.pointToWorldSpace(outUR); - outUL = m_cframe.pointToWorldSpace(outUL); - outLR = m_cframe.pointToWorldSpace(outLR); - outLL = m_cframe.pointToWorldSpace(outLL); -} - -void GCamera::getFarViewportCorners( - const Rect2D& viewport, - Vector3& outUR, - Vector3& outUL, - Vector3& outLL, - Vector3& outLR) const { - - // Must be kept in sync with getFrustum() - const float w = viewportWidth(viewport) * m_farPlaneZ / m_nearPlaneZ; - const float h = viewportHeight(viewport) * m_farPlaneZ / m_nearPlaneZ; - const float z = m_farPlaneZ; - - // Compute the points - outUR = Vector3( w, h, z); - outUL = Vector3(-w, h, z); - outLL = Vector3(-w, -h, z); - outLR = Vector3( w, -h, z); - - // Take to world space - outUR = m_cframe.pointToWorldSpace(outUR); - outUL = m_cframe.pointToWorldSpace(outUL); - outLR = m_cframe.pointToWorldSpace(outLR); - outLL = m_cframe.pointToWorldSpace(outLL); -} - - - -void GCamera::setPosition(const Vector3& t) { - m_cframe.translation = t; -} - - -void GCamera::lookAt(const Vector3& position, const Vector3& up) { - m_cframe.lookAt(position, up); -} - - -void GCamera::serialize(BinaryOutput& bo) const { - bo.writeFloat32(m_fieldOfView); - bo.writeFloat32(imagePlaneDepth()); - debugAssert(nearPlaneZ() < 0.0f); - bo.writeFloat32(nearPlaneZ()); - debugAssert(farPlaneZ() < 0.0f); - bo.writeFloat32(farPlaneZ()); - m_cframe.serialize(bo); - bo.writeInt8(m_direction); -} - - -void GCamera::deserialize(BinaryInput& bi) { - m_fieldOfView = bi.readFloat32(); - m_nearPlaneZ = bi.readFloat32(); - debugAssert(m_nearPlaneZ < 0.0f); - m_farPlaneZ = bi.readFloat32(); - debugAssert(m_farPlaneZ < 0.0f); - m_cframe.deserialize(bi); - m_direction = (FOVDirection)bi.readInt8(); -} - - -Vector3 GCamera::convertFromUnitToNormal(const Vector3& in, const Rect2D& viewport) const{ - return (in + Vector3(1,1,1)) * 0.5 * Vector3(viewport.width(), -viewport.height(), 1) + - Vector3(viewport.x0(), viewport.y1(), 0); -} -} // namespace diff --git a/externals/g3dlite/G3D.lib/source/GImage.cpp b/externals/g3dlite/G3D.lib/source/GImage.cpp deleted file mode 100644 index c7abf982553..00000000000 --- a/externals/g3dlite/G3D.lib/source/GImage.cpp +++ /dev/null @@ -1,1065 +0,0 @@ -/** - @file GImage.cpp - @author Morgan McGuire, morgan@graphics3d.com - Copyright 2002-2007, Morgan McGuire - - @created 2002-05-27 - @edited 2006-10-10 - */ -#include "G3D/platform.h" -#include "G3D/GImage.h" -#include "G3D/debug.h" -#include "G3D/stringutils.h" -#include "G3D/TextInput.h" -#include "G3D/TextOutput.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/Log.h" -#include -#include -#include -#include - -////////////////////////////////////////////////////////////////////////////////////////////// - -namespace G3D { - -void GImage::RGBtoRGBA( - const uint8* in, - uint8* out, - int numPixels) { - - for (int i = 0; i < numPixels; ++i) { - int i3 = i * 3; - int i4 = i3 + i; - - out[i4 + 0] = in[i3 + 0]; - out[i4 + 1] = in[i3 + 1]; - out[i4 + 2] = in[i3 + 2]; - out[i4 + 3] = 255; - } -} - - -void GImage::RGBAtoRGB( - const uint8* in, - uint8* out, - int numPixels) { - - for (int i = 0; i < numPixels; ++i) { - int i3 = i * 3; - int i4 = i3 + i; - - out[i3 + 0] = in[i4 + 0]; - out[i3 + 1] = in[i4 + 1]; - out[i3 + 2] = in[i4 + 2]; - } -} - - -void GImage::RGBtoBGRA( - const uint8* in, - uint8* out, - int numPixels) { - - for (int i = 0; i < numPixels; ++i) { - int i3 = i * 3; - int i4 = i3 + i; - - out[i4 + 2] = in[i3 + 0]; - out[i4 + 1] = in[i3 + 1]; - out[i4 + 0] = in[i3 + 2]; - out[i4 + 3] = 255; - } -} - - - -void GImage::RGBtoBGR( - const uint8* in, - uint8* out, - int numPixels) { - - for (int i = 0; i < numPixels; ++i) { - int i3 = i * 3; - - int r = in[i3 + 0]; - int g = in[i3 + 1]; - int b = in[i3 + 2]; - - out[i3 + 2] = r; - out[i3 + 1] = g; - out[i3 + 0] = b; - } -} - - -void GImage::RGBxRGBtoRGBA( - const uint8* colorRGB, - const uint8* alphaRGB, - uint8* out, - int numPixels) { - - for (int i = numPixels - 1; i >= 0; --i) { - int i3 = i * 3; - int i4 = i3 + i; - - out[i4 + 0] = colorRGB[i3 + 0]; - out[i4 + 1] = colorRGB[i3 + 1]; - out[i4 + 2] = colorRGB[i3 + 2]; - out[i4 + 3] = alphaRGB[i3 + 0]; - } -} - - -void GImage::RGBtoARGB( - const uint8* in, - uint8* out, - int numPixels) { - - for (int i = 0; i < numPixels; ++i) { - int i3 = i * 3; - int i4 = i3 + i; - - out[i4 + 0] = 255; - out[i4 + 1] = in[i3 + 0]; - out[i4 + 2] = in[i3 + 1]; - out[i4 + 3] = in[i3 + 2]; - } -} - - -void GImage::flipRGBVertical( - const uint8* in, - uint8* out, - int width, - int height) { - - - // Allocate a temp row so the operation - // is still safe if in == out - uint8* temp = (uint8*)System::malloc(width * 3); - alwaysAssertM(temp != NULL, "Out of memory"); - - int oneRow = width * 3; - int N = height / 2; - - // if height is an odd value, don't swap odd middle row - for (int i = 0; i < N; ++i) { - int topOff = i * oneRow; - int botOff = (height - i - 1) * oneRow; - System::memcpy(temp, in + topOff, oneRow); - System::memcpy(out + topOff, in + botOff, oneRow); - System::memcpy(out + botOff, temp, oneRow); - } - - System::free(temp); -} - - -void GImage::flipRGBAVertical( - const uint8* in, - uint8* out, - int width, - int height) { - - - // Allocate a temp row so the operation - // is still safe if in == out - uint8* temp = (uint8*)System::malloc(width * 4); - alwaysAssertM(temp != NULL, "Out of memory"); - - int oneRow = width * 4; - - // if height is an odd value, don't swap odd middle row - for (int i = 0; i < height / 2; ++i) { - int topOff = i * oneRow; - int botOff = (height - i - 1) * oneRow; - System::memcpy(temp, in + topOff, oneRow); - System::memcpy(out + topOff, in + botOff, oneRow); - System::memcpy(out + botOff, temp, oneRow); - } - - System::free(temp); -} - -//////////////////////////////////////////////////////////////////////////////////////// - -void GImage::decode( - BinaryInput& input, - Format format) { - - switch (format) { - case PPM_ASCII: - decodePPMASCII(input); - break; - - case PPM: - decodePPM(input); - break; - - case PNG: - decodePNG(input); - break; - - case JPEG: - decodeJPEG(input); - break; - - case TGA: - decodeTGA(input); - break; - - case BMP: - decodeBMP(input); - break; - - case ICO: - decodeICO(input); - break; - - case PCX: - decodePCX(input); - break; - - default: - debugAssert(false); - } - - debugAssert(width >= 0); - debugAssert(height >= 0); - debugAssert(channels == 1 || channels == 3 || channels == 4); - debugAssert(_byte != NULL); -} - - -void GImage::decodePCX( - BinaryInput& input) { - - uint8 manufacturer = input.readUInt8(); - uint8 version = input.readUInt8(); - uint8 encoding = input.readUInt8(); - uint8 bitsPerPixel = input.readUInt8(); - - uint16 xmin = input.readUInt16(); - uint16 ymin = input.readUInt16(); - uint16 xmax = input.readUInt16(); - uint16 ymax = input.readUInt16(); - - uint16 horizDPI = input.readUInt16(); - uint16 vertDPI = input.readUInt16(); - - Color3uint8 colorMap[16]; - input.readBytes(colorMap, 48); - - input.skip(1); - - uint8 planes = input.readUInt8(); - uint16 bytesPerLine = input.readUInt16(); - uint16 paletteType = input.readUInt16(); - input.skip(4 + 54); - - (void)bytesPerLine; - - width = xmax - xmin + 1; - height = ymax - ymin + 1; - channels = 3; - - if ((manufacturer != 0x0A) || (encoding != 0x01)) { - throw GImage::Error("PCX file is corrupted", input.getFilename()); - } - - (void)version; - (void)vertDPI; - (void)horizDPI; - - if ((bitsPerPixel != 8) || ((planes != 1) && (planes != 3))) { - throw GImage::Error("Only 8-bit paletted and 24-bit PCX files supported.", input.getFilename()); - } - - // Prepare the pointer object for the pixel data - _byte = (uint8*)System::malloc(width * height * 3); - - if ((paletteType == 1) && (planes == 3)) { - - Color3uint8* pixel = pixel3(); - - // Iterate over each scan line - for (int row = 0; row < height; ++row) { - // Read each scan line once per plane - for (int plane = 0; plane < planes; ++plane) { - int p = row * width; - int p1 = p + width; - while (p < p1) { - uint8 value = input.readUInt8(); - int length = 1; - - if (value >= 192) { - // This is the length, not the value. Mask off - // the two high bits and read the true index. - length = value & 0x3F; - value = input.readUInt8(); - } - - // Set the whole run - for (int i = length - 1; i >= 0; --i, ++p) { - debugAssert(p < width * height); - pixel[p][plane] = value; - } - } - } - } - - } else if (planes == 1) { - - Color3uint8 palette[256]; - - int imageBeginning = input.getPosition(); - int paletteBeginning = input.getLength() - 769; - - input.setPosition(paletteBeginning); - - uint8 dummy = input.readUInt8(); - - if (dummy != 12) { - Log::common()->println("\n*********************"); - Log::common()->printf("Warning: Corrupted PCX file (palette marker byte was missing) \"%s\"\nLoading anyway\n\n", input.getFilename().c_str()); - } - - input.readBytes(palette, sizeof(palette)); - input.setPosition(imageBeginning); - - Color3uint8* pixel = pixel3(); - - // The palette indices are run length encoded. - int p = 0; - while (p < width * height) { - uint8 index = input.readUInt8(); - uint8 length = 1; - - if (index >= 192) { - // This is the length, not the index. Mask off - // the two high bits and read the true index. - length = index & 0x3F; - index = input.readUInt8(); - } - - Color3uint8 color = palette[index]; - - // Set the whole run - for (int i = length - 1; i >= 0; --i, ++p) { - if (p > width * height) { - break; - } - pixel[p] = color; - } - - } - - } else { - throw GImage::Error("Unsupported PCX file type.", input.getFilename()); - } -} - - -GImage::Format GImage::resolveFormat(const std::string& filename) { - BinaryInput b(filename, G3D_LITTLE_ENDIAN); - if (b.size() <= 0) { - throw Error("File not found.", filename); - } - - return resolveFormat(filename, b.getCArray(), b.size(), AUTODETECT); -} - - -GImage::Format GImage::resolveFormat( - const std::string& filename, - const uint8* data, - int dataLen, - Format maybeFormat) { - - // Return the provided format if it is specified. - if (maybeFormat != AUTODETECT) { - return maybeFormat; - } - - std::string extension; - - // Try to detect from the filename's extension - if (filename.size() >= 5) { - int n = iMax(filename.size() - 1, 5); - // Search backwards for the "." - for (int i = 1; i <= n; ++i) { - if (filename[filename.size() - i] == '.') { - // Upper case - extension = toUpper(filename.substr(filename.size() - i + 1)); - break; - } - } - } - - if (extension == "PPM") { - // There are two PPM formats; we handle them differently - if (dataLen > 3) { - if (!memcmp(data, "P6", 2)) { - return PPM; - } else { - return PPM_ASCII; - } - } - } - - Format tmp = stringToFormat(extension); - if ((tmp != AUTODETECT) && (tmp != UNKNOWN)) { - return tmp; - } - - // Try and autodetect from the file itself by looking at the first - // character. - - // We can't look at the character if it is null. - debugAssert(data != NULL); - - if ((dataLen > 3) && (!memcmp(data, "P3", 2) || !memcmp(data, "P2", 2) || !memcmp(data, "P1", 2))) { - return PPM_ASCII; - } - - if ((dataLen > 3) && !memcmp(data, "P6", 2)) { - return PPM; - } - - if (dataLen > 8) { - if (!png_sig_cmp((png_bytep)data, 0, 8)) - return PNG; - } - - if ((dataLen > 0) && (data[0] == 'B')) { - return BMP; - } - - if (dataLen > 10) { - if ((dataLen > 11) && (data[0] == 0xFF) && - (memcmp(&data[6], "JFIF", 4) == 0)) { - return JPEG; - } - } - - if (dataLen > 40) { - if (memcmp(&data[dataLen - 18], "TRUEVISION-XFILE", 16) == 0) { - return TGA; - } - } - - if ((dataLen > 4) && (data[0] == 0) && (data[1] == 0) && (data[2] == 0) && (data[3] == 1)) { - return ICO; - } - - if ((dataLen > 0) && (data[0] == 10)) { - return PCX; - } - - return UNKNOWN; -} - - -GImage::GImage( - const std::string& filename, - Format format) : - _byte(NULL), - width(0), - height(0), - channels(0){ - - load(filename, format); -} - - -void GImage::load( - const std::string& filename, - Format format) { - - clear(); - - try { - BinaryInput b(filename, G3D_LITTLE_ENDIAN); - if (b.size() <= 0) { - throw Error("File not found.", filename); - } - - alwaysAssertM(this != NULL, "Corrupt GImage"); - decode(b, resolveFormat(filename, b.getCArray(), b.size(), format)); - } catch (const std::string& error) { - throw Error(error, filename); - } -} - - -GImage::GImage( - const uint8* data, - int length, - Format format) { - - BinaryInput b(data, length, G3D_LITTLE_ENDIAN); - // It is safe to cast away the const because we - // know we don't corrupt the data. - - decode(b, resolveFormat("", data, length, format)); -} - - -GImage::GImage( - int width, - int height, - int channels) { - - _byte = NULL; - resize(width, height, channels); -} - - -void GImage::resize( - int width, - int height, - int channels) { - debugAssert(width >= 0); - debugAssert(height >= 0); - debugAssert(channels >= 1); - - clear(); - - this->width = width; - this->height = height; - this->channels = channels; - size_t sz = width * height * channels; - - _byte = (uint8*)System::calloc(sz, sizeof(uint8)); - debugAssert(isValidHeapPointer(_byte)); -} - - -void GImage::_copy( - const GImage& other) { - - clear(); - - width = other.width; - height = other.height; - channels = other.channels; - int s = width * height * channels * sizeof(uint8); - _byte = (uint8*)System::malloc(s); - debugAssert(isValidHeapPointer(_byte)); - memcpy(_byte, other._byte, s); -} - - -GImage::GImage( - const GImage& other) : _byte(NULL) { - - _copy(other); -} - - -GImage::~GImage() { - clear(); -} - - -void GImage::clear() { - width = 0; - height = 0; - System::free(_byte); - _byte = NULL; -} - - -GImage& GImage::operator=(const GImage& other) { - _copy(other); - return *this; -} - - -bool GImage::copySubImage( - GImage & dest, const GImage & src, - int srcX, int srcY, int srcWidth, int srcHeight) { - if ((src.width < srcX + srcWidth) || - (src.height < srcY + srcHeight) || - (srcY < 0) || - (srcX < 0)) { - - return false; - } - - dest.resize(srcWidth, srcHeight, src.channels); - - bool ret; - ret = pasteSubImage(dest, src, 0, 0, srcX, srcY, srcWidth, srcHeight); - debugAssert(ret); - - return true; -} - - -bool GImage::pasteSubImage( - GImage & dest, const GImage & src, - int destX, int destY, - int srcX, int srcY, int srcWidth, int srcHeight) { - if ((src.width < srcX + srcWidth) || - (src.height < srcY + srcHeight) || - (dest.width < destX + srcWidth) || - (dest.height < destY + srcHeight) || - (srcY < 0) || - (srcX < 0) || - (destY < 0) || - (destX < 0) || - (src.channels != dest.channels)) { - - return false; - } - - for (int i = 0; i < srcHeight; i++) { - const uint8* srcRow = src.byte() + - ((i + srcY) * src.width + srcX) * src.channels; - uint8* destRow = dest.byte() + - ((i + destY) * dest.width + destX) * dest.channels; - memcpy(destRow, srcRow, srcWidth * src.channels); - } - - return true; -} - - -bool GImage::supportedFormat( - const std::string& format) { - - return (stringToFormat(format) != UNKNOWN); -} - - -GImage::Format GImage::stringToFormat( - const std::string& format) { - - std::string extension = toUpper(format); - - if ((extension == "JPG") || (extension == "JPEG")) { - return JPEG; - } else if (extension == "TGA") { - return TGA; - } else if (extension == "BMP") { - return BMP; - } else if (extension == "PCX") { - return PCX; - } else if (extension == "ICO") { - return ICO; - } else if (extension == "PNG") { - return PNG; - } else if (extension == "PPM") { - return PPM; - } else { - return UNKNOWN; - } -} - - -void GImage::save( - const std::string& filename, - Format format) const { - - BinaryOutput b(filename, G3D_LITTLE_ENDIAN); - encode(resolveFormat(filename, NULL, 0, format), b); - b.commit(false); -} - - -void GImage::encode( - Format format, - uint8*& outData, - int& outLength) const { - - BinaryOutput out; - - encode(format, out); - - outData = (uint8*)System::malloc(out.size()); - debugAssert(outData); - outLength = out.size(); - - out.commit(outData); -} - - -void GImage::encode( - Format format, - BinaryOutput& out) const { - - switch (format) { - case PPM_ASCII: - encodePPMASCII(out); - break; - - case PPM: - encodePPM(out); - break; - - case PNG: - encodePNG(out); - break; - - case JPEG: - encodeJPEG(out); - break; - - case BMP: - encodeBMP(out); - break; - - case TGA: - encodeTGA(out); - break; - - default: - debugAssert(false); - } -} - -void GImage::insertRedAsAlpha(const GImage& alpha, GImage& output) const { - debugAssert(alpha.width == width); - debugAssert(alpha.height == height); - - // make sure output GImage is valid - if (output.width != width || output.height != height || output.channels != 4) { - output.resize(width, height, 4); - } - - for (int i = 0; i < width * height; ++i) { - output.byte()[i * 4 + 0] = byte()[i * channels + 0]; - output.byte()[i * 4 + 1] = byte()[i * channels + 1]; - output.byte()[i * 4 + 2] = byte()[i * channels + 2]; - output.byte()[i * 4 + 3] = alpha.byte()[i * alpha.channels]; - } -} - -GImage GImage::insertRedAsAlpha(const GImage& alpha) const { - debugAssert(alpha.width == width); - debugAssert(alpha.height == height); - - GImage out(width, height, 4); - - insertRedAsAlpha(alpha, out); - - return out; -} - - -void GImage::stripAlpha(GImage& output) const { - - if (output.width != width || output.height != height || output.channels != 3) - { - output.resize(width, height, 3); - } - - for (int i = 0; i < width * height; ++i) { - output.byte()[i * 3 + 0] = byte()[i * channels + 0]; - output.byte()[i * 3 + 1] = byte()[i * channels + 1]; - output.byte()[i * 3 + 2] = byte()[i * channels + 2]; - } -} - -GImage GImage::stripAlpha() const { - GImage out(width, height, 3); - - stripAlpha(out); - - return out; -} - - -int GImage::sizeInMemory() const { - return sizeof(GImage) + width * height * channels; -} - - -void GImage::computeNormalMap( - const GImage& bump, - GImage& normal, - float whiteHeightInPixels, - bool lowPassBump, - bool scaleHeightByNz) { - computeNormalMap(bump.width, bump.height, bump.channels, bump.byte(), normal, whiteHeightInPixels, lowPassBump, scaleHeightByNz); -} - -void GImage::computeNormalMap( - int width, - int height, - int channels, - const uint8* src, - GImage& normal, - float whiteHeightInPixels, - bool lowPassBump, - bool scaleHeightByNz) { - - if (whiteHeightInPixels == -1.0f) { - // Default setting scales so that a gradient ramp - // over the whole image becomes a 45-degree angle - - // Account for potentially non-square aspect ratios - whiteHeightInPixels = max(width, height); - } - - debugAssert(whiteHeightInPixels >= 0); - - const int w = width; - const int h = height; - const int stride = channels; - - normal.resize(w, h, 4); - - const uint8* const B = src; - Color4uint8* const N = normal.pixel4(); - - for (int y = 0; y < h; ++y) { - for (int x = 0; x < w; ++x) { - // Index into normal map pixel - int i = x + y * w; - - // Index into bump map *byte* - int j = stride * i; - - Vector3 delta; - - // Get a value from B (with wrapping lookup) relative to (x, y) - // and divide by 255 - #define height(DX, DY) ((int)B[(((DX + x + w) % w) + \ - ((DY + y + h) % h) * w) * stride]) - - - // Sobel filter to compute the normal. - // - // Y Filter (X filter is the transpose) - // [ -1 -2 -1 ] - // [ 0 0 0 ] - // [ 1 2 1 ] - - // Write the Y value directly into the x-component so we don't have - // to explicitly compute a cross product at the end. - delta.y = -(height(-1, -1) * 1 + height( 0, -1) * 2 + height( 1, -1) * 1 + - height(-1, 1) * -1 + height( 0, 1) * -2 + height( 1, 1) * -1); - - delta.x = -(height(-1, -1) * -1 + height( 1, -1) * 1 + - height(-1, 0) * -2 + height( 1, 0) * 2 + - height(-1, 1) * -1 + height( 1, 1) * 1); - - // The scale of each filter row is 4, the filter width is two pixels, - // and the "normal" range is 0-255. - delta.z = 4 * 2 * (whiteHeightInPixels / 255.0f); - - // Delta is now scaled in pixels; normalize - delta = delta.direction(); - - // Copy over the bump value into the alpha channel. - float H = B[j] / 255.0; - - if (lowPassBump) { - H = (height(-1, -1) + height( 0, -1) + height(1, -1) + - height(-1, 0) + height( 0, 0) + height(1, 0) + - height(-1, 1) + height( 0, 1) + height(1, 1)) / (255.0f * 9.0f); - } - #undef height - - if (scaleHeightByNz) { - // delta.z can't possibly be negative, so we avoid actually - // computing the absolute value. - H *= delta.z; - } - - N[i].a = iRound(H * 255.0); - - // Pack into byte range - delta = delta * 127.5 + Vector3(127.5, 127.5, 127.5); - N[i].r = iClamp(iRound(delta.x), 0, 255); - N[i].g = iClamp(iRound(delta.y), 0, 255); - N[i].b = iClamp(iRound(delta.z), 0, 255); - } - } -} - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void GImage::convertToL8() { - switch(channels) { - case 1: - return; - - case 3: - { - // Average - Color3uint8* src = (Color3uint8*)_byte; - _byte = NULL; - resize(width, height, 1); - for (int i = width * height - 1; i >= 0; --i) { - const Color3uint8 s = src[i]; - uint8& d = _byte[i]; - d = ((int)s.r + (int)s.g + (int)s.b) / 3; - } - System::free(src); - } - break; - - case 4: - { - // Average - Color4uint8* src = (Color4uint8*)_byte; - _byte = NULL; - resize(width, height, 1); - for (int i = width * height - 1; i >= 0; --i) { - const Color4uint8 s = src[i]; - uint8& d = _byte[i]; - d = ((int)s.r + (int)s.g + (int)s.b) / 3; - } - System::free(src); - } - return; - - default: - alwaysAssertM(false, "Bad number of channels in input image"); - } -} - - -void GImage::convertToRGBA() { - switch(channels) { - case 1: - { - // Spread - uint8* old = _byte; - _byte = NULL; - resize(width, height, 4); - for (int i = width * height - 1; i >= 0; --i) { - const uint8 s = old[i]; - Color4uint8& d = ((Color4uint8*)_byte)[i]; - d.r = d.g = d.b = s; - d.a = 255; - } - System::free(_byte); - } - break; - - case 3: - { - // Add alpha - Color3uint8* old = (Color3uint8*)_byte; - _byte = NULL; - resize(width, height, 4); - for (int i = width * height - 1; i >= 0; --i) { - const Color3uint8 s = old[i]; - Color4uint8& d = ((Color4uint8*)_byte)[i]; - d.r = s.r; - d.g = s.g; - d.b = s.b; - d.a = 255; - } - System::free(old); - } - break; - - case 4: - // Already RGBA - return; - - default: - alwaysAssertM(false, "Bad number of channels in input image"); - } -} - - -void GImage::convertToRGB() { - switch(channels) { - case 1: - { - // Spread - uint8* old = _byte; - _byte = NULL; - resize(width, height, 3); - for (int i = width * height - 1; i >= 0; --i) { - const uint8 s = old[i]; - Color3uint8& d = ((Color3uint8*)_byte)[i]; - d.r = d.g = d.b = s; - } - System::free(old); - } - break; - - case 3: - return; - - case 4: - // Strip alpha - { - Color4uint8* old = (Color4uint8*)_byte; - _byte = NULL; - resize(width, height, 3); - for (int i = width * height - 1; i >= 0; --i) { - const Color4uint8 s = old[i]; - Color3uint8& d = ((Color3uint8*)_byte)[i]; - d.r = s.r; - d.g = s.g; - d.b = s.b; - } - System::free(old); - } - break; - - default: - alwaysAssertM(false, "Bad number of channels in input image"); - } -} - - -void GImage::R8G8B8_to_Y8U8V8(int width, int height, const uint8* _in, uint8* _out) { - const Color3uint8* in = reinterpret_cast(_in); - Color3uint8* out = reinterpret_cast(_out); - - Color3uint8 p; - for (int i = width * height - 1; i >= 0; --i) { - p.r = iClamp(iRound(in->r * 0.229 + in->g * 0.587 + in->b * 0.114), 0, 255); - p.g = iClamp(iRound(in->r * -0.147 + in->g * -0.289 + in->b * 0.436) + 127, 0, 255); - p.b = iClamp(iRound(in->r * 0.615 + in->g * -0.515 + in->b * -0.100) + 127, 0, 255); - *out = p; - ++in; - ++out; - } -} - - - -void GImage::Y8U8V8_to_R8G8B8(int width, int height, const uint8* _in, uint8* _out) { - const Color3uint8* in = reinterpret_cast(_in); - Color3uint8* out = reinterpret_cast(_out); - - Color3uint8 p; - for (int i = width * height - 1; i >= 0; --i) { - p.r = iClamp(iRound(in->r * 1.0753 + (in->b - 127) * 1.2256), 0, 255); - p.g = iClamp(iRound(in->r * 1.0753 + (in->g - 127) * -0.3946 + (in->b - 127) * -0.4947), 0, 255); - p.b = iClamp(iRound(in->r * 1.0753 + (in->g - 127) * 2.0320 + (in->b - 127) * 0.0853), 0, 255); - *out = p; - ++in; - ++out; - } -} - - -void GImage::makeCheckerboard(GImage& im, int checkerSize, const Color4uint8& A, const Color4uint8& B) { - for (int y = 0; y < im.height; ++y) { - for (int x = 0; x < im.width; ++x) { - bool checker = isOdd((x / checkerSize) + (y / checkerSize)); - const Color4uint8& color = checker ? A : B; - for (int c = 0; c < im.channels; ++c) { - uint8* v = im.byte() + (x + y * im.width) * im.channels + c; - *v = color[c]; - } - } - } -} - -} - diff --git a/externals/g3dlite/G3D.lib/source/GImage_bayer.cpp b/externals/g3dlite/G3D.lib/source/GImage_bayer.cpp deleted file mode 100644 index 16499af15f6..00000000000 --- a/externals/g3dlite/G3D.lib/source/GImage_bayer.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/** - @file GImage_bayer.cpp - @author Morgan McGuire, morgan@graphics3d.com - @created 2002-05-27 - @edited 2006-05-10 - */ -#include "G3D/platform.h" -#include "G3D/GImage.h" - -namespace G3D { - -void GImage::BAYER_G8B8_R8G8_to_Quarter_R8G8B8(int width, int height, const uint8* in, uint8* out) { - debugAssert(in != out); - - int halfHeight = height / 2; - int halfWidth = width / 2; - - int dst_off = 0; - for (int y = 0; y < halfHeight; ++y) { - for (int x = 0; x < halfWidth; ++x) { - // GBRG - int src_off = x*2 + y*2*width; - out[dst_off] = in[src_off+width]; // red - out[dst_off+1] = ((int)in[src_off] + (int)in[src_off+width+1])/2; // green - out[dst_off+2] = in[src_off+1]; // blue - - dst_off = dst_off + 3; - } - } -} - - -void GImage::Quarter_R8G8B8_to_BAYER_G8B8_R8G8(int inWidth, int inHeight, const uint8* in, uint8* out) { - // Undo quarter-size Bayer as best we can. This code isn't very efficient, but it - // also isn't used very frequently. - - debugAssert(out != in); - - int outWidth = 2 * inWidth; - int outHeight = 2 * inHeight; - - for (int y = 0; y < outHeight; ++y) { - for (int x = 0; x < outWidth; ++x) { - const Color3uint8* inp = ((const Color3uint8*)in) + ((x/2) + (y/2)* inWidth); - uint8* outp = out + x + y * outWidth; - - if (isEven(y)) { - // GB row - if (isEven(x)) { - // Green - *outp = inp->g; - } else { - // Blue - *outp = inp->b; - } - } else { - // RG row - if (isEven(x)) { - // Red - *outp = inp->r; - } else { - // Green - *outp = inp->g; - } - } - } - } -} - - -/** Applies a 5x5 filter to monochrome image I (wrapping at the boundaries) */ -static uint8 applyFilter( - const uint8* I, - int x, - int y, - int w, - int h, - const float filter[5][5]) { - - debugAssert(isEven(w)); - debugAssert(isEven(h)); - - float sum = 0.0f; - float denom = 0.0f; - - for (int dy = 0; dy < 5; ++dy) { - int offset = ((y + dy + h - 2) % h) * w; - - for (int dx = 0; dx < 5; ++dx) { - float f = filter[dy][dx]; - sum += f * I[((x + dx + w - 2) % w) + offset]; - denom += f; - } - } - - return (uint8)iClamp(iRound(sum / denom), 0, 255); -} - -//////////////////////////////////////////////////////////////////////////////////////////////// -// -// Bayer conversions -// - -// There are two kinds of rows (GR and BG). -// In each row, there are two kinds of pixels (G/R, B/G). -// We express the four kinds of INPUT pixels as: -// GRG, GRG, BGB, BGG -// -// There are three kinds of OUTPUT pixels: R, G, B. -// Thus there are nominally 12 different I/O combinations, -// but several are impulses because needed output at that -// location *is* the input (e.g., G_GRG and G_BGG). -// -// The following 5x5 row-major filters are named as output_input. - -// Green -static const float G_GRR[5][5] = -{{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}, -{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f}, -{ -1.0f, 2.0f, 4.0f, 2.0f, -1.0f}, -{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f}, -{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}}; - -static const float G_BGB[5][5] = -{{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}, -{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f}, -{ -1.0f, 2.0f, 4.0f, 2.0f, -1.0f}, -{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f}, -{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}}; - -// Red -//(the caption in the paper is wrong for this case: -// "R row B column really means R row G column" -static const float R_GRG[5][5] = -{{ 0.0f, 0.0f, 0.5f, 0.0f, 0.0f}, -{ 0.0f, -1.0f, 0.0f, -1.0f, 0.0f}, -{ -1.0f, 4.0f, 5.0f, 4.0f, -1.0f}, -{ 0.0f, -1.0f, 0.0f, -1.0f, 0.0f}, -{ 0.0f, 0.0f, 0.5f, 0.0f, 0.0f}}; - -static const float R_BGG[5][5] = -{{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}, -{ 0.0f, -1.0f, 4.0f, -1.0f, 0.0f}, -{ 0.5f, 0.0f, 5.0f, 0.0f, 0.5f}, -{ 0.0f, -1.0f, 4.0f, -1.0f, 0.0f}, -{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}}; - -static const float R_BGB[5][5] = -{{ 0.0f, 0.0f, -3.0f/2.0f, 0.0f, 0.0f}, -{ 0.0f, 2.0f, 0.0f, 2.0f, 0.0f}, -{-3.0f/2.0f, 0.0f, 6.0f, 0.0f, -3.0f/2.0f}, -{ 0.0f, 2.0f, 0.0f, 2.0f, 0.0f}, -{ 0.0f, 0.0f, -3.0f/2.0f, 0.0f, 0.0f}}; - - -// Blue -//(the caption in the paper is wrong for this case: -// "B row R column really means B row G column") -#define B_BGG R_GRG -#define B_GRG R_BGG -#define B_GRR R_BGB - - -void GImage::BAYER_R8G8_G8B8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) { - debugAssert(in != _out); - - Color3uint8* out = (Color3uint8*)_out; - - for (int y = 0; y < h; ++y) { - - // Row beginning in the input array. - int offset = y * w; - - // RG row - for (int x = 0; x < w; ++x, ++out) { - // R pixel - { - out->r = in[x + offset]; - out->g = applyFilter(in, x, y, w, h, G_GRR); - out->b = applyFilter(in, x, y, w, h, B_GRR); - } - ++x; ++out; - - // G pixel - { - out->r = applyFilter(in, x, y, w, h, R_GRG); - out->g = in[x + offset]; - out->b = applyFilter(in, x, y, w, h, B_GRG); - } - } - - ++y; - offset += w; - - // GB row - for (int x = 0; x < w; ++x, ++out) { - // G pixel - { - out->r = applyFilter(in, x, y, w, h, R_BGG); - out->g = in[x + offset]; - out->b = applyFilter(in, x, y, w, h, B_BGG); - } - ++x; ++out; - - // B pixel - { - out->r = applyFilter(in, x, y, w, h, R_BGB); - out->g = applyFilter(in, x, y, w, h, G_BGB); - out->b = in[x + offset]; - } - } - } -} - -static void swapRedAndBlue(int N, Color3uint8* out) { - for (int i = N - 1; i >= 0; --i) { - uint8 tmp = out[i].r; - out[i].r = out[i].b; - out[i].b = tmp; - } -} - -void GImage::BAYER_G8R8_B8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) { - // Run the equivalent function for red - BAYER_G8B8_R8G8_to_R8G8B8_MHC(w, h, in, _out); - - // Now swap red and blue - swapRedAndBlue(w * h, (Color3uint8*)_out); -} - - -void GImage::BAYER_B8G8_G8R8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) { - // Run the equivalent function for red - BAYER_R8G8_G8B8_to_R8G8B8_MHC(w, h, in, _out); - - // Now swap red and blue - swapRedAndBlue(w * h, (Color3uint8*)_out); -} - - -void GImage::BAYER_G8B8_R8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) { - - debugAssert(in != _out); - - Color3uint8* out = (Color3uint8*)_out; - - for (int y = 0; y < h; ++y) { - - // Row beginning in the input array. - int offset = y * w; - - // GB row - for (int x = 0; x < w; ++x, ++out) { - // G pixel - { - out->r = applyFilter(in, x, y, w, h, R_BGG); - out->g = in[x + offset]; - out->b = applyFilter(in, x, y, w, h, B_BGG); - } - ++x; ++out; - - // B pixel - { - out->r = applyFilter(in, x, y, w, h, R_BGB); - out->g = applyFilter(in, x, y, w, h, G_BGB); - out->b = in[x + offset]; - } - } - - ++y; - offset += w; - - // RG row - for (int x = 0; x < w; ++x, ++out) { - // R pixel - { - out->r = in[x + offset]; - out->g = applyFilter(in, x, y, w, h, G_GRR); - out->b = applyFilter(in, x, y, w, h, B_GRR); - } - ++x; ++out; - - // G pixel - { - out->r = applyFilter(in, x, y, w, h, R_GRG); - out->g = in[x + offset]; - out->b = applyFilter(in, x, y, w, h, B_GRG); - } - } - } - -} - -#undef B_BGG -#undef B_GRG -#undef B_GRR - -} diff --git a/externals/g3dlite/G3D.lib/source/GImage_bmp.cpp b/externals/g3dlite/G3D.lib/source/GImage_bmp.cpp deleted file mode 100644 index 598ba730d0b..00000000000 --- a/externals/g3dlite/G3D.lib/source/GImage_bmp.cpp +++ /dev/null @@ -1,716 +0,0 @@ -/** - @file GImage_bmp.cpp - @author Morgan McGuire, morgan@graphics3d.com - @created 2002-05-27 - @edited 2006-05-10 - */ -#include "G3D/platform.h" -#include "G3D/GImage.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/Log.h" - -namespace G3D { - -#ifndef G3D_WIN32 -/** - This is used by the Windows bitmap I/O. - */ -static const int BI_RGB = 0; -#endif - -void GImage::encodeBMP( - BinaryOutput& out) const { - - debugAssert(channels == 1 || channels == 3); - out.setEndian(G3D_LITTLE_ENDIAN); - - uint8 red; - uint8 green; - uint8 blue; - int pixelBufferSize = width * height * 3; - int fileHeaderSize = 14; - int infoHeaderSize = 40; - int BMScanWidth; - int BMPadding; - - // First write the BITMAPFILEHEADER - // - // WORD bfType; - // DWORD bfSize; - // WORD bfReserved1; - // WORD bfReserved2; - // DWORD bfOffBits; - - // Type - out.writeUInt8('B'); - out.writeUInt8('M'); - - // File size - out.writeUInt32(fileHeaderSize + infoHeaderSize + pixelBufferSize); - - // Two reserved fields set to zero - out.writeUInt16(0); - out.writeUInt16(0); - - // The offset, in bytes, from the BITMAPFILEHEADER structure - // to the bitmap bits. - out.writeUInt32(infoHeaderSize + fileHeaderSize); - - // Now the BITMAPINFOHEADER - // - // DWORD biSize; - // LONG biWidth; - // LONG biHeight; - // WORD biPlanes; - // WORD biBitCount - // DWORD biCompression; - // DWORD biSizeImage; - // LONG biXPelsPerMeter; - // LONG biYPelsPerMeter; - // DWORD biClrUsed; - // DWORD biClrImportant; - - // Size of the info header - out.writeUInt32(infoHeaderSize); - - // Width and height of the image - out.writeUInt32(width); - out.writeUInt32(height); - - // Planes ("must be set to 1") - out.writeUInt16(1); - - // BitCount and CompressionType - out.writeUInt16(24); - out.writeUInt32(BI_RGB); - - // Image size ("may be zero for BI_RGB bitmaps") - out.writeUInt32(0); - - // biXPelsPerMeter - out.writeUInt32(0); - // biYPelsPerMeter - out.writeUInt32(0); - - // biClrUsed - out.writeUInt32(0); - - // biClrImportant - out.writeUInt32(0); - - BMScanWidth = width * 3; - - if (BMScanWidth & 3) { - BMPadding = 4 - (BMScanWidth & 3); - } else { - BMPadding = 0; - } - - int hStart = height - 1; - int hEnd = -1; - int hDir = -1; - int dest; - - // Write the pixel data - for (int h = hStart; h != hEnd; h += hDir) { - dest = channels * h * width; - for (int w = 0; w < width; ++w) { - - if (channels == 3) { - red = _byte[dest]; - green = _byte[dest + 1]; - blue = _byte[dest + 2]; - } else { - red = _byte[dest]; - green = _byte[dest]; - blue = _byte[dest]; - } - - out.writeUInt8(blue); - out.writeUInt8(green); - out.writeUInt8(red); - - dest += channels; - } - - if (BMPadding > 0) { - out.skip(BMPadding); - } - } -} - - -void GImage::decodeBMP( - BinaryInput& input) { - - // The BMP decoding uses these flags. - static const uint16 PICTURE_NONE = 0x0000; - static const uint16 PICTURE_BITMAP = 0x1000; - - // Compression Flags - static const uint16 PICTURE_UNCOMPRESSED = 0x0100; - static const uint16 PICTURE_MONOCHROME = 0x0001; - static const uint16 PICTURE_4BIT = 0x0002; - static const uint16 PICTURE_8BIT = 0x0004; - static const uint16 PICTURE_16BIT = 0x0008; - static const uint16 PICTURE_24BIT = 0x0010; - static const uint16 PICTURE_32BIT = 0x0020; - - (void)PICTURE_16BIT; - (void)PICTURE_32BIT; - - // This is a simple BMP loader that can handle uncompressed BMP files. - // Verify this is a BMP file by looking for the BM tag. - input.reset(); - std::string tag = input.readString(2); - if (tag != "BM") { - throw Error("Not a BMP file", input.getFilename()); - } - - channels = 3; - // Skip to the BITMAPINFOHEADER's width and height - input.skip(16); - - width = input.readUInt32(); - height = input.readUInt32(); - - // Skip to the bit count and compression type - input.skip(2); - - uint16 bitCount = input.readUInt16(); - uint32 compressionType = input.readUInt32(); - - uint8 red; - uint8 green; - uint8 blue; - uint8 blank; - - // Only uncompressed bitmaps are supported by this code - if ((int32)compressionType != BI_RGB) { - throw Error("BMP images must be uncompressed", input.getFilename()); - } - - uint8* palette = NULL; - - // Create the palette if needed - if (bitCount <= 8) { - - // Skip to the palette color count in the header - input.skip(12); - - int numColors = input.readUInt32(); - - palette = (uint8*)System::malloc(numColors * 3); - debugAssert(palette); - - // Skip past the end of the header to the palette info - input.skip(4); - - int c; - for(c = 0; c < numColors * 3; c += 3) { - // Palette information in bitmaps is stored in BGR_ format. - // That means it's blue-green-red-blank, for each entry. - blue = input.readUInt8(); - green = input.readUInt8(); - red = input.readUInt8(); - blank = input.readUInt8(); - - palette[c] = red; - palette[c + 1] = green; - palette[c + 2] = blue; - } - } - - int hStart = 0; - int hEnd = 0; - int hDir = 0; - - if (height < 0) { - height = -height; - hStart = 0; - hEnd = height; - hDir = 1; - } else { - //height = height; - hStart = height - 1; - hEnd = -1; - hDir = -1; - } - - _byte = (uint8*)System::malloc(width * height * 3); - debugAssert(_byte); - - int BMScanWidth; - int BMPadding; - uint8 BMGroup; - uint8 BMPixel8; - int currPixel; - int dest; - int flags = PICTURE_NONE; - - if (bitCount == 1) { - // Note that this file is not necessarily grayscale, since it's possible - // the palette is blue-and-white, or whatever. But of course most image - // programs only write 1-bit images if they're black-and-white. - flags = PICTURE_BITMAP | PICTURE_UNCOMPRESSED | PICTURE_MONOCHROME; - - // For bitmaps, each scanline is dword-aligned. - BMScanWidth = (width + 7) >> 3; - if (BMScanWidth & 3) { - BMScanWidth += 4 - (BMScanWidth & 3); - } - - // Powers of 2 - int pow2[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; - - for (int h = hStart; h != hEnd; h += hDir) { - - currPixel = 0; - dest = 3 * h * width; - - for (int w = 0; w < BMScanWidth; ++w) { - - BMGroup = input.readUInt8(); - - // Now we read the pixels. Usually there are eight pixels per byte, - // since each pixel is represented by one bit, but if the width - // is not a multiple of eight, the last byte will have some bits - // set, with the others just being extra. Plus there's the - // dword-alignment padding. So we keep checking to see if we've - // already read "width" number of pixels. - for (int i = 7; i >= 0; --i) { - if (currPixel < width) { - int src = 3 * ((BMGroup & pow2[i]) >> i); - - _byte[dest] = palette[src]; - _byte[dest + 1] = palette[src + 1]; - _byte[dest + 2] = palette[src + 2]; - - ++currPixel; - dest += 3; - } - } - } - } - - } else if (bitCount == 4) { - - flags = PICTURE_BITMAP | PICTURE_UNCOMPRESSED | PICTURE_4BIT; - - // For bitmaps, each scanline is dword-aligned. - int BMScanWidth = (width+1) >> 1; - if (BMScanWidth & 3) { - BMScanWidth += 4 - (BMScanWidth & 3); - } - - for (int h = hStart; h != hEnd; h += hDir) { - - currPixel = 0; - dest = 3 * h * width; - - for (int w = 0; w < BMScanWidth; w++) { - - BMGroup = input.readUInt8(); - int src[2]; - src[0] = 3 * ((BMGroup & 0xF0) >> 4); - src[1] = 3 * (BMGroup & 0x0F); - - // Now we read the pixels. Usually there are two pixels per byte, - // since each pixel is represented by four bits, but if the width - // is not a multiple of two, the last byte will have only four bits - // set, with the others just being extra. Plus there's the - // dword-alignment padding. So we keep checking to see if we've - // already read "Width" number of pixels. - - for (int i = 0; i < 2; ++i) { - if (currPixel < width) { - int tsrc = src[i]; - - _byte[dest] = palette[tsrc]; - _byte[dest + 1] = palette[tsrc + 1]; - _byte[dest + 2] = palette[tsrc + 2]; - - ++currPixel; - dest += 3; - } - } - } - } - - } else if (bitCount == 8) { - - flags = PICTURE_BITMAP | PICTURE_UNCOMPRESSED | PICTURE_8BIT; - - // For bitmaps, each scanline is dword-aligned. - BMScanWidth = width; - if (BMScanWidth & 3) { - BMScanWidth += 4 - (BMScanWidth & 3); - } - - for (int h = hStart; h != hEnd; h += hDir) { - - currPixel = 0; - - for (int w = 0; w < BMScanWidth; ++w) { - - BMPixel8 = input.readUInt8(); - - if (currPixel < width) { - dest = 3 * ((h * width) + currPixel); - int src = 3 * BMPixel8; - - _byte[dest] = palette[src]; - _byte[dest + 1] = palette[src + 1]; - _byte[dest + 2] = palette[src + 2]; - - ++currPixel; - } - } - } - - } else if (bitCount == 16) { - - System::free(_byte); - _byte = NULL; - System::free(palette); - palette = NULL; - throw Error("16-bit bitmaps not supported", input.getFilename()); - - } else if (bitCount == 24) { - input.skip(20); - - flags = PICTURE_BITMAP | PICTURE_UNCOMPRESSED | PICTURE_24BIT; - - // For bitmaps, each scanline is dword-aligned. - BMScanWidth = width * 3; - - if (BMScanWidth & 3) { - BMPadding = 4 - (BMScanWidth & 3); - } else { - BMPadding = 0; - } - - for (int h = hStart; h != hEnd; h += hDir) { - dest = 3 * h * width; - for (int w = 0; w < width; ++w) { - - blue = input.readUInt8(); - green = input.readUInt8(); - red = input.readUInt8(); - - _byte[dest] = red; - _byte[dest + 1] = green; - _byte[dest + 2] = blue; - - dest += 3; - } - - if (BMPadding) { - input.skip(2); - } - } - - } else if (bitCount == 32) { - - System::free(_byte); - _byte = NULL; - System::free(palette); - palette = NULL; - throw Error("32 bit bitmaps not supported", input.getFilename()); - - } else { - // We support all possible bit depths, so if the - // code gets here, it's not even a real bitmap. - System::free(_byte); - _byte = NULL; - throw Error("Not a bitmap!", input.getFilename()); - } - - System::free(palette); - palette = NULL; -} - - -void GImage::decodeICO( - BinaryInput& input) { - - // Header - uint16 r = input.readUInt16(); - debugAssert(r == 0); - r = input.readUInt16(); - debugAssert(r == 1); - - // Read the number of icons, although we'll only load the - // first one. - int count = input.readUInt16(); - - channels = 4; - - debugAssert(count > 0); - - const uint8* headerBuffer = input.getCArray() + input.getPosition(); - int maxWidth = 0, maxHeight = 0; - int maxHeaderNum = 0; - for (int currentHeader = 0; currentHeader < count; ++currentHeader) { - - const uint8* curHeaderBuffer = headerBuffer + (currentHeader * 16); - int tmpWidth = curHeaderBuffer[0]; - int tmpHeight = curHeaderBuffer[1]; - // Just in case there is a non-square icon, checking area - if ((tmpWidth * tmpHeight) > (maxWidth * maxHeight)) { - maxWidth = tmpWidth; - maxHeight = tmpHeight; - maxHeaderNum = currentHeader; - } - } - - input.skip(maxHeaderNum * 16); - - width = input.readUInt8(); - height = input.readUInt8(); - int numColors = input.readUInt8(); - - _byte = (uint8*)System::malloc(width * height * channels); - debugAssert(_byte); - - // Bit mask for packed bits - int mask = 0; - - int bitsPerPixel = 8; - - switch (numColors) { - case 2: - mask = 0x01; - bitsPerPixel = 1; - break; - - case 16: - mask = 0x0F; - bitsPerPixel = 4; - break; - - case 0: - numColors = 256; - mask = 0xFF; - bitsPerPixel = 8; - break; - default: - throw Error("Unsupported ICO color count.", input.getFilename()); - } - - input.skip(5); - // Skip 'size' unused - input.skip(4); - - int offset = input.readUInt32(); - - // Skip over any other icon descriptions - input.setPosition(offset); - - // Skip over bitmap header; it is redundant - input.skip(40); - - Array palette; - palette.resize(numColors, true); - for (int c = 0; c < numColors; ++c) { - palette[c].b = input.readUInt8(); - palette[c].g = input.readUInt8(); - palette[c].r = input.readUInt8(); - palette[c].a = input.readUInt8(); - } - - // The actual image and mask follow - - // The XOR Bitmap is stored as 1-bit, 4-bit or 8-bit uncompressed Bitmap - // using the same encoding as BMP files. The AND Bitmap is stored in as - // 1-bit uncompressed Bitmap. - // - // Pixels are stored bottom-up, left-to-right. Pixel lines are padded - // with zeros to end on a 32bit (4byte) boundary. Every line will have the - // same number of bytes. Color indices are zero based, meaning a pixel color - // of 0 represents the first color table entry, a pixel color of 255 (if there - // are that many) represents the 256th entry. -/* - int bitsPerRow = width * bitsPerPixel; - int bytesPerRow = iCeil((double)bitsPerRow / 8); - // Rows are padded to 32-bit boundaries - bytesPerRow += bytesPerRow % 4; - - // Read the XOR values into the color channel - for (int y = height - 1; y >= 0; --y) { - int x = 0; - // Read the row - for (int i = 0; i < bytesPerRow; ++i) { - uint8 byte = input.readUInt8(); - for (int j = 0; (j < 8) && (x < width); ++x, j += bitsPerPixel) { - int bit = ((byte << j) >> (8 - bitsPerPixel)) & mask; - pixel4(x, y) = colorTable[bit]; - } - } - } -*/ - int hStart = 0; - int hEnd = 0; - int hDir = 0; - - if (height < 0) { - height = -height; - hStart = 0; - hEnd = height; - hDir = 1; - } else { - //height = height; - hStart = height - 1; - hEnd = -1; - hDir = -1; - } - - int BMScanWidth; - uint8 BMGroup; - uint8 BMPixel8; - int currPixel; - int dest; - - if (bitsPerPixel == 1) { - // Note that this file is not necessarily grayscale, since it's possible - // the palette is blue-and-white, or whatever. But of course most image - // programs only write 1-bit images if they're black-and-white. - - // For bitmaps, each scanline is dword-aligned. - BMScanWidth = (width + 7) >> 3; - if (BMScanWidth & 3) { - BMScanWidth += 4 - (BMScanWidth & 3); - } - - // Powers of 2 - int pow2[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; - - for (int h = hStart; h != hEnd; h += hDir) { - - currPixel = 0; - dest = 3 * h * width; - - for (int w = 0; w < BMScanWidth; ++w) { - - BMGroup = input.readUInt8(); - - // Now we read the pixels. Usually there are eight pixels per byte, - // since each pixel is represented by one bit, but if the width - // is not a multiple of eight, the last byte will have some bits - // set, with the others just being extra. Plus there's the - // dword-alignment padding. So we keep checking to see if we've - // already read "width" number of pixels. - for (int i = 7; i >= 0; --i) { - if (currPixel < width) { - int src = ((BMGroup & pow2[i]) >> i); - - _byte[dest] = palette[src].r; - _byte[dest + 1] = palette[src].g; - _byte[dest + 2] = palette[src].b; - - ++currPixel; - dest += 4; - } - } - } - } - - } else if (bitsPerPixel == 4) { - - // For bitmaps, each scanline is dword-aligned. - int BMScanWidth = (width+1) >> 1; - if (BMScanWidth & 3) { - BMScanWidth += 4 - (BMScanWidth & 3); - } - - for (int h = hStart; h != hEnd; h += hDir) { - - currPixel = 0; - dest = 4 * h * width; - - for (int w = 0; w < BMScanWidth; w++) { - - BMGroup = input.readUInt8(); - int src[2]; - src[0] = ((BMGroup & 0xF0) >> 4); - src[1] = (BMGroup & 0x0F); - - // Now we read the pixels. Usually there are two pixels per byte, - // since each pixel is represented by four bits, but if the width - // is not a multiple of two, the last byte will have only four bits - // set, with the others just being extra. Plus there's the - // dword-alignment padding. So we keep checking to see if we've - // already read "Width" number of pixels. - - for (int i = 0; i < 2; ++i) { - if (currPixel < width) { - int tsrc = src[i]; - - _byte[dest] = palette[tsrc].r; - _byte[dest + 1] = palette[tsrc].g; - _byte[dest + 2] = palette[tsrc].b; - - ++currPixel; - dest += 4; - } - } - } - } - - } else if (bitsPerPixel == 8) { - - // For bitmaps, each scanline is dword-aligned. - BMScanWidth = width; - if (BMScanWidth & 3) { - BMScanWidth += 4 - (BMScanWidth & 3); - } - - for (int h = hStart; h != hEnd; h += hDir) { - - currPixel = 0; - - for (int w = 0; w < BMScanWidth; ++w) { - - BMPixel8 = input.readUInt8(); - - if (currPixel < width) { - dest = 4 * ((h * width) + currPixel); - int src = BMPixel8; - - _byte[dest] = palette[src].r; - _byte[dest + 1] = palette[src].g; - _byte[dest + 2] = palette[src].b; - - ++currPixel; - } - } - } - } - - // Read the mask into the alpha channel - int bitsPerRow = width; - int bytesPerRow = iCeil((double)bitsPerRow / 8); - - // For bitmaps, each scanline is dword-aligned. - //BMScanWidth = (width + 1) >> 1; - if (bytesPerRow & 3) { - bytesPerRow += 4 - (bytesPerRow & 3); - } - - for (int y = height - 1; y >= 0; --y) { - int x = 0; - // Read the row - for (int i = 0; i < bytesPerRow; ++i) { - uint8 byte = input.readUInt8(); - for (int j = 0; (j < 8) && (x < width); ++x, ++j) { - int bit = (byte >> (7 - j)) & 0x01; - pixel4(x, y).a = (1 - bit) * 0xFF; - } - } - } - -} - - -} diff --git a/externals/g3dlite/G3D.lib/source/GImage_jpeg.cpp b/externals/g3dlite/G3D.lib/source/GImage_jpeg.cpp deleted file mode 100644 index fe2812cf3b2..00000000000 --- a/externals/g3dlite/G3D.lib/source/GImage_jpeg.cpp +++ /dev/null @@ -1,445 +0,0 @@ -/** - @file GImage_jpeg.cpp - @author Morgan McGuire, morgan@graphics3d.com - @created 2002-05-27 - @edited 2006-10-10 - */ -#include "G3D/platform.h" -#include "G3D/GImage.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - -#include - -/** - Pick up libjpeg headers locally on Windows, but from the system on all other platforms. -*/ -extern "C" { -#include -#include -} - -namespace G3D { - - -const int jpegQuality = 96; - -/** - The IJG library needs special setup for compress/decompressing - from memory. These classes provide them. - - The format of this class is defined by the IJG library; do not - change it. - */ -class memory_destination_mgr { -public: - struct jpeg_destination_mgr pub; - JOCTET* buffer; - int size; - int count; -}; - -typedef memory_destination_mgr* mem_dest_ptr; - -/** - Signature dictated by IJG. - */ -static void init_destination ( - j_compress_ptr cinfo) { - - mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; - - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = dest->size; - dest->count=0; -} - -/** - Signature dictated by IJG. - */ -static boolean empty_output_buffer ( - j_compress_ptr cinfo) { - - mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; - - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = dest->size; - - return TRUE; -} - -/** - Signature dictated by IJG. - */ -static void term_destination ( - j_compress_ptr cinfo) { - - mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; - dest->count = dest->size - dest->pub.free_in_buffer; -} - -/** - Signature dictated by IJG. - */ -static void jpeg_memory_dest ( - j_compress_ptr cinfo, - JOCTET* buffer, - int size) { - - mem_dest_ptr dest; - - if (cinfo->dest == NULL) { - // First time for this JPEG object; call the - // IJG allocator to get space. - cinfo->dest = (struct jpeg_destination_mgr*) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, - JPOOL_PERMANENT, - sizeof(memory_destination_mgr)); - } - - dest = (mem_dest_ptr) cinfo->dest; - dest->size = size; - dest->buffer = buffer; - dest->pub.init_destination = init_destination; - dest->pub.empty_output_buffer = empty_output_buffer; - dest->pub.term_destination = term_destination; -} - -//////////////////////////////////////////////////////////////////////////////////////// - -#define INPUT_BUF_SIZE 4096 - -/** - Structure dictated by IJG. - */ -class memory_source_mgr { -public: - struct jpeg_source_mgr pub; - int source_size; - unsigned char* source_data; - boolean start_of_data; - JOCTET* buffer; -}; - - -typedef memory_source_mgr* mem_src_ptr; - - -/** - Signature dictated by IJG. - */ -static void init_source( - j_decompress_ptr cinfo) { - - mem_src_ptr src = (mem_src_ptr) cinfo->src; - - src->start_of_data = TRUE; -} - - -/** - Signature dictated by IJG. - */ -static boolean fill_input_buffer( - j_decompress_ptr cinfo) { - - mem_src_ptr src = (mem_src_ptr) cinfo->src; - - size_t bytes_read = 0; - - if (src->source_size > INPUT_BUF_SIZE) - bytes_read = INPUT_BUF_SIZE; - else - bytes_read = src->source_size; - - memcpy (src->buffer, src->source_data, bytes_read); - - src->source_data += bytes_read; - src->source_size -= bytes_read; - - src->pub.next_input_byte = src->buffer; - src->pub.bytes_in_buffer = bytes_read; - src->start_of_data = FALSE; - - - return TRUE; -} - - -/** - Signature dictated by IJG. - */ -static void skip_input_data( - j_decompress_ptr cinfo, - long num_bytes) { - - mem_src_ptr src = (mem_src_ptr)cinfo->src; - - if (num_bytes > 0) { - while (num_bytes > (long) src->pub.bytes_in_buffer) { - num_bytes -= (long) src->pub.bytes_in_buffer; - boolean s = fill_input_buffer(cinfo); - debugAssert(s); (void)s; - } - - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; - } -} - - -/** - Signature dictated by IJG. - */ -static void term_source ( - j_decompress_ptr cinfo) { - (void)cinfo; - // Intentionally empty -} - - -/** - Signature dictated by IJG. - */ -static void jpeg_memory_src ( - j_decompress_ptr cinfo, - JOCTET* buffer, - int size) { - - mem_src_ptr src; - - if (cinfo->src == NULL) { - // First time for this JPEG object - cinfo->src = (struct jpeg_source_mgr*) - (*cinfo->mem->alloc_small)( - (j_common_ptr) cinfo, - JPOOL_PERMANENT, - sizeof(memory_source_mgr)); - - src = (mem_src_ptr)cinfo->src; - - src->buffer = (JOCTET*) - (*cinfo->mem->alloc_small)( - (j_common_ptr) cinfo, - JPOOL_PERMANENT, - INPUT_BUF_SIZE * sizeof(JOCTET)); - } - - src = (mem_src_ptr)cinfo->src; - src->pub.init_source = init_source; - src->pub.fill_input_buffer = fill_input_buffer; - src->pub.skip_input_data = skip_input_data; - - // use default method - src->pub.resync_to_restart = jpeg_resync_to_restart; - src->pub.term_source = term_source; - src->source_data = buffer; - src->source_size = size; - - // forces fill_input_buffer on first read - src->pub.bytes_in_buffer = 0; - - // until buffer loaded - src->pub.next_input_byte = NULL; -} - - -void GImage::encodeJPEG( - BinaryOutput& out) const { - - if (channels != 3) { - // Convert to three channel - GImage tmp = *this; - tmp.convertToRGB(); - tmp.encodeJPEG(out); - return; - } - - debugAssert(channels == 3); - out.setEndian(G3D_LITTLE_ENDIAN); - - // Allocate and initialize a compression object - jpeg_compress_struct cinfo; - jpeg_error_mgr jerr; - - cinfo.err = jpeg_std_error(&jerr); - jpeg_create_compress(&cinfo); - - // Specify the destination for the compressed data. - // (Overestimate the size) - int buffer_size = width * height * 3 + 200; - JOCTET* compressed_data = (JOCTET*)System::malloc(buffer_size); - jpeg_memory_dest(&cinfo, compressed_data, buffer_size); - - - cinfo.image_width = width; - cinfo.image_height = height; - - // # of color components per pixel - cinfo.input_components = 3; - - // colorspace of input image - cinfo.in_color_space = JCS_RGB; - cinfo.input_gamma = 1.0; - - // Set parameters for compression, including image size & colorspace - jpeg_set_defaults(&cinfo); - jpeg_set_quality(&cinfo, jpegQuality, false); - cinfo.smoothing_factor = 0; - cinfo.optimize_coding = TRUE; -// cinfo.dct_method = JDCT_FLOAT; - cinfo.dct_method = JDCT_ISLOW; - cinfo.jpeg_color_space = JCS_YCbCr; - - // Initialize the compressor - jpeg_start_compress(&cinfo, TRUE); - - // Iterate over all scanlines from top to bottom - // pointer to a single row - JSAMPROW row_pointer[1]; - - // JSAMPLEs per row in image_buffer - int row_stride = cinfo.image_width * 3; - while (cinfo.next_scanline < cinfo.image_height) { - row_pointer[0] = &(_byte[cinfo.next_scanline * row_stride]); - jpeg_write_scanlines(&cinfo, row_pointer, 1); - } - - // Shut down the compressor - jpeg_finish_compress(&cinfo); - - // Figure out how big the result was. - int outLength = ((mem_dest_ptr)cinfo.dest)->count; - - // Release the JPEG compression object - jpeg_destroy_compress(&cinfo); - - // Copy into an appropriately sized output buffer. - out.writeBytes(compressed_data, outLength); - - // Free the conservative buffer. - System::free(compressed_data); - compressed_data = NULL; -} - - - -void GImage::decodeJPEG( - BinaryInput& input) { - - struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; - int loc = 0; - - channels = 3; - // We have to set up the error handler, in case initialization fails. - cinfo.err = jpeg_std_error(&jerr); - - // Initialize the JPEG decompression object. - jpeg_create_decompress(&cinfo); - - // Specify data source (eg, a file, for us, memory) - jpeg_memory_src(&cinfo, const_cast(input.getCArray()), input.size()); - - // Read the parameters with jpeg_read_header() - jpeg_read_header(&cinfo, TRUE); - - // Set parameters for decompression - // (We do nothing here since the defaults are fine) - - // Start decompressor - jpeg_start_decompress(&cinfo); - - // Get and set the values of interest to this object - this->width = cinfo.output_width; - this->height = cinfo.output_height; - - // Prepare the pointer object for the pixel data - _byte = (uint8*)System::malloc(width * height * 3); - - // JSAMPLEs per row in output buffer - int bpp = cinfo.output_components; - int row_stride = cinfo.output_width * bpp; - - // Make a one-row-high sample array that will go away when done with image - JSAMPARRAY temp = (*cinfo.mem->alloc_sarray) - ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); - - // Read data on a scanline by scanline basis - while (cinfo.output_scanline < cinfo.output_height) { - - // We may need to adjust the output based on the - // number of channels it has. - switch (bpp) { - case 1: - // Grayscale; decompress to temp. - jpeg_read_scanlines(&cinfo, temp, 1); - - // Expand to three channels - { - uint8* scan = &(_byte[loc * 3]); - uint8* endScan = scan + (width * 3); - uint8* t = *temp; - - while (scan < endScan) { - uint8 value = t[0]; - - // Spread the value 3x. - scan[0] = value; - scan[1] = value; - scan[2] = value; - - scan += 3; - t += 1; - } - } - break; - - case 3: - // Read directly into the array - { - // Need one extra level of indirection. - uint8* scan = _byte + loc; - JSAMPARRAY ptr = &scan; - jpeg_read_scanlines(&cinfo, ptr, 1); - } - break; - - case 4: - // RGBA; decompress to temp. - jpeg_read_scanlines(&cinfo, temp, 1); - - // Drop the 3rd channel - { - uint8* scan = &(_byte[loc * 3]); - uint8* endScan = scan + width * 3; - uint8* t = *temp; - - while (scan < endScan) { - scan[0] = t[0]; - scan[1] = t[1]; - scan[2] = t[2]; - - scan += 3; - t += 4; - } - } - break; - - default: - throw Error("Unexpected number of channels.", input.getFilename()); - } - - loc += row_stride; - } - - // Finish decompression - jpeg_finish_decompress(&cinfo); - - alwaysAssertM(this, "Corrupt GImage"); - // Release JPEG decompression object - jpeg_destroy_decompress(&cinfo); -} - - -} diff --git a/externals/g3dlite/G3D.lib/source/GImage_png.cpp b/externals/g3dlite/G3D.lib/source/GImage_png.cpp deleted file mode 100644 index 9fd6a743e8e..00000000000 --- a/externals/g3dlite/G3D.lib/source/GImage_png.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/** - @file GImage_png.cpp - @author Morgan McGuire, morgan@graphics3d.com - @created 2002-05-27 - @edited 2006-05-10 - */ -#include "G3D/platform.h" -#include "G3D/GImage.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/Log.h" -#include - -namespace G3D { - - -//libpng required function signature -static void png_read_data( - png_structp png_ptr, - png_bytep data, - png_size_t length) { - - - debugAssert( png_ptr->io_ptr != NULL ); - debugAssert( length >= 0 ); - debugAssert( data != NULL ); - - ((BinaryInput*)png_ptr->io_ptr)->readBytes(data, length); -} - -//libpng required function signature -static void png_write_data(png_structp png_ptr, - png_bytep data, - png_size_t length) { - - debugAssert( png_ptr->io_ptr != NULL ); - debugAssert( data != NULL ); - - ((BinaryOutput*)png_ptr->io_ptr)->writeBytes(data, length); -} - -//libpng required function signature -static void png_flush_data( - png_structp png_ptr) { - (void)png_ptr; - //Do nothing. -} - -//libpng required function signature -static void png_error( - png_structp png_ptr, - png_const_charp error_msg) { - - (void)png_ptr; - debugAssert( error_msg != NULL ); - throw GImage::Error(error_msg, "PNG"); -} - -//libpng required function signature -void png_warning( - png_structp png_ptr, - png_const_charp warning_msg) { - - (void)png_ptr; - debugAssert( warning_msg != NULL ); - Log::common()->println(warning_msg); -} - -void GImage::encodePNG( - BinaryOutput& out) const { - - debugAssert( channels == 1 || channels == 3 || channels == 4 ); - - if (this->height > (int)(PNG_UINT_32_MAX/png_sizeof(png_bytep))) - throw GImage::Error("Unsupported PNG height.", out.getFilename()); - - out.setEndian(G3D_LITTLE_ENDIAN); - - png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_error, png_warning); - if (!png_ptr) - throw GImage::Error("Unable to initialize PNG encoder.", out.getFilename()); - - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_write_struct(&png_ptr, &info_ptr); - throw GImage::Error("Unable to initialize PNG encoder.", out.getFilename()); - } - - //setup libpng write handler so can use BinaryOutput - png_set_write_fn(png_ptr, (void*)&out, png_write_data, png_flush_data); - - if (channels == 3) { - png_set_IHDR(png_ptr, info_ptr, this->width, this->height, 8, PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - } - else if (channels == 4) { - png_set_IHDR(png_ptr, info_ptr, this->width, this->height, 8, PNG_COLOR_TYPE_RGBA, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - } - else if (channels == 1) { - png_set_IHDR(png_ptr, info_ptr, this->width, this->height, 8, PNG_COLOR_TYPE_GRAY, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - } - else { - png_destroy_write_struct(&png_ptr, &info_ptr); - throw GImage::Error("Unsupported number of channels for PNG.", out.getFilename()); - } - - png_color_8_struct sig_bit; - sig_bit.red = 8; - sig_bit.green = 8; - sig_bit.blue = 8; - if (channels == 4) - sig_bit.alpha = 8; - else - sig_bit.alpha = 0; - png_set_sBIT(png_ptr, info_ptr, &sig_bit); - - //write the png header - png_write_info(png_ptr, info_ptr); - - png_bytepp row_pointers = new png_bytep[this->height]; - - for (int i=0; i < this->height; ++i) { - row_pointers[i] = (png_bytep)&this->_byte[(this->width * this->channels * i)]; - } - - png_write_image(png_ptr, row_pointers); - - png_write_end(png_ptr, info_ptr); - - delete[] row_pointers; - - png_destroy_write_struct(&png_ptr, &info_ptr); -} - - -void GImage::decodePNG( - BinaryInput& input) { - - png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_error, png_warning); - if (!png_ptr) - throw GImage::Error("Unable to initialize PNG decoder.", input.getFilename()); - - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); - throw GImage::Error("Unable to initialize PNG decoder.", input.getFilename()); - } - - png_infop end_info = png_create_info_struct(png_ptr); - if (!end_info) { - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - throw GImage::Error("Unable to initialize PNG decoder.", input.getFilename()); - } - - //now that the libpng structures are setup, change the error handlers and read routines - //to use G3D functions so that BinaryInput can be used. - - png_set_read_fn(png_ptr, (png_voidp)&input, png_read_data); - - //read in sequentially so that three copies of the file are not in memory at once - png_read_info(png_ptr, info_ptr); - - png_uint_32 png_width, png_height; - int bit_depth, color_type, interlace_type; - //this will validate the data it extracts from info_ptr - png_get_IHDR(png_ptr, info_ptr, &png_width, &png_height, &bit_depth, &color_type, - &interlace_type, int_p_NULL, int_p_NULL); - - if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - throw GImage::Error("Unsupported PNG color type - PNG_COLOR_TYPE_GRAY_ALPHA.", input.getFilename()); - } - - this->width = static_cast(png_width); - this->height = static_cast(png_height); - - //swap bytes of 16 bit files to least significant byte first - png_set_swap(png_ptr); - - png_set_strip_16(png_ptr); - - //Expand paletted colors into true RGB triplets - if (color_type == PNG_COLOR_TYPE_PALETTE) { - png_set_palette_to_rgb(png_ptr); - } - - //Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { - png_set_gray_1_2_4_to_8(png_ptr); - } - - //Expand paletted or RGB images with transparency to full alpha channels - //so the data will be available as RGBA quartets. - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { - png_set_tRNS_to_alpha(png_ptr); - } - - // Fix sub-8 bit_depth to 8bit - if (bit_depth < 8) { - png_set_packing(png_ptr); - } - - if ((color_type == PNG_COLOR_TYPE_RGBA) || - ((color_type == PNG_COLOR_TYPE_PALETTE) && (png_ptr->num_trans > 0)) ) { - - this->channels = 4; - this->_byte = (uint8*)System::malloc(width * height * 4); - - } else if ((color_type == PNG_COLOR_TYPE_RGB) || - (color_type == PNG_COLOR_TYPE_PALETTE)) { - - this->channels = 3; - this->_byte = (uint8*)System::malloc(width * height * 3); - - } else if (color_type == PNG_COLOR_TYPE_GRAY) { - - this->channels = 1; - this->_byte = (uint8*)System::malloc(width * height); - - } else { - throw GImage::Error("Unsupported PNG bit-depth or type.", input.getFilename()); - } - - //since we are reading row by row, required to handle interlacing - uint32 number_passes = png_set_interlace_handling(png_ptr); - - png_read_update_info(png_ptr, info_ptr); - - for (uint32 pass = 0; pass < number_passes; ++pass) { - for (uint32 y = 0; y < (uint32)height; ++y) { - png_bytep rowPointer = &this->_byte[width * this->channels * y]; - png_read_rows(png_ptr, &rowPointer, png_bytepp_NULL, 1); - } - } - -// png_read_image(png_ptr, &_byte); - png_read_end(png_ptr, info_ptr); - - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); -} - - -} diff --git a/externals/g3dlite/G3D.lib/source/GImage_ppm.cpp b/externals/g3dlite/G3D.lib/source/GImage_ppm.cpp deleted file mode 100644 index bfe5c8305e8..00000000000 --- a/externals/g3dlite/G3D.lib/source/GImage_ppm.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/** - @file GImage_ppm.cpp - @author Morgan McGuire, morgan@graphics3d.com - @created 2002-05-27 - @edited 2006-05-10 - */ -#include "G3D/platform.h" -#include "G3D/GImage.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/TextInput.h" -#include "G3D/TextOutput.h" -#include "G3D/Log.h" - -namespace G3D { - -void GImage::encodePPMASCII( - BinaryOutput& out) const { - - debugAssert(channels == 3); - - TextOutput::Settings ppmOptions; - ppmOptions.convertNewlines = false; - ppmOptions.numColumns = 70; - ppmOptions.wordWrap = TextOutput::Settings::WRAP_WITHOUT_BREAKING; - TextOutput ppm(ppmOptions); - // Always write out a full-color ppm - ppm.printf("P3\n%d %d\n255\n", width, height); - - const Color3uint8* c = this->pixel3(); - for (uint32 i = 0; i < (uint32)(width * height); ++i) { - ppm.printf("%d %d %d%c", c[i].r, c[i].g, c[i].b, - ((i % ((width * 3) - 1)) == 0) ? - '\n' : ' '); - } - - out.writeString(ppm.commitString()); -} - - -void GImage::encodePPM( - BinaryOutput& out) const { - - // http://netpbm.sourceforge.net/doc/ppm.html - debugAssert(channels == 3); - - std::string header = format("P6 %d %d 255 ", width, height); - - out.writeBytes(header.c_str(), header.size()); - - out.writeBytes(this->pixel3(), width * height * 3); -} - -void GImage::decodePPMASCII( - BinaryInput& input) { - - int ppmWidth; - int ppmHeight; - - double maxColor; - - // Create a TextInput object to parse ascii format - // Mixed binary/ascii formats will require more - - const std::string inputStr = input.readString(); - - TextInput::Settings ppmOptions; - ppmOptions.cppComments = false; - ppmOptions.otherCommentCharacter = '#'; - ppmOptions.signedNumbers = true; - ppmOptions.singleQuotedStrings = false; - - TextInput ppmInput(TextInput::FROM_STRING, inputStr, ppmOptions); - - //Skip first line in header P# - std::string ppmType = ppmInput.readSymbol(); - - ppmWidth = (int)ppmInput.readNumber(); - ppmHeight = (int)ppmInput.readNumber(); - - // Everything but a PBM will have a max color value - if (ppmType != "P2") { - maxColor = ppmInput.readNumber(); - } else { - maxColor = 255; - } - - if ((ppmWidth < 0) || - (ppmHeight < 0) || - (maxColor <= 0)) { - throw GImage::Error("Invalid PPM Header.", input.getFilename()); - } - - // I don't think it's proper to scale values less than 255 - if (maxColor <= 255.0) { - maxColor = 255.0; - } - - this->width = ppmWidth; - this->height = ppmHeight; - this->channels = 3; - // always scale down to 1 byte per channel - this->_byte = (uint8*)System::malloc(width * height * 3); - - // Read in the image data. I am not validating if the values match the maxColor - // requirements. I only scale if needed to fit within the byte available. - for (uint32 i = 0; i < (uint32)(width * height); ++i) { - // read in color and scale to max pixel defined in header - // A max color less than 255 might need to be left alone and not scaled. - Color3uint8& curPixel = *(this->pixel3() + i); - - if (ppmType == "P3") { - curPixel.r = (uint8)(ppmInput.readNumber() * (255.0 / maxColor)); - curPixel.g = (uint8)(ppmInput.readNumber() * (255.0 / maxColor)); - curPixel.b = (uint8)(ppmInput.readNumber() * (255.0 / maxColor)); - } else if (ppmType == "P2") { - uint8 pixel = (uint8)(ppmInput.readNumber() * (255.0 / maxColor)); - curPixel.r = pixel; - curPixel.g = pixel; - curPixel.b = pixel; - } else if (ppmType == "P1") { - int pixel = (uint8)(ppmInput.readNumber() * maxColor); - curPixel.r = pixel; - curPixel.g = pixel; - curPixel.b = pixel; - } - } -} - -/** Consumes whitespace up to and including a number, but not the following character */ -static int scanUInt(BinaryInput& input) { - char c = input.readUInt8(); - while (isWhiteSpace(c)) { - c = input.readUInt8(); - } - - std::string s; - s += c; - c = input.readUInt8(); - while (!isWhiteSpace(c)) { - s += c; - c = input.readUInt8(); - } - - // Back up one to avoid consuming the last character - input.setPosition(input.getPosition() - 1); - - int x; - sscanf(s.c_str(), "%d", &x); - return x; -} - -void GImage::decodePPM( - BinaryInput& input) { - - char head[2]; - int w, h; - - input.readBytes(head, 2); - if (head[0] != 'P' || head[1] != '6') { - throw GImage::Error("Invalid PPM Header.", input.getFilename()); - } - - w = scanUInt(input); - h = scanUInt(input); - - // Skip the max color specifier - scanUInt(input); - - if ((w < 0) || - (h < 0) || - (w > 100000) || - (h > 100000)) { - throw GImage::Error("Invalid PPM size in header.", input.getFilename()); - } - - // Trailing whitespace - input.readUInt8(); - - resize(w, h, 3); - - input.readBytes(_byte, width * height * 3); -} - -} diff --git a/externals/g3dlite/G3D.lib/source/GImage_tga.cpp b/externals/g3dlite/G3D.lib/source/GImage_tga.cpp deleted file mode 100644 index d84feedecc9..00000000000 --- a/externals/g3dlite/G3D.lib/source/GImage_tga.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/** - @file GImage_tga.cpp - @author Morgan McGuire, morgan@graphics3d.com - @created 2002-05-27 - @edited 2006-05-10 - */ -#include "G3D/platform.h" -#include "G3D/GImage.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/Log.h" - -namespace G3D { - -void GImage::encodeTGA( - BinaryOutput& out) const { - - out.setEndian(G3D_LITTLE_ENDIAN); - - // ID length - out.writeUInt8(0); - - // Color map Type - out.writeUInt8(0); - - // Type - out.writeUInt8(2); - - // Color map - out.skip(5); - - // x, y offsets - out.writeUInt16(0); - out.writeUInt16(0); - - // Width & height - out.writeUInt16(width); - out.writeUInt16(height); - - // Color depth - out.writeUInt8(8 * channels); - - // Image descriptor - if (channels == 3) { - // 0 alpha bits - out.writeUInt8(0); - } - else { - // 8 alpha bits - out.writeUInt8(8); - } - - // Image ID (zero length) - - if (channels == 3) { - // Pixels are upside down in BGR format. - for (int y = height - 1; y >= 0; y--) { - for (int x = 0; x < width; x++) { - uint8* p = &(_byte[3 * (y * width + x)]); - out.writeUInt8(p[2]); - out.writeUInt8(p[1]); - out.writeUInt8(p[0]); - } - } - } else { - // Pixels are upside down in BGRA format. - for (int y = height - 1; y >= 0; y--) { - for (int x = 0; x < width; x++) { - uint8* p = &(_byte[4 * (y * width + x)]); - out.writeUInt8(p[2]); - out.writeUInt8(p[1]); - out.writeUInt8(p[0]); - out.writeUInt8(p[3]); - } - } - } - - // Write "TRUEVISION-XFILE " 18 bytes from the end - // (with null termination) - out.writeString("TRUEVISION-XFILE "); -} - - -void GImage::decodeTGA( - BinaryInput& input) { - - // This is a simple TGA loader that can handle uncompressed - // truecolor TGA files (TGA type 2). - // Verify this is a TGA file by looking for the TRUEVISION tag. - int pos = input.getPosition(); - input.setPosition(input.size() - 18); - std::string tag = input.readString(16); - if (tag != "TRUEVISION-XFILE") { - throw Error("Not a TGA file", input.getFilename()); - } - - input.setPosition(pos); - - int IDLength = input.readUInt8(); - int colorMapType = input.readUInt8(); - int imageType = input.readUInt8(); - - (void)colorMapType; - - // 2 is the type supported by this routine. - if (imageType != 2) { - throw Error("TGA images must be type 2 (Uncompressed truecolor)", input.getFilename()); - } - - // Color map specification - input.skip(5); - - // Image specification - - // Skip x and y offsets - input.skip(4); - - width = input.readInt16(); - height = input.readInt16(); - - int colorDepth = input.readUInt8(); - - if ((colorDepth != 24) && (colorDepth != 32)) { - throw Error("TGA files must be 24 or 32 bit.", input.getFilename()); - } - - if (colorDepth == 32) { - channels = 4; - } else { - channels = 3; - } - - // Image descriptor contains overlay data as well - // as data indicating where the origin is - int imageDescriptor = input.readUInt8(); - (void)imageDescriptor; - - // Image ID - input.skip(IDLength); - - _byte = (uint8*)System::malloc(width * height * channels); - debugAssert(_byte); - - // Pixel data - int x; - int y; - - if (channels == 3) { - for (y = height - 1; y >= 0; y--) { - for (x = 0; x < width; x++) { - int b = input.readUInt8(); - int g = input.readUInt8(); - int r = input.readUInt8(); - - int i = (x + y * width) * 3; - _byte[i + 0] = r; - _byte[i + 1] = g; - _byte[i + 2] = b; - } - } - } else { - for (y = height - 1; y >= 0; y--) { - for (x = 0; x < width; x++) { - int b = input.readUInt8(); - int g = input.readUInt8(); - int r = input.readUInt8(); - int a = input.readUInt8(); - - int i = (x + y * width) * 4; - _byte[i + 0] = r; - _byte[i + 1] = g; - _byte[i + 2] = b; - _byte[i + 3] = a; - } - } - } -} - -} diff --git a/externals/g3dlite/G3D.lib/source/GLight.cpp b/externals/g3dlite/G3D.lib/source/GLight.cpp deleted file mode 100644 index 8acb066ef54..00000000000 --- a/externals/g3dlite/G3D.lib/source/GLight.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/** - @file GLight.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-11-12 - @edited 2007-10-22 -*/ - -#include "G3D/GLight.h" -#include "G3D/Sphere.h" - -namespace G3D { - -GLight::GLight() { - position = Vector4(0, 0, 0, 0); - color = Color3::white(); - spotDirection = Vector3(0, 0, -1); - spotCutoff = 180; - enabled = false; - attenuation[0] = 1.0; - attenuation[1] = 0.0; - attenuation[2] = 0.0; - specular = true; - diffuse = true; -} - - -GLight GLight::directional(const Vector3& toLight, const Color3& color, bool s, bool d) { - GLight L; - L.position = Vector4(toLight.direction(), 0); - L.color = color; - L.specular = s; - L.diffuse = d; - return L; -} - - -GLight GLight::point(const Vector3& pos, const Color3& color, float constAtt, float linAtt, float quadAtt, bool s, bool d) { - GLight L; - L.position = Vector4(pos, 1); - L.color = color; - L.attenuation[0] = constAtt; - L.attenuation[1] = linAtt; - L.attenuation[2] = quadAtt; - L.specular = s; - L.diffuse = d; - return L; -} - - -GLight GLight::spot(const Vector3& pos, const Vector3& pointDirection, float cutOffAngleDegrees, const Color3& color, float constAtt, float linAtt, float quadAtt, bool s, bool d) { - GLight L; - L.position = Vector4(pos, 1.0f); - L.spotDirection = pointDirection.direction(); - debugAssert(cutOffAngleDegrees <= 90); - L.spotCutoff = cutOffAngleDegrees; - L.color = color; - L.attenuation[0] = constAtt; - L.attenuation[1] = linAtt; - L.attenuation[2] = quadAtt; - L.specular = s; - L.diffuse = d; - return L; -} - - -bool GLight::operator==(const GLight& other) const { - return (position == other.position) && - (spotDirection == other.spotDirection) && - (spotCutoff == other.spotCutoff) && - (attenuation[0] == other.attenuation[0]) && - (attenuation[1] == other.attenuation[1]) && - (attenuation[2] == other.attenuation[2]) && - (color == other.color) && - (enabled == other.enabled) && - (specular == other.specular) && - (diffuse == other.diffuse); -} - -bool GLight::operator!=(const GLight& other) const { - return !(*this == other); -} - - -Sphere GLight::effectSphere(float cutoff) const { - if (position.w == 0) { - // Directional light - return Sphere(Vector3::zero(), (float)inf()); - } else { - // Avoid divide by zero - cutoff = max(cutoff, 0.0001f); - float maxIntensity = max(color.r, max(color.g, color.b)); - - float radius = (float)inf(); - - if (attenuation[2] != 0) { - - // Solve I / attenuation.dot(1, r, r^2) < cutoff for r - // - // a[0] + a[1] r + a[2] r^2 > I/cutoff - // - - float a = attenuation[2]; - float b = attenuation[1]; - float c = attenuation[0] - maxIntensity / cutoff; - - float discrim = square(b) - 4 * a * c; - - if (discrim >= 0) { - discrim = sqrt(discrim); - - float r1 = (-b + discrim) / (2 * a); - float r2 = (-b - discrim) / (2 * a); - - if (r1 < 0) { - if (r2 > 0) { - radius = r2; - } - } else if (r2 > 0) { - radius = min(r1, r2); - } else { - radius = r1; - } - } - - } else if (attenuation[1] != 0) { - - // Solve I / attenuation.dot(1, r) < cutoff for r - // - // r * a[1] + a[0] = I / cutoff - // r = (I / cutoff - a[0]) / a[1] - - float radius = (maxIntensity / cutoff - attenuation[0]) / attenuation[1]; - radius = max(radius, 0.0f); - } - - return Sphere(position.xyz(), radius); - - } -} - -} diff --git a/externals/g3dlite/G3D.lib/source/GThread.cpp b/externals/g3dlite/G3D.lib/source/GThread.cpp deleted file mode 100644 index 090370436c4..00000000000 --- a/externals/g3dlite/G3D.lib/source/GThread.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/** - @file GThread.cpp - - GThread class. - - @created 2005-09-24 - @edited 2005-10-22 - */ - -#include "G3D/GThread.h" -#include "G3D/System.h" -#include "G3D/debugAssert.h" - - -namespace G3D { - -namespace _internal { - -class BasicThread: public GThread { -public: - BasicThread(const std::string& name, void (*proc)(void*), void* param): - GThread(name), m_wrapperProc(proc), m_param(param) { } -protected: - virtual void threadMain() { - m_wrapperProc(m_param); - } - -private: - void (*m_wrapperProc)(void*); - - void* m_param; -}; - -} // namespace _internal - - -GThread::GThread(const std::string& name): - m_status(STATUS_CREATED), - m_name(name) { - -#ifdef G3D_WIN32 - m_event = NULL; -#endif - - // system-independent clear of handle - System::memset(&m_handle, 0, sizeof(m_handle)); -} - -GThread::~GThread() { -#ifdef _MSC_VER -# pragma warning( push ) -# pragma warning( disable : 4127 ) -#endif - alwaysAssertM(m_status != STATUS_RUNNING, "Deleting thread while running."); -#ifdef _MSC_VER -# pragma warning( pop ) -#endif - -#ifdef G3D_WIN32 - if (m_event) { - ::CloseHandle(m_event); - } -#endif -} - -GThreadRef GThread::create(const std::string& name, void (*proc)(void*), void* param) { - return new _internal::BasicThread(name, proc, param); -} - - -bool GThread::started() const { - return m_status != STATUS_CREATED; -} - -bool GThread::start() { - - debugAssertM(! started(), "Thread has already executed."); - if (started()) { - return false; - } - - m_status = STATUS_STARTED; - -# ifdef G3D_WIN32 - DWORD threadId; - - m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL); - debugAssert(m_event); - - m_handle = ::CreateThread(NULL, 0, &internalThreadProc, this, 0, &threadId); - - if (m_handle == NULL) { - ::CloseHandle(m_event); - m_event = NULL; - } - - return (m_handle != NULL); -# else - if (!pthread_create(&m_handle, NULL, &internalThreadProc, this)) { - return true; - } else { - // system-independent clear of handle - System::memset(&m_handle, 0, sizeof(m_handle)); - - return false; - } -# endif -} - -void GThread::terminate() { - if (m_handle) { -# ifdef G3D_WIN32 - ::TerminateThread(m_handle, 0); -# else - pthread_kill(m_handle, SIGSTOP); -# endif - // system-independent clear of handle - System::memset(&m_handle, 0, sizeof(m_handle)); - } -} - -bool GThread::running() const{ - return (m_status == STATUS_RUNNING); -} - -bool GThread::completed() const { - return (m_status == STATUS_COMPLETED); -} - -void GThread::waitForCompletion() { -# ifdef G3D_WIN32 - debugAssert(m_event); - ::WaitForSingleObject(m_event, INFINITE); -# else - debugAssert(m_handle); - pthread_join(m_handle, NULL); -# endif -} - -#ifdef G3D_WIN32 -DWORD WINAPI GThread::internalThreadProc(LPVOID param) { - GThread* current = reinterpret_cast(param); - debugAssert(current->m_event); - current->m_status = STATUS_RUNNING; - current->threadMain(); - current->m_status = STATUS_COMPLETED; - ::SetEvent(current->m_event); - return 0; -} -#else -void* GThread::internalThreadProc(void* param) { - GThread* current = reinterpret_cast(param); - current->m_status = STATUS_RUNNING; - current->threadMain(); - current->m_status = STATUS_COMPLETED; - return (void*)NULL; -} -#endif - - - -GMutex::GMutex() { -# ifdef G3D_WIN32 - ::InitializeCriticalSection(&m_handle); -# else - pthread_mutex_init(&m_handle, NULL); -# endif -} - -GMutex::~GMutex() { - //TODO: Debug check for locked -# ifdef G3D_WIN32 - ::DeleteCriticalSection(&m_handle); -# else - pthread_mutex_destroy(&m_handle); -# endif -} - -//bool GMutex::tryLock() { -//# ifdef G3D_WIN32 -// return ::TryEnterCriticalSection(&m_handle); -//# else -// return pthread_mutex_trylock(&m_handle); -//# endif -//} - -void GMutex::lock() { -# ifdef G3D_WIN32 - ::EnterCriticalSection(&m_handle); -# else - pthread_mutex_lock(&m_handle); -# endif -} - -void GMutex::unlock() { -# ifdef G3D_WIN32 - ::LeaveCriticalSection(&m_handle); -# else - pthread_mutex_unlock(&m_handle); -# endif -} - -} // namespace G3D diff --git a/externals/g3dlite/G3D.lib/source/GUniqueID.cpp b/externals/g3dlite/G3D.lib/source/GUniqueID.cpp deleted file mode 100644 index 25c757b70e4..00000000000 --- a/externals/g3dlite/G3D.lib/source/GUniqueID.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/** - @file GUniqueID.cpp - @author Morgan McGuire, morgan@cs.williams.edu - */ -#include "G3D/GUniqueID.h" -#include "G3D/BinaryInput.h" -#include "G3D/TextInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/TextOutput.h" -#include "G3D/NetworkDevice.h" - -namespace G3D { - -void GUniqueID::serialize(BinaryOutput& b) const { - b.writeUInt64(id); -} - - -void GUniqueID::deserialize(BinaryInput& b) { - id = b.readUInt64(); -} - -void GUniqueID::serialize(TextOutput& t) const { - t.writeSymbol("("); - t.writeNumber((double)(id >> 32)); - t.writeNumber((double)(id & 0xFFFFFFFF)); - t.writeSymbol(")"); -} - -void GUniqueID::deserialize(TextInput& t) { - t.readSymbol("("); - id = (((uint64)t.readNumber()) << 32) + (uint64)t.readNumber(); - t.readSymbol(")"); -} - - -GUniqueID GUniqueID::create(uint16 tag) { - static uint64 counter = 0; - static uint64 systemID = 0; - - if (systemID == 0) { - // Create a unique ID for this machine/program instance - - // TODO: see ioctl(skfd, SIOCGIFHWADDR, &if_hwaddr) - Array addr; - NetworkDevice::instance()->localHostAddresses(addr); - if (addr.size() > 0) { - systemID |= addr[0].ip(); - } - - union { - float64 ft; - uint64 ut; - }; - ft = System::time(); - systemID = ut << 22; - systemID ^= ((uint64)iRandom(0, 32768)) << 8; - - systemID &= ~((uint64)1023 << 54); - - // Ensure that the systemID is non-zero (vanishingly small probability) - if (systemID == 0) { - systemID = 1; - } - } - - // No need for modulo; we'll all be dead before this counter - // overflows 54 bits - ++counter; - - GUniqueID i; - - i.id = (((uint64)(tag & 1023)) << 54) | (counter ^ systemID); - - return i; -} - -} // G3D diff --git a/externals/g3dlite/G3D.lib/source/Image1.cpp b/externals/g3dlite/G3D.lib/source/Image1.cpp deleted file mode 100644 index 30841d01c6b..00000000000 --- a/externals/g3dlite/G3D.lib/source/Image1.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/** - @file Image1.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-01-31 - @edited 2007-01-31 -*/ - - -#include "G3D/Image1.h" -#include "G3D/Image1uint8.h" -#include "G3D/GImage.h" -#include "G3D/Color4.h" -#include "G3D/Color4uint8.h" -#include "G3D/Color1.h" -#include "G3D/Color1uint8.h" -#include "G3D/ImageFormat.h" - -namespace G3D { - -Image1::Image1(int w, int h, WrapMode wrap) : Map2D(w, h, wrap) { - setAll(Color1(0.0f)); -} - - -Image1::Ref Image1::fromGImage(const GImage& im, WrapMode wrap) { - switch (im.channels) { - case 1: - return fromArray(im.pixel1(), im.width, im.height, wrap); - - case 3: - return fromArray(im.pixel3(), im.width, im.height, wrap); - - case 4: - return fromArray(im.pixel4(), im.width, im.height, wrap); - - default: - debugAssertM(false, "Input GImage must have 1, 3, or 4 channels."); - return NULL; - } -} - - -Image1::Ref Image1::fromImage1uint8(const ReferenceCountedPointer& im) { - Ref out = createEmpty(static_cast(im->wrapMode())); - out->resize(im->width(), im->height()); - - int N = im->width() * im->height(); - const Color1uint8* src = reinterpret_cast(im->getCArray()); - for (int i = 0; i < N; ++i) { - out->data[i] = Color1(src[i]); - } - - return out; -} - - -Image1::Ref Image1::createEmpty(int width, int height, WrapMode wrap) { - return new Type(width, height, wrap); -} - - -Image1::Ref Image1::createEmpty(WrapMode wrap) { - return createEmpty(0, 0, wrap); -} - - -Image1::Ref Image1::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) { - Ref out = createEmpty(wrap); - out->load(filename); - return out; -} - - -void Image1::load(const std::string& filename, GImage::Format fmt) { - copyGImage(GImage(filename, fmt)); - setChanged(true); -} - - -Image1::Ref Image1::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image1::Ref Image1::fromArray(const class Color1* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image1::Ref Image1::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image1::Ref Image1::fromArray(const class Color3* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image1::Ref Image1::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image1::Ref Image1::fromArray(const class Color4* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - -void Image1::copyGImage(const GImage& im) { - switch (im.channels) { - case 1: - copyArray(im.pixel1(), im.width, im.height); - break; - - case 3: - copyArray(im.pixel3(), im.width, im.height); - break; - - case 4: - copyArray(im.pixel4(), im.width, im.height); - break; - } -} - - -void Image1::copyArray(const Color3uint8* src, int w, int h) { - resize(w, h); - - int N = w * h; - Color1* dst = data.getCArray(); - // Convert int8 -> float - for (int i = 0; i < N; ++i) { - dst[i] = Color1(Color3(src[i]).average()); - } -} - - -void Image1::copyArray(const Color4uint8* src, int w, int h) { - resize(w, h); - - int N = w * h; - Color1* dst = data.getCArray(); - - // Strip alpha and convert - for (int i = 0; i < N; ++i) { - dst[i] = Color1(Color3(src[i].rgb()).average()); - } -} - - -void Image1::copyArray(const Color1* src, int w, int h) { - resize(w, h); - System::memcpy(getCArray(), src, w * h * sizeof(Color1)); -} - - -void Image1::copyArray(const Color4* src, int w, int h) { - resize(w, h); - - int N = w * h; - Color1* dst = data.getCArray(); - - // Strip alpha - for (int i = 0; i < N; ++i) { - dst[i] = Color1(src[i].rgb().average()); - } -} - - -void Image1::copyArray(const Color1uint8* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color1* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i]= Color1(src[i]); - } -} - - -void Image1::copyArray(const Color3* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color1* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i] = Color1(src[i].average()); - } -} - - -/** Saves in any of the formats supported by G3D::GImage. */ -void Image1::save(const std::string& filename, GImage::Format fmt) { - GImage im(width(), height(), 1); - - int N = im.width * im.height; - Color1uint8* dst = im.pixel1(); - for (int i = 0; i < N; ++i) { - dst[i] = Color1uint8(data[i]); - } - - im.save(filename, fmt); -} - - -const ImageFormat* Image1::format() const { - return ImageFormat::L32F(); -} - -} // G3D diff --git a/externals/g3dlite/G3D.lib/source/Image1uint8.cpp b/externals/g3dlite/G3D.lib/source/Image1uint8.cpp deleted file mode 100644 index c43e7194d7d..00000000000 --- a/externals/g3dlite/G3D.lib/source/Image1uint8.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/** - @file Image1uint8.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-01-31 - @edited 2008-01-13 -*/ - -#include "G3D/Image1uint8.h" -#include "G3D/Image3uint8.h" -#include "G3D/Image1.h" -#include "G3D/GImage.h" -#include "G3D/Color1.h" -#include "G3D/Color1uint8.h" -#include "G3D/Color4.h" -#include "G3D/Color4uint8.h" -#include "G3D/ImageFormat.h" - -namespace G3D { - -Image1uint8::Image1uint8(int w, int h, WrapMode wrap) : Map2D(w, h, wrap) { - setAll(Color1uint8(0)); -} - - -Image1uint8::Ref Image1uint8::fromImage3uint8(const ReferenceCountedPointer& im) { - return fromArray(im->getCArray(), im->width(), im->height(), im->wrapMode()); -} - - -Image1uint8::Ref Image1uint8::fromGImage(const GImage& im, WrapMode wrap) { - switch (im.channels) { - case 1: - return fromArray(im.pixel1(), im.width, im.height, wrap); - - case 3: - return fromArray(im.pixel3(), im.width, im.height, wrap); - - case 4: - return fromArray(im.pixel4(), im.width, im.height, wrap); - - default: - debugAssertM(false, "Input GImage must have 1, 3, or 4 channels."); - return NULL; - } -} - - -Image1uint8::Ref Image1uint8::fromImage1(const ReferenceCountedPointer& im) { - Ref out = createEmpty(static_cast(im->wrapMode())); - out->copyArray(im->getCArray(), im->width(), im->height()); - - return out; -} - - -Image1uint8::Ref Image1uint8::createEmpty(int width, int height, WrapMode wrap) { - return new Type(width, height, wrap); -} - - -Image1uint8::Ref Image1uint8::createEmpty(WrapMode wrap) { - return createEmpty(0, 0, wrap); -} - - -Image1uint8::Ref Image1uint8::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) { - Ref out = createEmpty(wrap); - out->load(filename); - return out; -} - - -Image1uint8::Ref Image1uint8::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image1uint8::Ref Image1uint8::fromArray(const class Color1* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image1uint8::Ref Image1uint8::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image1uint8::Ref Image1uint8::fromArray(const class Color3* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image1uint8::Ref Image1uint8::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image1uint8::Ref Image1uint8::fromArray(const class Color4* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -void Image1uint8::load(const std::string& filename, GImage::Format fmt) { - copyGImage(GImage(filename, fmt)); - setChanged(true); -} - - -void Image1uint8::copyGImage(const GImage& im) { - switch (im.channels) { - case 1: - copyArray(im.pixel1(), im.width, im.height); - break; - - case 3: - copyArray(im.pixel3(), im.width, im.height); - break; - - case 4: - copyArray(im.pixel4(), im.width, im.height); - break; - } -} - - -void Image1uint8::copyArray(const Color3uint8* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color1uint8* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i].value = (src[i].r + src[i].g + src[i].b) / 3; - } -} - -void Image1uint8::copyArray(const Color3* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color1uint8* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i] = Color1uint8(Color1(src[i].average())); - } -} - - -void Image1uint8::copyArray(const Color1uint8* ptr, int w, int h) { - resize(w, h); - System::memcpy(getCArray(), ptr, w * h); -} - - -void Image1uint8::copyArray(const Color1* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color1uint8* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i] = Color1uint8(src[i]); - } -} - - -void Image1uint8::copyArray(const Color4uint8* ptr, int w, int h) { - resize(w, h); - int N = w * h; - - Color1uint8* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i].value = (ptr[i].r + ptr[i].g + ptr[i].b) / 3; - } -} - - -void Image1uint8::copyArray(const Color4* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color1uint8* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i] = Color1uint8(Color1(src[i].rgb().average())); - } -} - - -/** Saves in any of the formats supported by G3D::GImage. */ -void Image1uint8::save(const std::string& filename, GImage::Format fmt) { - GImage im(width(), height(), 1); - System::memcpy(im.byte(), getCArray(), width() * height()); - im.save(filename, fmt); -} - - -const ImageFormat* Image1uint8::format() const { - return ImageFormat::L8(); -} - -} // G3D diff --git a/externals/g3dlite/G3D.lib/source/Image3.cpp b/externals/g3dlite/G3D.lib/source/Image3.cpp deleted file mode 100644 index aa2ac6098dc..00000000000 --- a/externals/g3dlite/G3D.lib/source/Image3.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/** - @file Image3.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-01-31 - @edited 2007-01-31 -*/ - - -#include "G3D/Image3.h" -#include "G3D/Image3uint8.h" -#include "G3D/GImage.h" -#include "G3D/Color4.h" -#include "G3D/Color4uint8.h" -#include "G3D/Color1.h" -#include "G3D/Color1uint8.h" -#include "G3D/ImageFormat.h" - -namespace G3D { - -Image3::Image3(int w, int h, WrapMode wrap) : Map2D(w, h, wrap) { - setAll(Color3::black()); -} - - -Image3::Ref Image3::fromGImage(const GImage& im, WrapMode wrap) { - switch (im.channels) { - case 1: - return fromArray(im.pixel1(), im.width, im.height, wrap); - - case 3: - return fromArray(im.pixel3(), im.width, im.height, wrap); - - case 4: - return fromArray(im.pixel4(), im.width, im.height, wrap); - - default: - debugAssertM(false, "Input GImage must have 1, 3, or 4 channels."); - return NULL; - } -} - - -Image3::Ref Image3::fromImage3uint8(const ReferenceCountedPointer& im) { - Ref out = createEmpty(im->wrapMode()); - out->resize(im->width(), im->height()); - - int N = im->width() * im->height(); - const Color3uint8* src = reinterpret_cast(im->getCArray()); - for (int i = 0; i < N; ++i) { - out->data[i] = Color3(src[i]); - } - - return out; -} - - -Image3::Ref Image3::createEmpty(int width, int height, WrapMode wrap) { - return new Image3(width, height, wrap); -} - - -Image3::Ref Image3::createEmpty(WrapMode wrap) { - return createEmpty(0, 0, wrap); -} - - -Image3::Ref Image3::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) { - Ref out = createEmpty(wrap); - out->load(filename); - return out; -} - - -void Image3::load(const std::string& filename, GImage::Format fmt) { - copyGImage(GImage(filename, fmt)); - setChanged(true); -} - - -Image3::Ref Image3::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image3::Ref Image3::fromArray(const class Color1* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image3::Ref Image3::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image3::Ref Image3::fromArray(const class Color3* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image3::Ref Image3::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image3::Ref Image3::fromArray(const class Color4* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - -void Image3::copyGImage(const GImage& im) { - switch (im.channels) { - case 1: - copyArray(im.pixel1(), im.width, im.height); - break; - - case 3: - copyArray(im.pixel3(), im.width, im.height); - break; - - case 4: - copyArray(im.pixel4(), im.width, im.height); - break; - } -} - - -void Image3::copyArray(const Color3uint8* src, int w, int h) { - resize(w, h); - - int N = w * h; - Color3* dst = data.getCArray(); - // Convert int8 -> float - for (int i = 0; i < N; ++i) { - dst[i] = Color3(src[i]); - } -} - - -void Image3::copyArray(const Color4uint8* src, int w, int h) { - resize(w, h); - - int N = w * h; - Color3* dst = data.getCArray(); - - // Strip alpha and convert - for (int i = 0; i < N; ++i) { - dst[i] = Color3(src[i].rgb()); - } -} - - -void Image3::copyArray(const Color3* src, int w, int h) { - resize(w, h); - System::memcpy(getCArray(), src, w * h * sizeof(Color3)); -} - - -void Image3::copyArray(const Color4* src, int w, int h) { - resize(w, h); - - int N = w * h; - Color3* dst = data.getCArray(); - - // Strip alpha - for (int i = 0; i < N; ++i) { - dst[i] = src[i].rgb(); - } -} - - -void Image3::copyArray(const Color1uint8* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color3* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i].r = dst[i].g = dst[i].b = Color1(src[i]).value; - } -} - - -void Image3::copyArray(const Color1* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color3* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i].r = dst[i].g = dst[i].b = src[i].value; - } -} - - -/** Saves in any of the formats supported by G3D::GImage. */ -void Image3::save(const std::string& filename, GImage::Format fmt) { - GImage im(width(), height(), 3); - - int N = im.width * im.height; - Color3uint8* dst = im.pixel3(); - for (int i = 0; i < N; ++i) { - dst[i] = Color3uint8(data[i]); - } - - im.save(filename, fmt); -} - - -const ImageFormat* Image3::format() const { - return ImageFormat::RGB32F(); -} - -} // G3D diff --git a/externals/g3dlite/G3D.lib/source/Image3uint8.cpp b/externals/g3dlite/G3D.lib/source/Image3uint8.cpp deleted file mode 100644 index 2de32b6009e..00000000000 --- a/externals/g3dlite/G3D.lib/source/Image3uint8.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/** - @file Image3uint8.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-01-31 - @edited 2008-01-08 -*/ - -#include "G3D/Image1uint8.h" -#include "G3D/Image3uint8.h" -#include "G3D/Image3.h" -#include "G3D/GImage.h" -#include "G3D/Color1.h" -#include "G3D/Color1uint8.h" -#include "G3D/Color4.h" -#include "G3D/Color4uint8.h" -#include "G3D/ImageFormat.h" - -namespace G3D { - -Image3uint8::Ref Image3uint8::fromImage1uint8(const ReferenceCountedPointer& im) { - return fromArray(im->getCArray(), im->width(), im->height(), im->wrapMode()); -} - - -Image3uint8::Image3uint8(int w, int h, WrapMode wrap) : Map2D(w, h, wrap) { - setAll(Color3::black()); -} - - -Image3uint8::Ref Image3uint8::fromGImage(const GImage& im, WrapMode wrap) { - switch (im.channels) { - case 1: - return fromArray(im.pixel1(), im.width, im.height, wrap); - - case 3: - return fromArray(im.pixel3(), im.width, im.height, wrap); - - case 4: - return fromArray(im.pixel4(), im.width, im.height, wrap); - - default: - debugAssertM(false, "Input GImage must have 1, 3, or 4 channels."); - return NULL; - } -} - - -Image3uint8::Ref Image3uint8::fromImage3(const ReferenceCountedPointer& im) { - Ref out = createEmpty(static_cast(im->wrapMode())); - out->copyArray(im->getCArray(), im->width(), im->height()); - - return out; -} - - -Image3uint8::Ref Image3uint8::createEmpty(int width, int height, WrapMode wrap) { - return new Type(width, height, wrap); -} - - -Image3uint8::Ref Image3uint8::createEmpty(WrapMode wrap) { - return createEmpty(0, 0, wrap); -} - - -Image3uint8::Ref Image3uint8::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) { - Ref out = createEmpty(wrap); - out->load(filename); - return out; -} - - -Image3uint8::Ref Image3uint8::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image3uint8::Ref Image3uint8::fromArray(const class Color1* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image3uint8::Ref Image3uint8::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image3uint8::Ref Image3uint8::fromArray(const class Color3* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image3uint8::Ref Image3uint8::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image3uint8::Ref Image3uint8::fromArray(const class Color4* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -void Image3uint8::load(const std::string& filename, GImage::Format fmt) { - copyGImage(GImage(filename, fmt)); - setChanged(true); -} - - -void Image3uint8::copyGImage(const GImage& im) { - switch (im.channels) { - case 1: - copyArray(im.pixel1(), im.width, im.height); - break; - - case 3: - copyArray(im.pixel3(), im.width, im.height); - break; - - case 4: - copyArray(im.pixel4(), im.width, im.height); - break; - } -} - - -void Image3uint8::copyArray(const Color1uint8* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color3uint8* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i].r = dst[i].g = dst[i].b = src[i].value; - } -} - -void Image3uint8::copyArray(const Color1* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color3uint8* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i].r = dst[i].g = dst[i].b = Color1uint8(src[i]).value; - } -} - - -void Image3uint8::copyArray(const Color3uint8* ptr, int w, int h) { - resize(w, h); - System::memcpy(getCArray(), ptr, w * h * 3); -} - - -void Image3uint8::copyArray(const Color3* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color3uint8* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i] = Color3uint8(src[i]); - } -} - - -void Image3uint8::copyArray(const Color4uint8* ptr, int w, int h) { - resize(w, h); - - // Copy 3/4 bytes - GImage::RGBAtoRGB((const uint8*)ptr, (uint8*)getCArray(), w * h); -} - - -void Image3uint8::copyArray(const Color4* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color3uint8* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i] = Color3uint8(src[i].rgb()); - } -} - - -/** Saves in any of the formats supported by G3D::GImage. */ -void Image3uint8::save(const std::string& filename, GImage::Format fmt) { - GImage im(width(), height(), 3); - System::memcpy(im.byte(), getCArray(), width() * height() * 3); - im.save(filename, fmt); -} - - -ReferenceCountedPointer Image3uint8::getChannel(int c) const { - debugAssert(c >= 0 && c <= 2); - - Image1uint8Ref dst = Image1uint8::createEmpty(width(), height(), wrapMode()); - const Color3uint8* srcArray = getCArray(); - Color1uint8* dstArray = dst->getCArray(); - - const int N = width() * height(); - for (int i = 0; i < N; ++i) { - dstArray[i] = Color1uint8(srcArray[i][c]); - } - - return dst; -} - - -const ImageFormat* Image3uint8::format() const { - return ImageFormat::RGB8(); -} - -} // G3D diff --git a/externals/g3dlite/G3D.lib/source/Image4.cpp b/externals/g3dlite/G3D.lib/source/Image4.cpp deleted file mode 100644 index 84a1cd650b6..00000000000 --- a/externals/g3dlite/G3D.lib/source/Image4.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/** - @file Image4.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-01-31 - @edited 2008-07-27 -*/ - - -#include "G3D/Image4.h" -#include "G3D/Image4uint8.h" -#include "G3D/GImage.h" -#include "G3D/Color3.h" -#include "G3D/Color3uint8.h" -#include "G3D/Color1.h" -#include "G3D/Color1uint8.h" -#include "G3D/ImageFormat.h" - -namespace G3D { - -Image4::Image4(int w, int h, WrapMode wrap) : Map2D(w, h, wrap) { - setAll(Color4::zero()); -} - - -Image4::Ref Image4::fromGImage(const GImage& im, WrapMode wrap) { - switch (im.channels) { - case 1: - return fromArray(im.pixel1(), im.width, im.height, wrap); - - case 3: - return fromArray(im.pixel3(), im.width, im.height, wrap); - - case 4: - return fromArray(im.pixel4(), im.width, im.height, wrap); - - default: - debugAssertM(false, "Input GImage must have 1, 3, or 4 channels."); - return NULL; - } -} - - -Image4::Ref Image4::fromImage4uint8(const ReferenceCountedPointer& im) { - Ref out = createEmpty(static_cast(im->wrapMode())); - out->resize(im->width(), im->height()); - - int N = im->width() * im->height(); - const Color4uint8* src = reinterpret_cast(im->getCArray()); - for (int i = 0; i < N; ++i) { - out->data[i] = Color4(src[i]); - } - - return out; -} - - -Image4::Ref Image4::createEmpty(int width, int height, WrapMode wrap) { - return new Type(width, height, WrapMode::ERROR); -} - - -Image4::Ref Image4::createEmpty(WrapMode wrap) { - return createEmpty(0, 0, wrap); -} - - -Image4::Ref Image4::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) { - Ref out = createEmpty(wrap); - out->load(filename); - return out; -} - - -void Image4::load(const std::string& filename, GImage::Format fmt) { - copyGImage(GImage(filename, fmt)); - setChanged(true); -} - - -Image4::Ref Image4::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image4::Ref Image4::fromArray(const class Color1* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image4::Ref Image4::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image4::Ref Image4::fromArray(const class Color3* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image4::Ref Image4::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image4::Ref Image4::fromArray(const class Color4* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -void Image4::copyGImage(const GImage& im) { - switch (im.channels) { - case 1: - copyArray(im.pixel1(), im.width, im.height); - break; - - case 3: - copyArray(im.pixel3(), im.width, im.height); - break; - - case 4: - copyArray(im.pixel4(), im.width, im.height); - break; - } -} - - -void Image4::copyArray(const Color4uint8* src, int w, int h) { - resize(w, h); - - int N = w * h; - Color4* dst = data.getCArray(); - // Convert int8 -> float - for (int i = 0; i < N; ++i) { - dst[i] = Color4(src[i]); - } -} - - -void Image4::copyArray(const Color3uint8* src, int w, int h) { - resize(w, h); - - int N = w * h; - Color4* dst = data.getCArray(); - - // Add alpha and convert - for (int i = 0; i < N; ++i) { - dst[i] = Color4(Color3(src[i]), 1.0f); - } -} - - -void Image4::copyArray(const Color4* src, int w, int h) { - resize(w, h); - System::memcpy(getCArray(), src, w * h * sizeof(Color4)); -} - - -void Image4::copyArray(const Color3* src, int w, int h) { - resize(w, h); - - int N = w * h; - Color4* dst = data.getCArray(); - - // Add alpha - for (int i = 0; i < N; ++i) { - dst[i] = Color4(src[i], 1.0f); - } -} - - -void Image4::copyArray(const Color1uint8* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color4* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i].r = dst[i].g = dst[i].b = Color1(src[i]).value; - dst[i].a = 1.0f; - } -} - - -void Image4::copyArray(const Color1* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color4* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i].r = dst[i].g = dst[i].b = src[i].value; - dst[i].a = 1.0f; - } -} - - -/** Saves in any of the formats supported by G3D::GImage. */ -void Image4::save(const std::string& filename, GImage::Format fmt) { - GImage im(width(), height(), 4); - - int N = im.width * im.height; - Color4uint8* dst = im.pixel4(); - for (int i = 0; i < N; ++i) { - dst[i] = Color4uint8(data[i]); - } - - im.save(filename, fmt); -} - -const ImageFormat* Image4::format() const { - return ImageFormat::RGBA32F(); -} - -} // G3D diff --git a/externals/g3dlite/G3D.lib/source/Image4uint8.cpp b/externals/g3dlite/G3D.lib/source/Image4uint8.cpp deleted file mode 100644 index dee1cba14ba..00000000000 --- a/externals/g3dlite/G3D.lib/source/Image4uint8.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/** - @file Image4uint8.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-01-31 - @edited 2008-07-31 -*/ - -#include "G3D/Image4uint8.h" -#include "G3D/Image4.h" -#include "G3D/Image3uint8.h" -#include "G3D/Image3.h" -#include "G3D/GImage.h" -#include "G3D/Color1.h" -#include "G3D/Color1uint8.h" -#include "G3D/Color4.h" -#include "G3D/Color4uint8.h" -#include "G3D/ImageFormat.h" - -namespace G3D { - -Image4uint8::Image4uint8(int w, int h, WrapMode wrap) : Map2D(w, h, wrap) { - setAll(Color4::zero()); -} - - -Image4uint8::Ref Image4uint8::fromGImage(const GImage& im, WrapMode wrap) { - switch (im.channels) { - case 1: - return fromArray(im.pixel1(), im.width, im.height, wrap); - - case 3: - return fromArray(im.pixel3(), im.width, im.height, wrap); - - case 4: - return fromArray(im.pixel4(), im.width, im.height, wrap); - - default: - debugAssertM(false, "Input GImage must have 1, 3, or 4 channels."); - return NULL; - } -} - - -Image4uint8::Ref Image4uint8::fromImage4(const ReferenceCountedPointer& im) { - Ref out = createEmpty(static_cast(im->wrapMode())); - out->copyArray(im->getCArray(), im->width(), im->height()); - - return out; -} - - -Image4uint8::Ref Image4uint8::createEmpty(int width, int height, WrapMode wrap) { - return new Type(width, height, wrap); -} - - -Image4uint8::Ref Image4uint8::createEmpty(WrapMode wrap) { - return createEmpty(0, 0, wrap); -} - - -Image4uint8::Ref Image4uint8::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) { - Ref out = createEmpty(wrap); - out->load(filename); - return out; -} - - -Image4uint8::Ref Image4uint8::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image4uint8::Ref Image4uint8::fromArray(const class Color1* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image4uint8::Ref Image4uint8::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image4uint8::Ref Image4uint8::fromArray(const class Color3* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image4uint8::Ref Image4uint8::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -Image4uint8::Ref Image4uint8::fromArray(const class Color4* ptr, int w, int h, WrapMode wrap) { - Ref out = createEmpty(wrap); - out->copyArray(ptr, w, h); - return out; -} - - -void Image4uint8::load(const std::string& filename, GImage::Format fmt) { - copyGImage(GImage(filename, fmt)); - setChanged(true); -} - - -void Image4uint8::copyGImage(const GImage& im) { - switch (im.channels) { - case 1: - copyArray(im.pixel1(), im.width, im.height); - break; - - case 3: - copyArray(im.pixel3(), im.width, im.height); - break; - - case 4: - copyArray(im.pixel4(), im.width, im.height); - break; - } -} - - -void Image4uint8::copyArray(const Color1uint8* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color4uint8* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i].r = dst[i].g = dst[i].b = src[i].value; - dst[i].a = 255; - } -} - -void Image4uint8::copyArray(const Color1* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color4uint8* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i].r = dst[i].g = dst[i].b = Color1uint8(src[i]).value; - dst[i].a = 255; - } -} - - -void Image4uint8::copyArray(const Color4uint8* ptr, int w, int h) { - resize(w, h); - System::memcpy(getCArray(), ptr, w * h * 4); -} - - -void Image4uint8::copyArray(const Color4* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color4uint8* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i] = Color4uint8(src[i]); - } -} - - -void Image4uint8::copyArray(const Color3uint8* ptr, int w, int h) { - resize(w, h); - - GImage::RGBtoRGBA((const uint8*)ptr, (uint8*)getCArray(), w * h); -} - - -void Image4uint8::copyArray(const Color3* src, int w, int h) { - resize(w, h); - int N = w * h; - - Color4uint8* dst = getCArray(); - for (int i = 0; i < N; ++i) { - dst[i] = Color4uint8(Color4(src[i], 1.0f)); - } -} - - -/** Saves in any of the formats supported by G3D::GImage. */ -void Image4uint8::save(const std::string& filename, GImage::Format fmt) { - GImage im(width(), height(), 4); - System::memcpy(im.byte(), getCArray(), width() * height() * 4); - im.save(filename, fmt); -} - - -ReferenceCountedPointer Image4uint8::getChannel(int c) const { - debugAssert(c >= 0 && c <= 3); - - Image1uint8Ref dst = Image1uint8::createEmpty(width(), height(), wrapMode()); - const Color4uint8* srcArray = getCArray(); - Color1uint8* dstArray = dst->getCArray(); - - const int N = width() * height(); - for (int i = 0; i < N; ++i) { - dstArray[i] = Color1uint8(srcArray[i][c]); - } - - return dst; -} - - -const ImageFormat* Image4uint8::format() const { - return ImageFormat::RGBA8(); -} - -} // G3D diff --git a/externals/g3dlite/G3D.lib/source/ImageFormat.cpp b/externals/g3dlite/G3D.lib/source/ImageFormat.cpp deleted file mode 100644 index 3cbf6ad711e..00000000000 --- a/externals/g3dlite/G3D.lib/source/ImageFormat.cpp +++ /dev/null @@ -1,440 +0,0 @@ -/** - @file ImageFormat.cpp - - @maintainer Morgan McGuire, morgan@graphics3d.com - - @created 2003-05-23 - @edited 2006-01-11 - */ - -#include "../../GLG3D.lib/include/GLG3D/glheaders.h" -#include "../../GLG3D.lib/include/GLG3D/glcalls.h" -#include "G3D/ImageFormat.h" - -namespace G3D { - -ImageFormat::ImageFormat( - int _numComponents, - bool _compressed, - int _glFormat, - int _glBaseFormat, - int _luminanceBits, - int _alphaBits, - int _redBits, - int _greenBits, - int _blueBits, - int _depthBits, - int _stencilBits, - int _hardwareBitsPerTexel, - int _packedBitsPerTexel, - int glDataFormat, - bool _opaque, - bool _floatingPoint, - Code _code, - ColorSpace _colorSpace, - BayerPattern _bayerPattern) : - - numComponents(_numComponents), - compressed(_compressed), - code(_code), - colorSpace(_colorSpace), - bayerPattern(_bayerPattern), - openGLFormat(_glFormat), - openGLBaseFormat(_glBaseFormat), - luminanceBits(_luminanceBits), - alphaBits(_alphaBits), - redBits(_redBits), - greenBits(_greenBits), - blueBits(_blueBits), - stencilBits(_stencilBits), - depthBits(_depthBits), - cpuBitsPerPixel(_packedBitsPerTexel), - packedBitsPerTexel(_packedBitsPerTexel), - openGLBitsPerPixel(_hardwareBitsPerTexel), - hardwareBitsPerTexel(_hardwareBitsPerTexel), - openGLDataFormat(glDataFormat), - opaque(_opaque), - floatingPoint(_floatingPoint) { - - debugAssert(_packedBitsPerTexel <= _hardwareBitsPerTexel); -} - -const ImageFormat* ImageFormat::depth(int depthBits) { - - switch (depthBits) { - case 16: - return DEPTH16(); - - case 24: - return DEPTH24(); - - case 32: - return DEPTH32(); - - default: - debugAssertM(false, "Depth must be 16, 24, or 32."); - return DEPTH32(); - } -} - - -const ImageFormat* ImageFormat::stencil(int bits) { - switch (bits) { - case 1: - return STENCIL1(); - - case 4: - return STENCIL4(); - - case 8: - return STENCIL8(); - - case 16: - return STENCIL16(); - - default: - debugAssertM(false, "Stencil must be 1, 4, 8 or 16."); - return STENCIL16(); - } -} - - -std::string ImageFormat::name() const { - - static const std::string nameArray[] = - { - "L8", - "L16", - "L16F", - "L32F", - - "A8", - "A16", - "A16F", - "A32F", - - "LA4", - "LA8", - "LA16", - "LA16F", - "LA32F", - - "RGB5", - "RGB5A1", - "RGB8", - "RGB10", - "RGB10A2", - "RGB16", - "RGB16F", - "RGB32F", - - "ARGB8", - "BGR8", - - "RGBA8", - "RGBA16", - "RGBA16F", - "RGBA32F", - - "BAYER_RGGB8", - "BAYER_GRBG8", - "BAYER_GBRG8", - "BAYER_BGGR8", - "BAYER_RGGB32F", - "BAYER_GRBG32F", - "BAYER_GBRG32F", - "BAYER_BGGR32F", - - "HSV8", - "HSV32F", - - "YUV420_PLANAR", - "YUV422", - "YUV444", - - "RGB_DXT1", - "RGBA_DXT1", - "RGBA_DXT3", - "RGBA_DXT5", - - "DEPTH16", - "DEPTH24", - "DEPTH32", - "DEPTH32F", - - "STENCIL1", - "STENCIL4", - "STENCIL8", - "STENCIL16", - - "DEPTH24_STENCIL8" - }; - - debugAssert(code < CODE_NUM); - return nameArray[code]; -} - - -const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) { - switch (code) { - case ImageFormat::CODE_L8: - return ImageFormat::L8(); - break; - case ImageFormat::CODE_L16: - return ImageFormat::L16(); - break; - case ImageFormat::CODE_L16F: - return ImageFormat::L16F(); - break; - case ImageFormat::CODE_L32F: - return ImageFormat::L32F(); - break; - - case ImageFormat::CODE_A8: - return ImageFormat::A8(); - break; - case ImageFormat::CODE_A16: - return ImageFormat::A16(); - break; - case ImageFormat::CODE_A16F: - return ImageFormat::A16F(); - break; - case ImageFormat::CODE_A32F: - return ImageFormat::A32F(); - break; - - case ImageFormat::CODE_LA4: - return ImageFormat::LA4(); - break; - case ImageFormat::CODE_LA8: - return ImageFormat::LA8(); - break; - case ImageFormat::CODE_LA16: - return ImageFormat::LA16(); - break; - case ImageFormat::CODE_LA16F: - return ImageFormat::LA16F(); - break; - case ImageFormat::CODE_LA32F: - return ImageFormat::LA32F(); - break; - - case ImageFormat::CODE_RGB5: - return ImageFormat::RGB5(); - break; - case ImageFormat::CODE_RGB5A1: - return ImageFormat::RGB5A1(); - break; - case ImageFormat::CODE_RGB8: - return ImageFormat::RGB8(); - break; - case ImageFormat::CODE_RGB10: - return ImageFormat::RGB10(); - break; - case ImageFormat::CODE_RGB10A2: - return ImageFormat::RGB10A2(); - break; - case ImageFormat::CODE_RGB16: - return ImageFormat::RGB16(); - break; - case ImageFormat::CODE_RGB16F: - return ImageFormat::RGB16F(); - break; - case ImageFormat::CODE_RGB32F: - return ImageFormat::RGB32F(); - break; - - case ImageFormat::CODE_ARGB8: - return NULL; - - case ImageFormat::CODE_BGR8: - return NULL; - - case ImageFormat::CODE_RGBA8: - return ImageFormat::RGBA8(); - break; - case ImageFormat::CODE_RGBA16: - return ImageFormat::RGBA16(); - break; - case ImageFormat::CODE_RGBA16F: - return ImageFormat::RGBA16F(); - break; - case ImageFormat::CODE_RGBA32F: - return ImageFormat::RGBA32F(); - break; - - case ImageFormat::CODE_BAYER_RGGB8: - case ImageFormat::CODE_BAYER_GRBG8: - case ImageFormat::CODE_BAYER_GBRG8: - case ImageFormat::CODE_BAYER_BGGR8: - case ImageFormat::CODE_BAYER_RGGB32F: - case ImageFormat::CODE_BAYER_GRBG32F: - case ImageFormat::CODE_BAYER_GBRG32F: - case ImageFormat::CODE_BAYER_BGGR32F: - - case ImageFormat::CODE_HSV8: - case ImageFormat::CODE_HSV32F: - - case ImageFormat::CODE_RGB_DXT1: - return ImageFormat::RGB_DXT1(); - break; - case ImageFormat::CODE_RGBA_DXT1: - return ImageFormat::RGBA_DXT1(); - break; - case ImageFormat::CODE_RGBA_DXT3: - return ImageFormat::RGBA_DXT3(); - break; - case ImageFormat::CODE_RGBA_DXT5: - return ImageFormat::RGBA_DXT5(); - break; - - case ImageFormat::CODE_DEPTH16: - return ImageFormat::DEPTH16(); - break; - case ImageFormat::CODE_DEPTH24: - return ImageFormat::DEPTH24(); - break; - case ImageFormat::CODE_DEPTH32: - return ImageFormat::DEPTH32(); - break; - case ImageFormat::CODE_DEPTH32F: - return ImageFormat::DEPTH32F(); - break; - - case ImageFormat::CODE_STENCIL1: - return ImageFormat::STENCIL1(); - break; - case ImageFormat::CODE_STENCIL4: - return ImageFormat::STENCIL4(); - break; - case ImageFormat::CODE_STENCIL8: - return ImageFormat::STENCIL8(); - break; - case ImageFormat::CODE_STENCIL16: - return ImageFormat::STENCIL16(); - break; - - case ImageFormat::CODE_DEPTH24_STENCIL8: - return ImageFormat::DEPTH24_STENCIL8(); - break; - - case ImageFormat::CODE_YUV420_PLANAR: - return ImageFormat::YUV420_PLANAR(); - break; - - case ImageFormat::CODE_YUV422: - return ImageFormat::YUV422(); - break; - - case ImageFormat::CODE_YUV444: - return ImageFormat::YUV444(); - break; - - default: - return NULL; - } -} - -// Helper variables for defining texture formats - -// Is floating point format -static const bool FLOAT_FORMAT = true; -static const bool INT_FORMAT = false; - -// Is opaque format (no alpha) -static const bool OPAQUE_FORMAT = true; -static const bool CLEAR_FORMAT = false; - -// Is compressed format (not raw component data) -static const bool COMP_FORMAT = true; -static const bool UNCOMP_FORMAT = false; - -#define DEFINE_TEXTUREFORMAT_METHOD(name, cmpnts, cmprssd, glf, glbf, lb, rb, gb, bb, db, sb, hbpt, pbpt, gldf, opq, fp, code, cs, bp) \ - const ImageFormat* ImageFormat::name() { \ - static const ImageFormat format(cmpnts, cmprssd, glf, glbf, lb, rb, gb, bb, db, sb, hbpt, pbpt, gldf, opq, fp, code, cs, bp); \ - return &format; } - -DEFINE_TEXTUREFORMAT_METHOD(L8, 1, UNCOMP_FORMAT, GL_LUMINANCE8, GL_LUMINANCE, 8, 0, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, CODE_L8, COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(L16, 1, UNCOMP_FORMAT, GL_LUMINANCE16, GL_LUMINANCE, 16, 0, 0, 0, 0, 0, 0, 16, 16,GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INT_FORMAT, CODE_L16, COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(L16F, 1, UNCOMP_FORMAT, GL_LUMINANCE16F_ARB,GL_LUMINANCE, 16, 0, 0, 0, 0, 0, 0, 16, 16, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, CODE_L16F, COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(L32F, 1, UNCOMP_FORMAT, GL_LUMINANCE32F_ARB,GL_LUMINANCE, 32, 0, 0, 0, 0, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, CODE_L32F, COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(A8, 1, UNCOMP_FORMAT, GL_ALPHA8, GL_ALPHA, 0, 8, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, CODE_A8, COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(A16, 1, UNCOMP_FORMAT, GL_ALPHA16, GL_ALPHA, 0, 16, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, CODE_A16, COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(A16F, 1, UNCOMP_FORMAT, GL_ALPHA16F_ARB, GL_ALPHA, 0, 16, 0, 0, 0, 0, 0, 16, 16, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, CODE_A16F, COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(A32F, 1, UNCOMP_FORMAT, GL_ALPHA32F_ARB, GL_ALPHA, 0, 32, 0, 0, 0, 0, 0, 32, 32, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, CODE_A32F, COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(LA4, 2, UNCOMP_FORMAT, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, 4, 4, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, CODE_LA4, COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(LA8, 2, UNCOMP_FORMAT, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, 8, 8, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, CODE_LA8, COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(LA16, 2, UNCOMP_FORMAT, GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, 16, 16, 0, 0, 0, 0, 0, 16*2, 16*2, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, CODE_LA16, COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(LA16F, 2, UNCOMP_FORMAT, GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE_ALPHA, 16, 16, 0, 0, 0, 0, 0, 16*2, 16*2, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_LA16F, ImageFormat::COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(LA32F, 2, UNCOMP_FORMAT, GL_LUMINANCE_ALPHA32F_ARB, GL_LUMINANCE_ALPHA, 32, 32, 0, 0, 0, 0, 0, 32*2, 32*2, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_LA32F, ImageFormat::COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(BGR8, 3, UNCOMP_FORMAT, GL_RGB8, GL_BGR, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_BGR8, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGB5, 3, UNCOMP_FORMAT, GL_RGB5, GL_RGBA, 0, 0, 5, 5, 5, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB5, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGB5A1, 4, UNCOMP_FORMAT, GL_RGB5_A1, GL_RGBA, 0, 1, 5, 5, 5, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB5A1, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGB8, 3, UNCOMP_FORMAT, GL_RGB8, GL_RGB, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGB10, 3, UNCOMP_FORMAT, GL_RGB10, GL_RGB, 0, 0, 10, 10, 10, 0, 0, 32, 10*3, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB10, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGB10A2, 4, UNCOMP_FORMAT, GL_RGB10_A2, GL_RGBA, 0, 2, 10, 10, 10, 0, 0, 32, 32, GL_UNSIGNED_INT_10_10_10_2, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB10A2, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGB16, 3, UNCOMP_FORMAT, GL_RGB16, GL_RGB, 0, 0, 16, 16, 16, 0, 0, 16*3, 16*3, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB16, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGB16F, 3, UNCOMP_FORMAT, GL_RGB16F_ARB, GL_RGB, 0, 0, 16, 16, 16, 0, 0, 16*3, 16*3, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGB16F, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGB32F, 3, UNCOMP_FORMAT, GL_RGB32F_ARB, GL_RGB, 0, 0, 32, 32, 32, 0, 0, 32*3, 32*3, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGB32F, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGBA8, 4, UNCOMP_FORMAT, GL_RGBA8, GL_RGBA, 0, 8, 8, 8, 8, 0, 0, 32, 32, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA8, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGBA16, 4, UNCOMP_FORMAT, GL_RGBA16, GL_RGBA, 0, 16, 16, 16, 16, 0, 0, 16*4, 16*4, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA16, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGBA16F, 4, UNCOMP_FORMAT, GL_RGBA16F_ARB, GL_RGBA, 0, 16, 16, 16, 16, 0, 0, 16*4, 16*4, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGB16F, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGBA32F, 4, UNCOMP_FORMAT, GL_RGBA32F_ARB, GL_RGBA, 0, 32, 32, 32, 32, 0, 0, 32*4, 32*4, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGBA32F, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGB_DXT1, 3, COMP_FORMAT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB_DXT1, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT1, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA_DXT1, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT3, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA_DXT3, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT5, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA_DXT5, ImageFormat::COLOR_SPACE_RGB); - -DEFINE_TEXTUREFORMAT_METHOD(DEPTH16, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT16_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 0, 16, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_DEPTH16, ImageFormat::COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(DEPTH24, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 0, 24, 32, 24, GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_DEPTH24, ImageFormat::COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(DEPTH32, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 0, 32, 32, 32, GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_DEPTH32, ImageFormat::COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(DEPTH32F, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 0, 32, 32, 32, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_DEPTH32F, ImageFormat::COLOR_SPACE_NONE); - -// These formats are for use with Renderbuffers only! -DEFINE_TEXTUREFORMAT_METHOD(STENCIL1, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX1_EXT, GL_STENCIL_INDEX_EXT, 0, 0, 0, 0, 0, 0, 1, 1, 1, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_STENCIL1, ImageFormat::COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(STENCIL4, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX4_EXT, GL_STENCIL_INDEX_EXT, 0, 0, 0, 0, 0, 0, 4, 4, 4, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_STENCIL4, ImageFormat::COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(STENCIL8, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX8_EXT, GL_STENCIL_INDEX_EXT, 0, 0, 0, 0, 0, 0, 8, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_STENCIL8, ImageFormat::COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(STENCIL16, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX16_EXT, GL_STENCIL_INDEX_EXT, 0, 0, 0, 0, 0, 0, 16, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_STENCIL16, ImageFormat::COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(DEPTH24_STENCIL8, 2, UNCOMP_FORMAT, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH_STENCIL_EXT,0, 0, 0, 0, 0, 24, 8, 32, 32, GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_DEPTH24_STENCIL8, ImageFormat::COLOR_SPACE_NONE); - -DEFINE_TEXTUREFORMAT_METHOD(YUV420_PLANAR, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 12, 12, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_YUV420_PLANAR, ImageFormat::COLOR_SPACE_YUV); -DEFINE_TEXTUREFORMAT_METHOD(YUV422, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_YUV422, ImageFormat::COLOR_SPACE_YUV); -DEFINE_TEXTUREFORMAT_METHOD(YUV444, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 24, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_YUV444, ImageFormat::COLOR_SPACE_YUV); - -} diff --git a/externals/g3dlite/G3D.lib/source/ImageFormat_convert.cpp b/externals/g3dlite/G3D.lib/source/ImageFormat_convert.cpp deleted file mode 100644 index 9cbc4edcb39..00000000000 --- a/externals/g3dlite/G3D.lib/source/ImageFormat_convert.cpp +++ /dev/null @@ -1,1305 +0,0 @@ -#include "G3D/ImageFormat.h" -#include "G3D/Color1uint8.h" -#include "G3D/Color3uint8.h" -#include "G3D/Color4uint8.h" -#include "G3D/Color1.h" -#include "G3D/Color3.h" -#include "G3D/Color4.h" - - -namespace G3D { - -// this is the signature for all conversion routines (same parameters as ImageFormat::convert) -typedef void (*ConvertFunc)(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg); - -// this defines the conversion routines for converting between compatible formats -static const int NUM_CONVERT_IMAGE_FORMATS = 5; -struct ConvertAttributes { - ConvertFunc m_converter; - ImageFormat::Code m_sourceFormats[NUM_CONVERT_IMAGE_FORMATS]; - ImageFormat::Code m_destFormats[NUM_CONVERT_IMAGE_FORMATS]; - bool m_handlesSourcePadding; - bool m_handlesDestPadding; - bool m_handleInvertY; -}; - -// forward declare the converters we can use them below -#define DECLARE_CONVERT_FUNC(name) static void name(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg); - -DECLARE_CONVERT_FUNC(l8_to_rgb8); -DECLARE_CONVERT_FUNC(l32f_to_rgb8); -DECLARE_CONVERT_FUNC(rgb8_to_rgba8); -DECLARE_CONVERT_FUNC(rgb8_to_bgr8); -DECLARE_CONVERT_FUNC(rgb8_to_rgba32f); -DECLARE_CONVERT_FUNC(bgr8_to_rgb8); -DECLARE_CONVERT_FUNC(bgr8_to_rgba8); -DECLARE_CONVERT_FUNC(bgr8_to_rgba32f); -DECLARE_CONVERT_FUNC(rgba8_to_rgb8); -DECLARE_CONVERT_FUNC(rgba8_to_bgr8); -DECLARE_CONVERT_FUNC(rgba8_to_rgba32f); -DECLARE_CONVERT_FUNC(rgb32f_to_rgba32f); -DECLARE_CONVERT_FUNC(rgba32f_to_rgb8); -DECLARE_CONVERT_FUNC(rgba32f_to_rgba8); -DECLARE_CONVERT_FUNC(rgba32f_to_bgr8); -DECLARE_CONVERT_FUNC(rgba32f_to_rgb32f); -DECLARE_CONVERT_FUNC(rgba32f_to_bayer_rggb8); -DECLARE_CONVERT_FUNC(rgba32f_to_bayer_gbrg8); -DECLARE_CONVERT_FUNC(rgba32f_to_bayer_grbg8); -DECLARE_CONVERT_FUNC(rgba32f_to_bayer_bggr8); -DECLARE_CONVERT_FUNC(bayer_rggb8_to_rgba32f); -DECLARE_CONVERT_FUNC(bayer_gbrg8_to_rgba32f); -DECLARE_CONVERT_FUNC(bayer_grbg8_to_rgba32f); -DECLARE_CONVERT_FUNC(bayer_bggr8_to_rgba32f); -DECLARE_CONVERT_FUNC(rgb8_to_yuv420p); -DECLARE_CONVERT_FUNC(rgb8_to_yuv422); -DECLARE_CONVERT_FUNC(rgb8_to_yuv444); -DECLARE_CONVERT_FUNC(yuv420p_to_rgb8); -DECLARE_CONVERT_FUNC(yuv422_to_rgb8); -DECLARE_CONVERT_FUNC(yuv444_to_rgb8); - -// this is the list of mappings between formats and the routines to perform them -static const ConvertAttributes sConvertMappings[] = { - - // RGB -> RGB color space - // L8 -> - {l8_to_rgb8, {ImageFormat::CODE_L8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGB8, ImageFormat::CODE_NONE}, false, false, true}, - - // L32F -> - {l32f_to_rgb8, {ImageFormat::CODE_L32F, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGB8, ImageFormat::CODE_NONE}, false, false, true}, - - // RGB8 -> - {rgb8_to_rgba8, {ImageFormat::CODE_RGB8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGBA8, ImageFormat::CODE_NONE}, false, false, true}, - {rgb8_to_bgr8, {ImageFormat::CODE_RGB8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_BGR8, ImageFormat::CODE_NONE}, false, false, true}, - {rgb8_to_rgba32f, {ImageFormat::CODE_RGB8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, true, false, true}, - - // BGR8 -> - {bgr8_to_rgb8, {ImageFormat::CODE_BGR8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGB8, ImageFormat::CODE_NONE}, false, false, true}, - {bgr8_to_rgba8, {ImageFormat::CODE_BGR8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGBA8, ImageFormat::CODE_NONE}, false, false, true}, - {bgr8_to_rgba32f, {ImageFormat::CODE_BGR8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, true, false, true}, - - // RGBA8 -> - {rgba8_to_rgb8, {ImageFormat::CODE_RGBA8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGB8, ImageFormat::CODE_NONE}, false, false, true}, - {rgba8_to_bgr8, {ImageFormat::CODE_RGBA8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_BGR8, ImageFormat::CODE_NONE}, false, false, true}, - {rgba8_to_rgba32f, {ImageFormat::CODE_RGBA8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, true, false, true}, - - // RGB32F -> - {rgb32f_to_rgba32f, {ImageFormat::CODE_RGB32F, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, true, false, true}, - - // RGBA32F -> - {rgba32f_to_rgb8, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGB8, ImageFormat::CODE_NONE}, false, true, true}, - {rgba32f_to_rgba8, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGBA8, ImageFormat::CODE_NONE}, false, true, true}, - {rgba32f_to_bgr8, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, {ImageFormat::CODE_BGR8, ImageFormat::CODE_NONE}, false, true, true}, - {rgba32f_to_rgb32f, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGB32F, ImageFormat::CODE_NONE}, false, true, true}, - - // RGB -> BAYER color space - {rgba32f_to_bayer_rggb8, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, {ImageFormat::CODE_BAYER_RGGB8, ImageFormat::CODE_NONE}, false, true, true}, - {rgba32f_to_bayer_gbrg8, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, {ImageFormat::CODE_BAYER_GBRG8, ImageFormat::CODE_NONE}, false, true, true}, - {rgba32f_to_bayer_grbg8, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, {ImageFormat::CODE_BAYER_GRBG8, ImageFormat::CODE_NONE}, false, true, true}, - {rgba32f_to_bayer_bggr8, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, {ImageFormat::CODE_BAYER_BGGR8, ImageFormat::CODE_NONE}, false, true, true}, - - // BAYER -> RGB color space - {bayer_rggb8_to_rgba32f, {ImageFormat::CODE_BAYER_RGGB8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, false, false, true}, - {bayer_gbrg8_to_rgba32f, {ImageFormat::CODE_BAYER_GBRG8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, false, false, true}, - {bayer_grbg8_to_rgba32f, {ImageFormat::CODE_BAYER_GRBG8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, false, false, true}, - {bayer_bggr8_to_rgba32f, {ImageFormat::CODE_BAYER_BGGR8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGBA32F, ImageFormat::CODE_NONE}, false, false, true}, - - // RGB <-> YUV color space - {rgb8_to_yuv420p, {ImageFormat::CODE_RGB8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_YUV420_PLANAR, ImageFormat::CODE_NONE}, false, false, false}, - {rgb8_to_yuv422, {ImageFormat::CODE_RGB8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_YUV422, ImageFormat::CODE_NONE}, false, false, false}, - {rgb8_to_yuv444, {ImageFormat::CODE_RGB8, ImageFormat::CODE_NONE}, {ImageFormat::CODE_YUV444, ImageFormat::CODE_NONE}, false, false, false}, - {yuv420p_to_rgb8, {ImageFormat::CODE_YUV420_PLANAR, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGB8, ImageFormat::CODE_NONE}, false, false, false}, - {yuv422_to_rgb8, {ImageFormat::CODE_YUV422, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGB8, ImageFormat::CODE_NONE}, false, false, false}, - {yuv444_to_rgb8, {ImageFormat::CODE_YUV444, ImageFormat::CODE_NONE}, {ImageFormat::CODE_RGB8, ImageFormat::CODE_NONE}, false, false, false}, -}; - -static ConvertFunc findConverter(TextureFormat::Code sourceCode, TextureFormat::Code destCode, bool needsSourcePadding, bool needsDestPadding, bool needsInvertY) { - int numRoutines = sizeof(sConvertMappings) / sizeof(ConvertAttributes); - for (int routineIndex = 0; routineIndex < numRoutines; ++routineIndex) { - int sourceIndex = 0; - ConvertAttributes routine = sConvertMappings[routineIndex]; - - while (routine.m_sourceFormats[sourceIndex] != ImageFormat::CODE_NONE) { - // check for matching source - if (routine.m_sourceFormats[sourceIndex] == sourceCode) { - int destIndex = 0; - - // now check for matching dest to see if the routine fits - while (routine.m_destFormats[destIndex] != ImageFormat::CODE_NONE) { - - // check if dest format matches and padding + invert rules match - if ((routine.m_destFormats[destIndex] == destCode) && - (!needsSourcePadding || (routine.m_handlesSourcePadding == needsSourcePadding)) && - (!needsDestPadding || (routine.m_handlesDestPadding == needsDestPadding)) && - (!needsInvertY || (routine.m_handleInvertY == needsInvertY))) { - - // found compatible converter - return routine.m_converter; - } - ++destIndex; - } - } - ++sourceIndex; - } - } - - return NULL; -} - -bool conversionAvailable(const ImageFormat* srcFormat, int srcRowPadBits, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY = false) { - bool conversionAvailable = false; - - // check if a conversion is available - if ( (srcFormat->code == dstFormat->code) && (srcRowPadBits == dstRowPadBits) && !invertY) { - conversionAvailable = true; - } else { - ConvertFunc directConverter = findConverter(srcFormat->code, dstFormat->code, srcRowPadBits > 0, dstRowPadBits > 0, invertY); - - conversionAvailable = (directConverter != NULL); - } - - return conversionAvailable; -} - -bool ImageFormat::convert(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, - const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, - bool invertY, BayerAlgorithm bayerAlg) { - - bool conversionAvailable = false; - - // Handle direct copy of image to same format - if ( (srcFormat->code == dstFormat->code) && (srcRowPadBits == dstRowPadBits) && !invertY) { - - System::memcpy(dstBytes[0], srcBytes[0], iCeil(((srcWidth * srcFormat->cpuBitsPerPixel + srcRowPadBits) * srcHeight) / 8.0f)); - conversionAvailable = true; - } else { - // if no direct conversion routine exists, - // then look for conversion to intermediate - // and then from intermediate to dest. - // intermediate format is RGBA32F - ConvertFunc directConverter = findConverter(srcFormat->code, dstFormat->code, srcRowPadBits > 0, dstRowPadBits > 0, invertY); - - // if we have a direct converter, use it, otherwise find intermdiate path - if (directConverter) { - directConverter(srcBytes, srcWidth, srcHeight, srcFormat, srcRowPadBits, dstBytes, dstFormat, dstRowPadBits, invertY, bayerAlg); - conversionAvailable = true; - } else { - ConvertFunc toInterConverter = findConverter(srcFormat->code, ImageFormat::CODE_RGBA32F, srcRowPadBits > 0, false, false);; - ConvertFunc fromInterConverter = findConverter(ImageFormat::CODE_RGBA32F, dstFormat->code, false, dstRowPadBits > 0, invertY);; - - if (toInterConverter && fromInterConverter) { - Array tmp; - tmp.append(System::malloc(srcWidth * srcHeight * ImageFormat::RGBA32F()->cpuBitsPerPixel * 8)); - - toInterConverter(srcBytes, srcWidth, srcHeight, srcFormat, srcRowPadBits, tmp, ImageFormat::RGBA32F(), 0, false, bayerAlg); - fromInterConverter(reinterpret_cast&>(tmp), srcWidth, srcHeight, ImageFormat::RGBA32F(), 0, dstBytes, dstFormat, dstRowPadBits, invertY, bayerAlg); - - System::free(tmp[0]); - - conversionAvailable = true; - } - } - } - - return conversionAvailable; -} - - -// ******************* -// RGB -> RGB color space conversions -// ******************* - -// L8 -> -static void l8_to_rgb8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - uint8* dst = static_cast(dstBytes[0]); - const uint8* src = static_cast(srcBytes[0]); - for (int y = 0; y < srcHeight; ++y) { - for (int x = 0; x < srcWidth; ++x) { - int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x); - int i3 = i * 3; - - dst[i3 + 0] = src[i]; - dst[i3 + 1] = src[i]; - dst[i3 + 2] = src[i]; - } - } -} - -// L32F -> -static void l32f_to_rgb8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - int srcIndex = 0; - int dstByteOffset = 0; - uint8* dst = static_cast(dstBytes[0]); - const float* src = static_cast(srcBytes[0]); - - for (int y = 0; y < srcHeight; ++y) { - if (invertY) { - srcIndex = srcWidth * (srcHeight - y - 1); - } - - for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 3) { - Color3uint8& d = *reinterpret_cast(dst + dstByteOffset); - float s = src[srcIndex]; - - uint8 c = iMin(255, iFloor(s * 256)); - d = Color3uint8(c, c, c); - } - } -} - -// RGB8 -> -static void rgb8_to_rgba8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - uint8* dst = static_cast(dstBytes[0]); - const uint8* src = static_cast(srcBytes[0]); - for (int y = 0; y < srcHeight; ++y) { - for (int x = 0; x < srcWidth; ++x) { - int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x); - int i3 = i * 3; - int i4 = i3 + i; - - dst[i4 + 0] = src[i3 + 0]; - dst[i4 + 1] = src[i3 + 1]; - dst[i4 + 2] = src[i3 + 2]; - dst[i4 + 3] = 255; - } - } -} - -static void rgb8_to_bgr8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - uint8* dst = static_cast(dstBytes[0]); - const uint8* src = static_cast(srcBytes[0]); - for (int y = 0; y < srcHeight; ++y) { - for (int x = 0; x < srcWidth; ++x) { - int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x); - int i3 = i * 3; - dst[i3 + 0] = src[i3 + 2]; - dst[i3 + 1] = src[i3 + 1]; - dst[i3 + 2] = src[i3 + 0]; - } - } -} - -static void rgb8_to_rgba32f(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - debugAssertM(srcRowPadBits % 8 == 0, "Source row padding must be a multiple of 8 bits for this format"); - - int dstIndex = 0; - int srcByteOffset = 0; - int srcRowPadBytes = srcRowPadBits / 8; - Color4* dst = static_cast(dstBytes[0]); - const uint8* src = static_cast(srcBytes[0]); - - for (int y = 0; y < srcHeight; ++y) { - if (invertY) { - dstIndex = srcWidth * (srcHeight - 1 - y); - } - for (int x = 0; x < srcWidth; ++x, ++dstIndex, srcByteOffset += 3) { - const Color3uint8& s = *reinterpret_cast(src + srcByteOffset); - dst[dstIndex] = Color4(Color3(s), 1.0f); - } - srcByteOffset += srcRowPadBytes; - } -} - -// BGR8 -> -static void bgr8_to_rgb8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - uint8* dst = static_cast(dstBytes[0]); - const uint8* src = static_cast(srcBytes[0]); - for (int y = 0; y < srcHeight; ++y) { - for (int x = 0; x < srcWidth; ++x) { - int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x); - int i3 = i * 3; - dst[i3 + 0] = src[i3 + 2]; - dst[i3 + 1] = src[i3 + 1]; - dst[i3 + 2] = src[i3 + 0]; - } - } -} - -static void bgr8_to_rgba8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - uint8* dst = static_cast(dstBytes[0]); - const uint8* src = static_cast(srcBytes[0]); - for (int y = 0; y < srcHeight; ++y) { - for (int x = 0; x < srcWidth; ++x) { - int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x); - int i3 = i * 3; - int i4 = i3 + i; - - dst[i4 + 0] = src[i3 + 2]; - dst[i4 + 1] = src[i3 + 1]; - dst[i4 + 2] = src[i3 + 0]; - dst[i4 + 3] = 255; - } - } -} - -static void bgr8_to_rgba32f(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - debugAssertM(srcRowPadBits % 8 == 0, "Source row padding must be a multiple of 8 bits for this format"); - - int dstIndex = 0; - int srcByteOffset = 0; - int srcRowPadBytes = srcRowPadBits / 8; - Color4* dst = static_cast(dstBytes[0]); - const uint8* src = static_cast(srcBytes[0]); - - for (int y = 0; y < srcHeight; ++y) { - if (invertY) { - dstIndex = srcWidth * (srcHeight - 1 - y); - } - - for (int x = 0; x < srcWidth; ++x, ++dstIndex, srcByteOffset += 3) { - const Color3uint8& s = *reinterpret_cast(src + srcByteOffset); - dst[dstIndex] = Color4(Color3(s).bgr(), 1.0f); - } - srcByteOffset += srcRowPadBytes; - } -} - -// RGBA8 -> -static void rgba8_to_rgb8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - uint8* dst = static_cast(dstBytes[0]); - const uint8* src = static_cast(srcBytes[0]); - for (int y = 0; y < srcHeight; ++y) { - for (int x = 0; x < srcWidth; ++x) { - int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x); - int i3 = i * 3; - int i4 = i3 + i; - - dst[i3 + 0] = src[i4 + 0]; - dst[i3 + 1] = src[i4 + 1]; - dst[i3 + 2] = src[i4 + 2]; - } - } -} - -static void rgba8_to_bgr8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - uint8* dst = static_cast(dstBytes[0]); - const uint8* src = static_cast(srcBytes[0]); - for (int y = 0; y < srcHeight; ++y) { - for (int x = 0; x < srcWidth; ++x) { - int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x); - int i3 = i * 3; - int i4 = i3 + i; - - dst[i3 + 0] = src[i4 + 2]; - dst[i3 + 1] = src[i4 + 1]; - dst[i3 + 2] = src[i4 + 0]; - } - } -} - -static void rgba8_to_rgba32f(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - debugAssertM(srcRowPadBits % 8 == 0, "Source row padding must be a multiple of 8 bits for this format"); - - int dstIndex = 0; - int srcByteOffset = 0; - int srcRowPadBytes = srcRowPadBits / 8; - Color4* dst = static_cast(dstBytes[0]); - const uint8* src = static_cast(srcBytes[0]); - - for (int y = 0; y < srcHeight; ++y) { - if (invertY) { - dstIndex = srcWidth * (srcHeight - 1 - y); - } - - for (int x = 0; x < srcWidth; ++x, ++dstIndex, srcByteOffset += 4) { - const Color4uint8& s = *reinterpret_cast(src + srcByteOffset); - dst[dstIndex] = Color4(s); - } - srcByteOffset += srcRowPadBytes; - } -} - -// RGB32F -> -static void rgb32f_to_rgba32f(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - debugAssertM(srcRowPadBits % 8 == 0, "Source row padding must be a multiple of 8 bits for this format"); - - int dstIndex = 0; - int srcByteOffset = 0; - int srcRowPadBytes = srcRowPadBits / 8; - Color4* dst = static_cast(dstBytes[0]); - const uint8* src = static_cast(srcBytes[0]); - - for (int y = 0; y < srcHeight; ++y) { - if (invertY) { - dstIndex = srcWidth * (srcHeight - 1 - y); - } - - for (int x = 0; x < srcWidth; ++x, ++dstIndex, srcByteOffset += 3 * sizeof(float)) { - const Color3& s = *reinterpret_cast(src + srcByteOffset); - dst[dstIndex] = Color4(Color3(s), 1.0f); - } - srcByteOffset += srcRowPadBytes; - } -} - -// RGBA32F -> -static void rgba32f_to_rgb8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - debugAssertM(dstRowPadBits % 8 == 0, "Destination row padding must be a multiple of 8 bits for this format"); - - int srcIndex = 0; - int dstByteOffset = 0; - int dstRowPadBytes = dstRowPadBits / 8; - uint8* dst = static_cast(dstBytes[0]); - const Color4* src = static_cast(srcBytes[0]); - - for (int y = 0; y < srcHeight; ++y) { - if (invertY) { - srcIndex = srcWidth * (srcHeight - y - 1); - } - - for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 3) { - Color3uint8& d = *reinterpret_cast(dst + dstByteOffset); - const Color4& s = src[srcIndex]; - - d = Color3uint8(s.rgb()); - } - dstByteOffset += dstRowPadBytes; - } -} - -static void rgba32f_to_rgba8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - debugAssertM(dstRowPadBits % 8 == 0, "Destination row padding must be a multiple of 8 bits for this format"); - - int srcIndex = 0; - int dstByteOffset = 0; - int dstRowPadBytes = dstRowPadBits / 8; - uint8* dst = static_cast(dstBytes[0]); - const Color4* src = static_cast(srcBytes[0]); - - for (int y = 0; y < srcHeight; ++y) { - if (invertY) { - srcIndex = srcWidth * (srcHeight - 1 - y); - } - for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 4) { - Color4uint8& d = *reinterpret_cast(dst + dstByteOffset); - const Color4& s = src[srcIndex]; - - d = Color4uint8(s); - } - dstByteOffset += dstRowPadBytes; - } -} - -static void rgba32f_to_bgr8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - debugAssertM(dstRowPadBits % 8 == 0, "Destination row padding must be a multiple of 8 bits for this format"); - - int srcIndex = 0; - int dstByteOffset = 0; - int dstRowPadBytes = dstRowPadBits / 8; - uint8* dst = static_cast(dstBytes[0]); - const Color4* src = static_cast(srcBytes[0]); - - for (int y = 0; y < srcHeight; ++y) { - if (invertY) { - srcIndex = srcWidth * (srcHeight - y - 1); - } - - for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 3) { - Color3uint8& d = *reinterpret_cast(dst + dstByteOffset); - const Color4& s = src[srcIndex]; - - d = Color3uint8(s.rgb()).bgr(); - } - dstByteOffset += dstRowPadBytes; - } -} - -static void rgba32f_to_rgb32f(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - debugAssertM(dstRowPadBits % 8 == 0, "Destination row padding must be a multiple of 8 bits for this format"); - - int srcIndex = 0; - int dstByteOffset = 0; - int dstRowPadBytes = dstRowPadBits / 8; - uint8* dst = static_cast(dstBytes[0]); - const Color4* src = static_cast(srcBytes[0]); - - for (int y = 0; y < srcHeight; ++y) { - if (invertY) { - srcIndex = srcWidth * (srcHeight - 1 - y); - } - for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 3 * sizeof(float)) { - Color3& d = *reinterpret_cast(dst + dstByteOffset); - const Color4& s = src[srcIndex]; - d = Color3(s); - } - dstByteOffset += dstRowPadBytes; - } -} - -// ******************* -// RGB <-> YUV color space conversions -// ******************* - -static uint32 blendPixels(uint32 pixel1, uint32 pixel2) { - static const uint32 rbMask = 0x00FF00FF; - static const uint32 agMask = 0xFF00FF00; - - // Compute two color channels at a time. Use >> 1 for fast division by two - // Using alternating color channels prevents overflow - const uint32 rb = ((pixel1 & rbMask) + (pixel2 & rbMask)) >> 1; - - // Shift first to avoid overflow in alpha channel - const uint32 ag = (((pixel1 & agMask) >> 1) + ((pixel2 & agMask) >> 1)); - - return ((rb & rbMask) | (ag & agMask)); -} - -#define PIXEL_RGB8_TO_YUV_Y(r, g, b) static_cast(iClamp(((66 * r + 129 * g + 25 * b + 128) >> 8) + 16, 0, 255)) -#define PIXEL_RGB8_TO_YUV_U(r, g, b) static_cast(iClamp(((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128, 0, 255)) -#define PIXEL_RGB8_TO_YUV_V(r, g, b) static_cast(iClamp(((112 * r - 94 * g - 18 * b + 128) >> 8) + 128, 0, 255)) - -static void rgb8_to_yuv420p(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format"); - debugAssertM((srcWidth % 2 == 0) && (srcHeight % 2 == 0), "Source width and height must be a multiple of two"); - - const Color3uint8* src = static_cast(srcBytes[0]); - - uint8* dstY = static_cast(dstBytes[0]); - uint8* dstU = static_cast(dstBytes[1]); - uint8* dstV = static_cast(dstBytes[2]); - - for (int y = 0; y < srcHeight; y += 2) { - for (int x = 0; x < srcWidth; x += 2) { - - // convert 4-pixel block at a time - int srcPixelOffset0 = y * srcWidth + x; - int srcPixelOffset1 = srcPixelOffset0 + 1; - int srcPixelOffset2 = srcPixelOffset0 + srcWidth; - int srcPixelOffset3 = srcPixelOffset2 + 1; - - int yIndex = y * srcWidth + x; - - dstY[yIndex] = PIXEL_RGB8_TO_YUV_Y(src[srcPixelOffset0].r, src[srcPixelOffset0].g, src[srcPixelOffset0].b); - dstY[yIndex + 1] = PIXEL_RGB8_TO_YUV_Y(src[srcPixelOffset1].r, src[srcPixelOffset1].g, src[srcPixelOffset1].b); - - yIndex += srcWidth; - dstY[yIndex] = PIXEL_RGB8_TO_YUV_Y(src[srcPixelOffset2].r, src[srcPixelOffset2].g, src[srcPixelOffset2].b); - dstY[yIndex + 1] = PIXEL_RGB8_TO_YUV_Y(src[srcPixelOffset3].r, src[srcPixelOffset3].g, src[srcPixelOffset3].b); - - uint32 blendedPixel = blendPixels(src[srcPixelOffset0].asUInt32(), src[srcPixelOffset2].asUInt32()); - Color3uint8 uvSrcColor = Color3uint8::fromARGB(blendedPixel); - - int uvIndex = y / 2 * srcWidth / 2 + x / 2; - dstU[uvIndex] = PIXEL_RGB8_TO_YUV_U(uvSrcColor.r, uvSrcColor.g, uvSrcColor.b); - dstV[uvIndex] = PIXEL_RGB8_TO_YUV_V(uvSrcColor.r, uvSrcColor.g, uvSrcColor.b); - } - } -} - -static void rgb8_to_yuv422(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format"); - debugAssertM((srcWidth % 2 == 0), "Source width must be a multiple of two"); - - const Color3uint8* src = static_cast(srcBytes[0]); - - uint8* dst = static_cast(dstBytes[0]); - - for (int y = 0; y < srcHeight; ++y) { - for (int x = 0; x < srcWidth; x += 2) { - - // convert 2-pixel horizontal block at a time - int srcIndex = y * srcWidth + x; - int dstIndex = srcIndex * 2; - - uint32 blendedPixel = blendPixels(src[srcIndex].asUInt32(), src[srcIndex + 1].asUInt32()); - Color3uint8 uvSrcColor = Color3uint8::fromARGB(blendedPixel); - - dst[dstIndex] = PIXEL_RGB8_TO_YUV_Y(src[srcIndex].r, src[srcIndex].g, src[srcIndex].b); - - dst[dstIndex + 1] = PIXEL_RGB8_TO_YUV_U(uvSrcColor.r, uvSrcColor.g, uvSrcColor.b); - - dst[dstIndex + 2] = PIXEL_RGB8_TO_YUV_Y(src[srcIndex + 1].r, src[srcIndex + 1].g, src[srcIndex + 1].b); - - dst[dstIndex + 3] = PIXEL_RGB8_TO_YUV_V(uvSrcColor.r, uvSrcColor.g, uvSrcColor.b); - - } - } -} - -static void rgb8_to_yuv444(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format"); - - const Color3uint8* src = static_cast(srcBytes[0]); - - Color3uint8* dst = static_cast(dstBytes[0]); - - for (int y = 0; y < srcHeight; ++y) { - for (int x = 0; x < srcWidth; ++x) { - - // convert 1-pixels at a time - int index = y * srcWidth + x; - uint8 y = PIXEL_RGB8_TO_YUV_Y(src[index].r, src[index].g, src[index].b); - uint8 u = PIXEL_RGB8_TO_YUV_U(src[index].r, src[index].g, src[index].b); - uint8 v = PIXEL_RGB8_TO_YUV_V(src[index].r, src[index].g, src[index].b); - - dst[index].r = y; - dst[index].g = u; - dst[index].b = v; - } - } -} - - -#define PIXEL_YUV_TO_RGB8_R(y, u, v) static_cast(iClamp((298 * (y - 16) + 409 * (v - 128) + 128) >> 8, 0, 255)) -#define PIXEL_YUV_TO_RGB8_G(y, u, v) static_cast(iClamp((298 * (y - 16) - 100 * (u - 128) - 208 * (v - 128) + 128) >> 8, 0, 255)) -#define PIXEL_YUV_TO_RGB8_B(y, u, v) static_cast(iClamp((298 * (y - 16) + 516 * (u - 128) + 128) >> 8, 0, 255)) - -static void yuv420p_to_rgb8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format"); - debugAssertM((srcWidth % 2 == 0) && (srcHeight % 2 == 0), "Source width and height must be a multiple of two"); - - const uint8* srcY = static_cast(srcBytes[0]); - const uint8* srcU = static_cast(srcBytes[1]); - const uint8* srcV = static_cast(srcBytes[2]); - - Color3uint8* dst = static_cast(dstBytes[0]); - - for (int y = 0; y < srcHeight; ++y) { - for (int x = 0; x < srcWidth; x += 2) { - - // convert to two rgb pixels in a row - Color3uint8* rgb = &dst[y * srcWidth + x]; - - int yOffset = y * srcWidth + x; - int uvOffset = y / 2 * srcWidth / 2 + x / 2; - - rgb->r = PIXEL_YUV_TO_RGB8_R(srcY[yOffset], srcU[uvOffset], srcV[uvOffset]); - rgb->g = PIXEL_YUV_TO_RGB8_G(srcY[yOffset], srcU[uvOffset], srcV[uvOffset]); - rgb->b = PIXEL_YUV_TO_RGB8_B(srcY[yOffset], srcU[uvOffset], srcV[uvOffset]); - - rgb += 1; - rgb->r = PIXEL_YUV_TO_RGB8_R(srcY[yOffset + 1], srcU[uvOffset], srcV[uvOffset]); - rgb->g = PIXEL_YUV_TO_RGB8_G(srcY[yOffset + 1], srcU[uvOffset], srcV[uvOffset]); - rgb->b = PIXEL_YUV_TO_RGB8_B(srcY[yOffset + 1], srcU[uvOffset], srcV[uvOffset]); - } - } -} - -static void yuv422_to_rgb8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format"); - debugAssertM((srcWidth % 2 == 0), "Source width must be a multiple of two"); - - const uint8* src = static_cast(srcBytes[0]); - - Color3uint8* dst = static_cast(dstBytes[0]); - - for (int y = 0; y < srcHeight; ++y) { - for (int x = 0; x < srcWidth; x += 2) { - - // convert to two rgb pixels in a row - Color3uint8* rgb = &dst[y * srcWidth + x]; - - int srcIndex = (y * srcWidth + x) * 2; - uint8 y = src[srcIndex]; - uint8 u = src[srcIndex + 1]; - uint8 y2 = src[srcIndex + 2]; - uint8 v = src[srcIndex + 3]; - - rgb->r = PIXEL_YUV_TO_RGB8_R(y, u, v); - rgb->g = PIXEL_YUV_TO_RGB8_G(y, u, v); - rgb->b = PIXEL_YUV_TO_RGB8_B(y, u, v); - - rgb += 1; - rgb->r = PIXEL_YUV_TO_RGB8_R(y2, u, v); - rgb->g = PIXEL_YUV_TO_RGB8_G(y2, u, v); - rgb->b = PIXEL_YUV_TO_RGB8_B(y2, u, v); - } - } -} - -static void yuv444_to_rgb8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format"); - - const Color3uint8* src = static_cast(srcBytes[0]); - - Color3uint8* dst = static_cast(dstBytes[0]); - - for (int y = 0; y < srcHeight; ++y) { - for (int x = 0; x < srcWidth; ++x) { - - // convert to one rgb pixels at a time - int index = y * srcWidth + x; - Color3uint8* rgb = &dst[index]; - - rgb->r = PIXEL_YUV_TO_RGB8_R(src[index].r, src[index].g, src[index].b); - rgb->g = PIXEL_YUV_TO_RGB8_G(src[index].r, src[index].g, src[index].b); - rgb->b = PIXEL_YUV_TO_RGB8_B(src[index].r, src[index].g, src[index].b); - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////// -// -// Bayer conversions -// - -// There are two kinds of rows (GR and BG). -// In each row, there are two kinds of pixels (G/R, B/G). -// We express the four kinds of INPUT pixels as: -// GRG, GRG, BGB, BGG -// -// There are three kinds of OUTPUT pixels: R, G, B. -// Thus there are nominally 12 different I/O combinations, -// but several are impulses because needed output at that -// location *is* the input (e.g., G_GRG and G_BGG). -// -// The following 5x5 row-major filters are named as output_input. - -// Green -static const float G_GRR[5][5] = - {{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}, - { 0.0f, 0.0f, 2.0f, 0.0f, 0.0f}, - { -1.0f, 2.0f, 4.0f, 2.0f, -1.0f}, - { 0.0f, 0.0f, 2.0f, 0.0f, 0.0f}, - { 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}}; - -static const float G_BGB[5][5] = - {{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}, - { 0.0f, 0.0f, 2.0f, 0.0f, 0.0f}, - { -1.0f, 2.0f, 4.0f, 2.0f, -1.0f}, - { 0.0f, 0.0f, 2.0f, 0.0f, 0.0f}, - { 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}}; - -// Red -//(the caption in the paper is wrong for this case: -// "R row B column really means R row G column" -static const float R_GRG[5][5] = - {{ 0.0f, 0.0f, 0.5f, 0.0f, 0.0f}, - { 0.0f, -1.0f, 0.0f, -1.0f, 0.0f}, - { -1.0f, 4.0f, 5.0f, 4.0f, -1.0f}, - { 0.0f, -1.0f, 0.0f, -1.0f, 0.0f}, - { 0.0f, 0.0f, 0.5f, 0.0f, 0.0f}}; - -static const float R_BGG[5][5] = - {{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}, - { 0.0f, -1.0f, 4.0f, -1.0f, 0.0f}, - { 0.5f, 0.0f, 5.0f, 0.0f, 0.5f}, - { 0.0f, -1.0f, 4.0f, -1.0f, 0.0f}, - { 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}}; - -static const float R_BGB[5][5] = - {{ 0.0f, 0.0f, -3.0f/2.0f, 0.0f, 0.0f}, - { 0.0f, 2.0f, 0.0f, 2.0f, 0.0f}, - {-3.0f/2.0f, 0.0f, 6.0f, 0.0f, -3.0f/2.0f}, - { 0.0f, 2.0f, 0.0f, 2.0f, 0.0f}, - { 0.0f, 0.0f, -3.0f/2.0f, 0.0f, 0.0f}}; - - -// Blue -//(the caption in the paper is wrong for this case: -// "B row R column really means B row G column") -#define B_BGG R_GRG -#define B_GRG R_BGG -#define B_GRR R_BGB - -// ===================================================================== -// Helper methods -// ===================================================================== - - -/** Applies a 5x5 filter to monochrome image I (wrapping at the boundaries) */ -static uint8 applyFilter(const uint8* I, - int x, - int y, - int w, - int h, - const float filter[5][5]) { - - debugAssert(isEven(w)); - debugAssert(isEven(h)); - - float sum = 0.0f; - float denom = 0.0f; - - for (int dy = 0; dy < 5; ++dy) { - int offset = ((y + dy + h - 2) % h) * w; - - for (int dx = 0; dx < 5; ++dx) { - float f = filter[dy][dx]; - sum += f * I[((x + dx + w - 2) % w) + offset]; - denom += f; - } - } - - return (uint8)iClamp(iRound(sum / denom), 0, 255); -} - -/** Helper method for Bayer grbg and bggr --> rgb8 */ -static void swapRedAndBlue(int N, Color3uint8* out) { - for (int i = N - 1; i >= 0; --i) { - uint8 tmp = out[i].r; - out[i].r = out[i].b; - out[i].b = tmp; - } -} - -// RGB -> BAYER color space - -// ===================================================================== -// rgb8 --> bayer helpers -// ===================================================================== -static void rgb8_to_bayer_rggb8(const int w, const int h, - const uint8* src, uint8* dst) { - Color3uint8* srcColor = (Color3uint8*)src; - Color1uint8* dstColor = (Color1uint8*)dst; - - // Top row pixels - for (int y = 0; y < h - 1; y += 2) { - int offset = y * w; - - // Top left pixels - for(int x = 0; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].r); - } - - // Top right pixels - for(int x = 1; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].g); - } - } - - // Bottom row pixels - for (int y = 1; y < h - 1; y += 2) { - int offset = y * w; - - // Bottom left pixels - for (int x = 0; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].g); - } - - // Bottom right pixels - for (int x = 1; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].b); - } - } -} - - -static void rgb8_to_bayer_grbg8(const int w, const int h, - const uint8* src, uint8* dst) { - Color3uint8* srcColor = (Color3uint8*)src; - Color1uint8* dstColor = (Color1uint8*)dst; - - // Top row pixels - for (int y = 0; y < h - 1; y += 2) { - int offset = y * w; - - // Top left pixels - for (int x = 0; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].g); - } - - // Top right pixels - for (int x = 1; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].r); - } - } - - // Bottom row pixels - for (int y = 1; y < h - 1; y += 2) { - int offset = y * w; - - // Bottom left pixels - for (int x = 0; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].b); - } - - // Bottom right pixels - for (int x = 1; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].g); - } - } -} - - -static void rgb8_to_bayer_bggr8(const int w, const int h, - const uint8* src, uint8* dst) { - Color3uint8* srcColor = (Color3uint8*)src; - Color1uint8* dstColor = (Color1uint8*)dst; - - // Top row pixels - for (int y = 0; y < h - 1; y += 2) { - int offset = y * w; - - // Top left pixels - for (int x = 0; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].b); - } - - // Top right pixels - for (int x = 1; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].g); - } - } - - // Bottom row pixels - for (int y = 1; y < h - 1; y += 2) { - int offset = y * w; - - // Bottom left pixels - for(int x = 0; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].g); - } - - // Bottom right pixels - for(int x = 1; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].r); - } - } -} - - -static void rgb8_to_bayer_gbrg8(const int w, const int h, - const uint8* src, uint8* dst) { - Color3uint8* srcColor = (Color3uint8*)src; - Color1uint8* dstColor = (Color1uint8*)dst; - - // Top row pixels - for(int y = 0; y < h - 1; y += 2) { - int offset = y * w; - - // Top left pixels - for(int x = 0; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].g); - } - - // Top right pixels - for(int x = 1; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].b); - } - } - - // Bottom row pixels - for(int y = 1; y < h - 1; y += 2) { - int offset = y * w; - - // Bottom left pixels - for(int x = 0; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].r); - } - - // Bottom right pixels - for(int x = 1; x < w - 1; x += 2) { - dstColor[x + offset] = Color1(srcColor[x + offset].g); - } - } -} - -// ===================================================================== -// rgba32f (-->rgb8) --> bayer converter implementations -// ===================================================================== -static void rgba32f_to_bayer_rggb8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - Array tmp; - tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8))); - - rgba32f_to_rgb8(srcBytes, srcWidth, srcHeight, ImageFormat::RGBA32F(), 0, tmp, ImageFormat::RGB8(), 0, invertY, bayerAlg); - rgb8_to_bayer_rggb8(srcWidth, srcHeight, static_cast(tmp[0]), static_cast(dstBytes[0])); - - System::free(tmp[0]); -} - -static void rgba32f_to_bayer_gbrg8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - Array tmp; - tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8))); - - rgba32f_to_rgb8(srcBytes, srcWidth, srcHeight, ImageFormat::RGBA32F(), 0, tmp, ImageFormat::RGB8(), 0, invertY, bayerAlg); - rgb8_to_bayer_grbg8(srcWidth, srcHeight, static_cast(tmp[0]), static_cast(dstBytes[0])); - - System::free(tmp[0]); -} - -static void rgba32f_to_bayer_grbg8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - Array tmp; - tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8))); - - rgba32f_to_rgb8(srcBytes, srcWidth, srcHeight, ImageFormat::RGBA32F(), 0, tmp, ImageFormat::RGB8(), 0, invertY, bayerAlg); - rgb8_to_bayer_gbrg8(srcWidth, srcHeight, static_cast(tmp[0]), static_cast(dstBytes[0])); - - System::free(tmp[0]); -} - -static void rgba32f_to_bayer_bggr8(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - Array tmp; - tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8))); - - rgba32f_to_rgb8(srcBytes, srcWidth, srcHeight, ImageFormat::RGBA32F(), 0, tmp, ImageFormat::RGB8(), 0, invertY, bayerAlg); - rgb8_to_bayer_bggr8(srcWidth, srcHeight, static_cast(tmp[0]), static_cast(dstBytes[0])); - - System::free(tmp[0]); -} - -// BAYER -> RGB color space - -// ===================================================================== -// bayer --> rgb8 helpers -// ===================================================================== -static void bayer_rggb8_to_rgb8_mhc(int w, int h, - const uint8* in, uint8* _out) { - debugAssert(in != _out); - - Color3uint8* out = (Color3uint8*)_out; - - for (int y = 0; y < h; ++y) { - - // Row beginning in the input array. - int offset = y * w; - - // RG row - for (int x = 0; x < w; ++x, ++out) { - // R pixel - { - out->r = in[x + offset]; - out->g = applyFilter(in, x, y, w, h, G_GRR); - out->b = applyFilter(in, x, y, w, h, B_GRR); - } - ++x; ++out; - - // G pixel - { - out->r = applyFilter(in, x, y, w, h, R_GRG); - out->g = in[x + offset]; - out->b = applyFilter(in, x, y, w, h, B_GRG); - } - } - - ++y; - offset += w; - - // GB row - for (int x = 0; x < w; ++x, ++out) { - // G pixel - { - out->r = applyFilter(in, x, y, w, h, R_BGG); - out->g = in[x + offset]; - out->b = applyFilter(in, x, y, w, h, B_BGG); - } - ++x; ++out; - - // B pixel - { - out->r = applyFilter(in, x, y, w, h, R_BGB); - out->g = applyFilter(in, x, y, w, h, G_BGB); - out->b = in[x + offset]; - } - } - } -} - - - -static void bayer_gbrg8_to_rgb8_mhc(int w, int h, - const uint8* in, uint8* _out) { - - debugAssert(in != _out); - - Color3uint8* out = (Color3uint8*)_out; - - for (int y = 0; y < h; ++y) { - - // Row beginning in the input array. - int offset = y * w; - - // GB row - for (int x = 0; x < w; ++x, ++out) { - // G pixel - { - out->r = applyFilter(in, x, y, w, h, R_BGG); - out->g = in[x + offset]; - out->b = applyFilter(in, x, y, w, h, B_BGG); - } - ++x; ++out; - - // B pixel - { - out->r = applyFilter(in, x, y, w, h, R_BGB); - out->g = applyFilter(in, x, y, w, h, G_BGB); - out->b = in[x + offset]; - } - } - } -} - - -static void bayer_grbg8_to_rgb8_mhc(int w, int h, - const uint8* in, uint8* _out) { - // Run the equivalent function for red - bayer_gbrg8_to_rgb8_mhc(w, h, in, _out); - - // Now swap red and blue - swapRedAndBlue(w * h, (Color3uint8*)_out); -} - - -static void bayer_bggr8_to_rgb8_mhc(int w, int h, - const uint8* in, uint8* _out) { - // Run the equivalent function for red - bayer_rggb8_to_rgb8_mhc(w, h, in, _out); - - // Now swap red and blue - swapRedAndBlue(w * h, (Color3uint8*)_out); -} - -// ===================================================================== -// bayer (--> rgb8) --> rgba32f converter implementations -// ===================================================================== -static void bayer_rggb8_to_rgba32f(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - Array tmp; - tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8))); - - bayer_rggb8_to_rgb8_mhc(srcWidth, srcHeight, static_cast(srcBytes[0]), static_cast(tmp[0])); - rgb8_to_rgba32f(reinterpret_cast&>(tmp), srcWidth, srcHeight, ImageFormat::RGB8(), 0, dstBytes, ImageFormat::RGBA32F(), 0, invertY, bayerAlg); - - System::free(tmp[0]); -} - -static void bayer_gbrg8_to_rgba32f(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - Array tmp; - tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8))); - - bayer_grbg8_to_rgb8_mhc(srcWidth, srcHeight, static_cast(srcBytes[0]), static_cast(tmp[0])); - rgb8_to_rgba32f(reinterpret_cast&>(tmp), srcWidth, srcHeight, ImageFormat::RGB8(), 0, dstBytes, ImageFormat::RGBA32F(), 0, invertY, bayerAlg); - - System::free(tmp[0]); -} - -static void bayer_grbg8_to_rgba32f(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - Array tmp; - tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8))); - - bayer_gbrg8_to_rgb8_mhc(srcWidth, srcHeight, static_cast(srcBytes[0]), static_cast(tmp[0])); - rgb8_to_rgba32f(reinterpret_cast&>(tmp), srcWidth, srcHeight, ImageFormat::RGB8(), 0, dstBytes, ImageFormat::RGBA32F(), 0, invertY, bayerAlg); - - System::free(tmp[0]); -} - -static void bayer_bggr8_to_rgba32f(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) { - Array tmp; - tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8))); - - bayer_bggr8_to_rgb8_mhc(srcWidth, srcHeight, static_cast(srcBytes[0]), static_cast(tmp[0])); - rgb8_to_rgba32f(reinterpret_cast&>(tmp), srcWidth, srcHeight, ImageFormat::RGB8(), 0, dstBytes, ImageFormat::RGBA32F(), 0, invertY, bayerAlg); - - System::free(tmp[0]); -} - - - - - - // TODO: The following region is commented out because so far - // those conversions are not used anywhere else. Until it is - // decided that such conversions are not needed, this region - // remains commented out. - - -// // ===================================================================== -// // bayer --> bgr8 -// // ===================================================================== - -// static void bayer_rggb8_to_bgr8_mhc(int w, int h, -// const uint8* in, uint8* _out) { -// debugAssert(in != _out); - -// Color3uint8* out = (Color3uint8*)_out; - -// for (int y = 0; y < h; ++y) { - -// // Row beginning in the input array. -// int offset = y * w; - -// // RG row -// for (int x = 0; x < w; ++x, ++out) { -// // R pixel -// { -// out->b = in[x + offset]; -// out->g = applyFilter(in, x, y, w, h, G_GRR); -// out->r = applyFilter(in, x, y, w, h, B_GRR); -// } -// ++x; ++out; - -// // G pixel -// { -// out->b = applyFilter(in, x, y, w, h, R_GRG); -// out->g = in[x + offset]; -// out->r = applyFilter(in, x, y, w, h, B_GRG); -// } -// } - -// ++y; -// offset += w; - -// // GB row -// for (int x = 0; x < w; ++x, ++out) { -// // G pixel -// { -// out->b = applyFilter(in, x, y, w, h, R_BGG); -// out->g = in[x + offset]; -// out->r = applyFilter(in, x, y, w, h, B_BGG); -// } -// ++x; ++out; - -// // B pixel -// { -// out->b = applyFilter(in, x, y, w, h, R_BGB); -// out->g = applyFilter(in, x, y, w, h, G_BGB); -// out->r = in[x + offset]; -// } -// } -// } -// } - - -// static void bayer_gbrg8_to_bgr8_mhc(int w, int h, -// const uint8* in, uint8* _out) { - -// debugAssert(in != _out); - -// Color3uint8* out = (Color3uint8*)_out; - -// for (int y = 0; y < h; ++y) { - -// // Row beginning in the input array. -// int offset = y * w; - -// // GB row -// for (int x = 0; x < srcWidth; ++x, ++out) { -// // G pixel -// { -// out->b = applyFilter(in, x, y, w, h, R_BGG); -// out->g = in[x + offset]; -// out->r = applyFilter(in, x, y, w, h, B_BGG); -// } -// ++x; ++out; - -// // B pixel -// { -// out->b = applyFilter(in, x, y, w, h, R_BGB); -// out->g = applyFilter(in, x, y, w, h, G_BGB); -// out->r = in[x + offset]; -// } -// } -// } -// } - -// static void bayer_grbg8_to_bgr8_mhc(int w, int h, -// const uint8* in, uint8* _out) { -// // Run the equivalent function for red -// bayer_gbrg8_to_bgr8_mhc(w, h, in, _out); - -// // Now swap red and blue -// swapRedAndBlue(srcWidth * h, (Color3uint8*)_out); -// } - -// static void bayer_bggr8_to_bgr8_mhc(int w, int h, -// const uint8* in, uint8* _out) { -// // Run the equivalent function for red -// bayer_rggb8_to_bgr8_mhc(w, h, in, _out); - -// // Now swap red and blue -// swapRedAndBlue(srcWidth * h, (Color3uint8*)_out); -// } - - - -/////////////////////////////////////////////////// - -} // namespace G3D diff --git a/externals/g3dlite/G3D.lib/source/Line.cpp b/externals/g3dlite/G3D.lib/source/Line.cpp deleted file mode 100644 index 195ae7197f2..00000000000 --- a/externals/g3dlite/G3D.lib/source/Line.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/** - @file Line.cpp - - Line class - - @maintainer Morgan McGuire, graphics3d.com - - @created 2001-06-02 - @edited 2006-01-28 - */ - -#include "G3D/Line.h" -#include "G3D/Plane.h" - -namespace G3D { - -Vector3 Line::intersection(const Plane& plane) const { - float d; - Vector3 normal = plane.normal(); - plane.getEquation(normal, d); - float rate = _direction.dot(normal); - - if (rate == 0) { - - return Vector3::inf(); - - } else { - float t = -(d + _point.dot(normal)) / rate; - - return _point + _direction * t; - } -} - - -Line::Line(class BinaryInput& b) { - deserialize(b); -} - - -void Line::serialize(class BinaryOutput& b) const { - _point.serialize(b); - _direction.serialize(b); -} - - -void Line::deserialize(class BinaryInput& b) { - _point.deserialize(b); - _direction.deserialize(b); -} - - -Vector3 Line::closestPoint(const Vector3& pt) const { - float t = _direction.dot(pt - _point); - return _point + _direction * t; -} - - -Vector3 Line::point() const { - return _point; -} - - -Vector3 Line::direction() const { - return _direction; -} - - -Vector3 Line::closestPoint(const Line& B, float& minDist) const { - const Vector3& P1 = _point; - const Vector3& U1 = _direction; - - Vector3 P2 = B.point(); - Vector3 U2 = B.direction(); - - const Vector3& P21 = P2 - P1; - const Vector3& M = U2.cross(U1); - float m2 = M.length(); - - Vector3 R = P21.cross(M) / m2; - - float t1 = R.dot(U2); - - minDist = abs(P21.dot(M)) / sqrt(m2); - - return P1 + t1 * U1; -} - -} - diff --git a/externals/g3dlite/G3D.lib/source/LineSegment.cpp b/externals/g3dlite/G3D.lib/source/LineSegment.cpp deleted file mode 100644 index 44dfcb48bc1..00000000000 --- a/externals/g3dlite/G3D.lib/source/LineSegment.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/** - @file LineSegment.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-02-08 - @edited 2008-02-02 - */ - -#include "G3D/platform.h" -#include "G3D/LineSegment.h" -#include "G3D/Sphere.h" -#include "G3D/debug.h" - -namespace G3D { - - -Vector3 LineSegment::closestPoint(const Vector3& p) const { - - // The vector from the end of the capsule to the point in question. - Vector3 v(p - _point); - - // Projection of v onto the line segment scaled by - // the length of direction. - float t = direction.dot(v); - - // Avoid some square roots. Derivation: - // t/direction.length() <= direction.length() - // t <= direction.squaredLength() - - if ((t >= 0) && (t <= direction.squaredMagnitude())) { - - // The point falls within the segment. Normalize direction, - // divide t by the length of direction. - return _point + direction * t / direction.squaredMagnitude(); - - } else { - - // The point does not fall within the segment; see which end is closer. - - // Distance from 0, squared - float d0Squared = v.squaredMagnitude(); - - // Distance from 1, squared - float d1Squared = (v - direction).squaredMagnitude(); - - if (d0Squared < d1Squared) { - - // Point 0 is closer - return _point; - - } else { - - // Point 1 is closer - return _point + direction; - - } - } - -} - -Vector3 LineSegment::point(int i) const { - switch (i) { - case 0: - return _point; - - case 1: - return _point + direction; - - default: - debugAssertM(i == 0 || i == 1, "Argument to point must be 0 or 1"); - return _point; - } -} - - -bool LineSegment::intersectsSolidSphere(const class Sphere& s) const { - return distanceSquared(s.center) <= square(s.radius); -} - - -LineSegment::LineSegment(class BinaryInput& b) { - deserialize(b); -} - - -void LineSegment::serialize(class BinaryOutput& b) const { - _point.serialize(b); - direction.serialize(b); -} - - -void LineSegment::deserialize(class BinaryInput& b) { - _point.deserialize(b); - direction.deserialize(b); -} - - -Vector3 LineSegment::randomPoint() const { - return _point + uniformRandom(0, 1) * direction; -} - - -///////////////////////////////////////////////////////////////////////////////////// - -LineSegment2D LineSegment2D::fromTwoPoints(const Vector2& p0, const Vector2& p1) { - LineSegment2D s; - s.m_origin = p0; - s.m_direction = p1 - p0; - s.m_length = s.m_direction.length(); - return s; -} - - -Vector2 LineSegment2D::point(int i) const { - debugAssert(i == 0 || i == 1); - if (i == 0) { - return m_origin; - } else { - return m_direction + m_origin; - } -} - - -Vector2 LineSegment2D::closestPoint(const Vector2& Q) const { - // Two constants that appear in the result - const Vector2 k1(m_origin - Q); - const Vector2& k2 = m_direction; - - if (fuzzyEq(m_length, 0)) { - // This line segment has no length - return m_origin; - } - - // Time [0, 1] at which we hit the closest point travelling from p0 to p1. - // Derivation can be obtained by minimizing the expression - // ||P0 + (P1 - P0)t - Q||. - const float t = -k1.dot(k2) / (m_length * m_length); - - if (t < 0) { - // Clipped to low end point - return m_origin; - } else if (t > 1) { - // Clipped to high end point - return m_origin + m_direction; - } else { - // Subsitute into the line equation to find - // the point on the segment. - return m_origin + k2 * t; - } -} - - -float LineSegment2D::distance(const Vector2& p) const { - Vector2 closest = closestPoint(p); - return (closest - p).length(); -} - - -float LineSegment2D::length() const { - return m_length; -} - - -Vector2 LineSegment2D::intersection(const LineSegment2D& other) const { - - if ((m_origin == other.m_origin) || - (m_origin == other.m_origin + other.m_direction)) { - return m_origin; - } - - if (m_origin + m_direction == other.m_origin) { - return other.m_origin; - } - - // Note: Now that we've checked the endpoints, all other parallel lines can now be assumed - // to not intersect (within numerical precision) - - Vector2 dir1 = m_direction; - Vector2 dir2 = other.m_direction; - Vector2 origin1 = m_origin; - Vector2 origin2 = other.m_origin; - - if (dir1.x == 0) { - // Avoid an upcoming divide by zero - dir1 = dir1.yx(); - dir2 = dir2.yx(); - origin1 = origin1.yx(); - origin2 = origin2.yx(); - } - - // t1 = ((other.m_origin.x - m_origin.x) + other.m_direction.x * t2) / m_direction.x - // - // ((other.m_origin.x - m_origin.x) + other.m_direction.x * t2) * m_direction.y / m_direction.x = - // (other.m_origin.y - m_origin.y) + other.m_direction.y * t2 - // - // m = m_direction.y / m_direction.x - // d = other.m_origin - m_origin - // - // (d.x + other.m_direction.x * t2) * m = d.y + other.m_direction.y * t2 - // - // d.x * m + other.m_direction.x * m * t2 = d.y + other.m_direction.y * t2 - // - // d.x * m - d.y = (other.m_direction.y - other.m_direction.x * m) * t2 - // - // (d.x * m - d.y) / (other.m_direction.y - other.m_direction.x * m) = t2 - // - - Vector2 d = origin2 - origin1; - float m = dir1.y / dir1.x; - - float t2 = (d.x * m - d.y) / (dir2.y - dir2.x * m); - if (! isFinite(t2)) { - // Parallel lines: no intersection - return Vector2::inf(); - } - - if ((t2 < 0.0f) || (t2 > 1.0f)) { - // Intersection occurs past the end of the line segments - return Vector2::inf(); - } - - float t1 = (d.x + dir2.x * t2) / dir1.x; - if ((t1 < 0.0f) || (t1 > 1.0f)) { - // Intersection occurs past the end of the line segments - return Vector2::inf(); - } - - // Return the intersection point (computed from non-transposed - // variables even if we flipped above) - return m_origin + m_direction * t1; - -} - -} - diff --git a/externals/g3dlite/G3D.lib/source/Log.cpp b/externals/g3dlite/G3D.lib/source/Log.cpp deleted file mode 100644 index 13cea7a31f0..00000000000 --- a/externals/g3dlite/G3D.lib/source/Log.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/** - @file Log.cpp - - @maintainer Morgan McGuire, morgan@graphics3d.com - @created 2001-08-04 - @edited 2005-07-01 - */ - -#include "G3D/platform.h" -#include "G3D/Log.h" -#include "G3D/format.h" -#include "G3D/Array.h" -#include "G3D/fileutils.h" -#include - -#ifdef G3D_WIN32 - #include -#else - #include -#endif - -namespace G3D { - -void logPrintf(const char* fmt, ...) { - va_list arg_list; - va_start(arg_list, fmt); - Log::common()->vprintf(fmt, arg_list); - va_end(arg_list); -} - - -Log* Log::commonLog = NULL; - -Log::Log(const std::string& filename, int stripFromStackBottom) : - stripFromStackBottom(stripFromStackBottom) { - - this->filename = filename; - - logFile = fopen(filename.c_str(), "w"); - - if (logFile == NULL) { - std::string drive, base, ext; - Array path; - parseFilename(filename, drive, path, base, ext); - std::string logName = base + ((ext != "") ? ("." + ext) : ""); - - // Write time is greater than 1ms. This may be a network drive.... try another file. - #ifdef G3D_WIN32 - logName = std::string(std::getenv("TEMP")) + logName; - #else - logName = std::string("/tmp/") + logName; - #endif - - logFile = fopen(logName.c_str(), "w"); - } - - // Turn off buffering. - setvbuf(logFile, NULL, _IONBF, 0); - - fprintf(logFile, "Application Log\n"); - time_t t; - time(&t); - fprintf(logFile, "Start: %s\n", ctime(&t)); - fflush(logFile); - - if (commonLog == NULL) { - commonLog = this; - } -} - - -Log::~Log() { - section("Shutdown"); - println("Closing log file"); - - // Make sure we don't leave a dangling pointer - if (Log::commonLog == this) { - Log::commonLog = NULL; - } - - fclose(logFile); -} - - -FILE* Log::getFile() const { - return logFile; -} - -Log* Log::common() { - if (commonLog == NULL) { - commonLog = new Log(); - } - return commonLog; -} - - -std::string Log::getCommonLogFilename() { - return common()->filename; -} - - -void Log::section(const std::string& s) { - fprintf(logFile, "_____________________________________________________\n"); - fprintf(logFile, "\n ### %s ###\n\n", s.c_str()); -} - - -void __cdecl Log::printf(const char* fmt, ...) { - printHeader(); - - va_list arg_list; - va_start(arg_list, fmt); - print(vformat(fmt, arg_list)); - va_end(arg_list); -} - - -void __cdecl Log::vprintf(const char* fmt, va_list argPtr) { - vfprintf(logFile, fmt, argPtr); -} - - -void Log::print(const std::string& s) { - printHeader(); - fprintf(logFile, "%s", s.c_str()); -} - - -void Log::println(const std::string& s) { - printHeader(); - fprintf(logFile, "%s\n", s.c_str()); -} - - -void Log::printHeader() { - time_t t; - if (time(&t) != ((time_t)-1)) { - /* - char buf[32]; - strftime(buf, 32, "[%H:%M:%S]", localtime(&t)); - - Removed because this doesn't work on SDL threads. - - #ifdef _DEBUG - std::string bt = getBacktrace(15, 2, stripFromStackBottom); - fprintf(logFile, "\n %s %s\n\n", buf, bt.c_str()); - #endif - - fprintf(logFile, "\n %s \n", buf); - */ - - } else { - println("[Error getting time]"); - } -} - -} diff --git a/externals/g3dlite/G3D.lib/source/Matrix.cpp b/externals/g3dlite/G3D.lib/source/Matrix.cpp deleted file mode 100644 index 0c6db214543..00000000000 --- a/externals/g3dlite/G3D.lib/source/Matrix.cpp +++ /dev/null @@ -1,1801 +0,0 @@ -/** - @file Matrix.cpp - @author Morgan McGuire, matrix@graphics3d.com - */ -#include "G3D/Matrix.h" -#include "G3D/TextOutput.h" - -static inline G3D::Matrix::T negate(G3D::Matrix::T x) { - return -x; -} - -namespace G3D { - -int Matrix::debugNumCopyOps = 0; -int Matrix::debugNumAllocOps = 0; - -void Matrix::serialize(TextOutput& t) const { - t.writeSymbol("%"); - t.writeNumber(rows()); - t.writeSymbol("x"); - t.writeNumber(cols()); - t.pushIndent(); - t.writeNewline(); - - t.writeSymbol("["); - for (int r = 0; r < rows(); ++r) { - for (int c = 0; c < cols(); ++c) { - t.writeNumber(impl->get(r, c)); - if (c < cols() - 1) { - t.writeSymbol(","); - } else { - if (r < rows() - 1) { - t.writeSymbol(";"); - t.writeNewline(); - } - } - } - } - t.writeSymbol("]"); - t.popIndent(); - t.writeNewline(); -} - - -std::string Matrix::toString(const std::string& name) const { - std::string s; - - if (name != "") { - s += format("%s = \n", name.c_str()); - } - - s += "["; - for (int r = 0; r < rows(); ++r) { - for (int c = 0; c < cols(); ++c) { - double v = impl->get(r, c); - - if (::fabs(v) < 0.00001) { - // Don't print "negative zero" - s += format("% 10.04g", 0.0); - } else if (v == iRound(v)) { - // Print integers nicely - s += format("% 10.04g", v); - } else { - s += format("% 10.04f", v); - } - - if (c < cols() - 1) { - s += ","; - } else if (r < rows() - 1) { - s += ";\n "; - } else { - s += "]\n"; - } - } - } - return s; -} - - -#define INPLACE(OP)\ - ImplRef A = impl;\ -\ - if (! A.isLastReference()) {\ - impl = new Impl(A->R, A->C);\ - }\ -\ - A->OP(B, *impl); - -Matrix& Matrix::operator*=(const T& B) { - INPLACE(mul) - return *this; -} - - -Matrix& Matrix::operator-=(const T& B) { - INPLACE(sub) - return *this; -} - - -Matrix& Matrix::operator+=(const T& B) { - INPLACE(add) - return *this; -} - - -Matrix& Matrix::operator/=(const T& B) { - INPLACE(div) - return *this; -} - - -Matrix& Matrix::operator*=(const Matrix& B) { - // We can't optimize this one - *this = *this * B; - return *this; -} - - -Matrix& Matrix::operator-=(const Matrix& _B) { - const Impl& B = *_B.impl; - INPLACE(sub) - return *this; -} - - -Matrix& Matrix::operator+=(const Matrix& _B) { - const Impl& B = *_B.impl; - INPLACE(add) - return *this; -} - - -void Matrix::arrayMulInPlace(const Matrix& _B) { - const Impl& B = *_B.impl; - INPLACE(arrayMul) -} - - -void Matrix::arrayDivInPlace(const Matrix& _B) { - const Impl& B = *_B.impl; - INPLACE(arrayDiv) -} - -#undef INPLACE - -Matrix Matrix::fromDiagonal(const Matrix& d) { - debugAssert((d.rows() == 1) || (d.cols() == 1)); - - int n = d.numElements(); - Matrix D = zero(n, n); - for (int i = 0; i < n; ++i) { - D.set(i, i, d.impl->data[i]); - } - - return D; -} - -void Matrix::set(int r, int c, T v) { - if (! impl.isLastReference()) { - // Copy the data before mutating; this object is shared - impl = new Impl(*impl); - } - impl->set(r, c, v); -} - - -void Matrix::setRow(int r, const Matrix& vec) { - debugAssertM(vec.cols() == cols(), - "A row must be set to a vector of the same size."); - debugAssertM(vec.rows() == 1, - "A row must be set to a row vector."); - - debugAssert(r >= 0); - debugAssert(r < rows()); - - if (! impl.isLastReference()) { - // Copy the data before mutating; this object is shared - impl = new Impl(*impl); - } - impl->setRow(r, vec.impl->data); -} - - -void Matrix::setCol(int c, const Matrix& vec) { - debugAssertM(vec.rows() == rows(), - "A column must be set to a vector of the same size."); - debugAssertM(vec.cols() == 1, - "A column must be set to a column vector."); - - debugAssert(c >= 0); - - debugAssert(c < cols()); - - if (! impl.isLastReference()) { - // Copy the data before mutating; this object is shared - impl = new Impl(*impl); - } - impl->setCol(c, vec.impl->data); -} - - -Matrix::T Matrix::get(int r, int c) const { - return impl->get(r, c); -} - - -Matrix Matrix::row(int r) const { - debugAssert(r >= 0); - debugAssert(r < rows()); - Matrix out(1, cols()); - out.impl->setRow(1, impl->elt[r]); - return out; -} - - -Matrix Matrix::col(int c) const { - debugAssert(c >= 0); - debugAssert(c < cols()); - Matrix out(rows(), 1); - - T* outData = out.impl->data; - // Get a pointer to the first element in the column - const T* inElt = &(impl->elt[0][c]); - int R = rows(); - int C = cols(); - for (int r = 0; r < R; ++r) { - outData[r] = *inElt; - // Skip around to the next row - inElt += C; - } - - return out; -} - - -Matrix Matrix::zero(int R, int C) { - Impl* A = new Impl(R, C); - A->setZero(); - return Matrix(A); -} - - -Matrix Matrix::one(int R, int C) { - Impl* A = new Impl(R, C); - for (int i = R * C - 1; i >= 0; --i) { - A->data[i] = 1.0; - } - return Matrix(A); -} - - -Matrix Matrix::random(int R, int C) { - Impl* A = new Impl(R, C); - for (int i = R * C - 1; i >= 0; --i) { - A->data[i] = G3D::uniformRandom(0.0, 1.0); - } - return Matrix(A); -} - - -Matrix Matrix::identity(int N) { - Impl* m = new Impl(N, N); - m->setZero(); - for (int i = 0; i < N; ++i) { - m->elt[i][i] = 1.0; - } - return Matrix(m); -} - - -// Implement an explicit-output unary method by trampolining to the impl -#define TRAMPOLINE_EXPLICIT_1(method)\ -void Matrix::method(Matrix& out) const {\ - if ((out.impl == impl) && impl.isLastReference()) {\ - impl->method(*out.impl);\ - } else {\ - out = this->method();\ - }\ -} - -TRAMPOLINE_EXPLICIT_1(abs) -TRAMPOLINE_EXPLICIT_1(negate) -TRAMPOLINE_EXPLICIT_1(arrayLog) -TRAMPOLINE_EXPLICIT_1(arrayExp) -TRAMPOLINE_EXPLICIT_1(arrayCos) -TRAMPOLINE_EXPLICIT_1(arraySin) - -void Matrix::mulRow(int r, const T& v) { - debugAssert(r >= 0 && r < rows()); - - if (! impl.isLastReference()) { - impl = new Impl(*impl); - } - - impl->mulRow(r, v); -} - - -void Matrix::transpose(Matrix& out) const { - if ((out.impl == impl) && impl.isLastReference() && (impl->R == impl->C)) { - // In place - impl->transpose(*out.impl); - } else { - out = this->transpose(); - } -} - - -Matrix3 Matrix::toMatrix3() const { - debugAssert(impl->R == 3); - debugAssert(impl->C == 3); - return Matrix3( - impl->get(0,0), impl->get(0,1), impl->get(0,2), - impl->get(1,0), impl->get(1,1), impl->get(1,2), - impl->get(2,0), impl->get(2,1), impl->get(2,2)); -} - - -Matrix4 Matrix::toMatrix4() const { - debugAssert(impl->R == 4); - debugAssert(impl->C == 4); - return Matrix4( - impl->get(0,0), impl->get(0,1), impl->get(0,2), impl->get(0,3), - impl->get(1,0), impl->get(1,1), impl->get(1,2), impl->get(1,3), - impl->get(2,0), impl->get(2,1), impl->get(2,2), impl->get(2,3), - impl->get(3,0), impl->get(3,1), impl->get(3,2), impl->get(3,3)); -} - - -Vector2 Matrix::toVector2() const { - debugAssert(impl->R * impl->C == 2); - if (impl->R > impl->C) { - return Vector2(impl->get(0,0), impl->get(1,0)); - } else { - return Vector2(impl->get(0,0), impl->get(0,1)); - } -} - - -Vector3 Matrix::toVector3() const { - debugAssert(impl->R * impl->C == 3); - if (impl->R > impl->C) { - return Vector3(impl->get(0,0), impl->get(1,0), impl->get(2, 0)); - } else { - return Vector3(impl->get(0,0), impl->get(0,1), impl->get(0, 2)); - } -} - - -Vector4 Matrix::toVector4() const { - debugAssert( - ((impl->R == 4) && (impl->C == 1)) || - ((impl->R == 1) && (impl->C == 4))); - - if (impl->R > impl->C) { - return Vector4(impl->get(0,0), impl->get(1,0), impl->get(2, 0), impl->get(3,0)); - } else { - return Vector4(impl->get(0,0), impl->get(0,1), impl->get(0, 2), impl->get(0,3)); - } -} - - -void Matrix::swapRows(int r0, int r1) { - debugAssert(r0 >= 0 && r0 < rows()); - debugAssert(r1 >= 0 && r1 < rows()); - - if (r0 == r1) { - return; - } - - if (! impl.isLastReference()) { - impl = new Impl(*impl); - } - - impl->swapRows(r0, r1); -} - - -void Matrix::swapAndNegateCols(int c0, int c1) { - debugAssert(c0 >= 0 && c0 < cols()); - debugAssert(c1 >= 0 && c1 < cols()); - - if (c0 == c1) { - return; - } - - if (! impl.isLastReference()) { - impl = new Impl(*impl); - } - - impl->swapAndNegateCols(c0, c1); -} - -Matrix Matrix::subMatrix(int r1, int r2, int c1, int c2) const { - debugAssert(r2>=r1); - debugAssert(c2>=c1); - debugAssert(c2=0); - debugAssert(c1>=0); - - Matrix X(r2 - r1 + 1, c2 - c1 + 1); - - for (int r = 0; r < X.rows(); ++r) { - for (int c = 0; c < X.cols(); ++c) { - X.set(r, c, get(r + r1, c + c1)); - } - } - - return X; -} - - -bool Matrix::anyNonZero() const { - return impl->anyNonZero(); -} - - -bool Matrix::allNonZero() const { - return impl->allNonZero(); -} - - -void Matrix::svd(Matrix& U, Array& d, Matrix& V, bool sort) const { - debugAssert(rows() >= cols()); - debugAssertM(&U != &V, "Arguments to SVD must be different matrices"); - debugAssertM(&U != this, "Arguments to SVD must be different matrices"); - debugAssertM(&V != this, "Arguments to SVD must be different matrices"); - - int R = rows(); - int C = cols(); - - // Make sure we don't overwrite a shared matrix - if (! V.impl.isLastReference()) { - V = Matrix::zero(C, C); - } else { - V.impl->setSize(C, C); - } - - if (&U != this || ! impl.isLastReference()) { - // Make a copy of this for in-place SVD - U.impl = new Impl(*impl); - } - - d.resize(C); - const char* ret = svdCore(U.impl->elt, R, C, d.getCArray(), V.impl->elt); - - debugAssertM(ret == NULL, ret); - (void)ret; - - if (sort) { - // Sort the singular values from greatest to least - - Array rank(C); - for (int c = 0; c < C; ++c) { - rank[c].col = c; - rank[c].value = d[c]; - } - - rank.sort(SORT_INCREASING); - - Matrix Uold = U; - Matrix Vold = V; - - U = Matrix(U.rows(), U.cols()); - V = Matrix(V.rows(), V.cols()); - - // Now permute U, d, and V appropriately - for (int c0 = 0; c0 < C; ++c0) { - const int c1 = rank[c0].col; - - d[c0] = rank[c0].value; - U.setCol(c0, Uold.col(c1)); - V.setCol(c0, Vold.col(c1)); - } - - } -} - - -#define COMPARE_SCALAR(OP)\ -Matrix Matrix::operator OP (const T& scalar) const {\ - int R = rows();\ - int C = cols();\ - int N = R * C;\ - Matrix out = Matrix::zero(R, C);\ -\ - const T* raw = impl->data;\ - T* outRaw = out.impl->data;\ - for (int i = 0; i < N; ++i) {\ - outRaw[i] = raw[i] OP scalar;\ - }\ -\ - return out;\ -} - -COMPARE_SCALAR(<) -COMPARE_SCALAR(<=) -COMPARE_SCALAR(>) -COMPARE_SCALAR(>=) -COMPARE_SCALAR(==) -COMPARE_SCALAR(!=) - -#undef COMPARE_SCALAR - -double Matrix::normSquared() const { - int R = rows(); - int C = cols(); - int N = R * C; - - double sum = 0.0; - - const T* raw = impl->data; - for (int i = 0; i < N; ++i) { - sum += square(raw[i]); - } - - return sum; -} - -double Matrix::norm() const { - return sqrt(normSquared()); -} - -/////////////////////////////////////////////////////////// - -Matrix::Impl::Impl(const Matrix3& M) : elt(NULL), data(NULL), R(0), C(0), dataSize(0){ - setSize(3, 3); - for (int r = 0; r < 3; ++r) { - for (int c = 0; c < 3; ++c) { - set(r, c, M[r][c]); - } - } - -} - - -Matrix::Impl::Impl(const Matrix4& M): elt(NULL), data(NULL), R(0), C(0), dataSize(0) { - setSize(4, 4); - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - set(r, c, M[r][c]); - } - } -} - - -void Matrix::Impl::setSize(int newRows, int newCols) { - if ((R == newRows) && (C == newCols)) { - // Nothing to do - return; - } - - int newSize = newRows * newCols; - - R = newRows; C = newCols; - - // Only allocate if we need more space - // or the size difference is ridiculous - if ((newSize > dataSize) || (newSize < dataSize / 4)) { - System::alignedFree(data); - data = (float*)System::alignedMalloc(R * C * sizeof(T), 16); - ++Matrix::debugNumAllocOps; - dataSize = newSize; - } - - // Construct the row pointers - //delete[] elt; - System::free(elt); - elt = (T**)System::malloc(R * sizeof(T*));// new T*[R]; - - for (int r = 0; r < R; ++ r) { - elt[r] = data + r * C; - } -} - - -Matrix::Impl::~Impl() { - //delete[] elt; - System::free(elt); - System::alignedFree(data); -} - - -Matrix::Impl& Matrix::Impl::operator=(const Impl& m) { - setSize(m.R, m.C); - System::memcpy(data, m.data, R * C * sizeof(T)); - ++Matrix::debugNumCopyOps; - return *this; -} - - -void Matrix::Impl::setZero() { - System::memset(data, 0, R * C * sizeof(T)); -} - - -void Matrix::Impl::swapRows(int r0, int r1) { - T* R0 = elt[r0]; - T* R1 = elt[r1]; - - for (int c = 0; c < C; ++c) { - T temp = R0[c]; - R0[c] = R1[c]; - R1[c] = temp; - } -} - - -void Matrix::Impl::swapAndNegateCols(int c0, int c1) { - for (int r = 0; r < R; ++r) { - T* row = elt[r]; - - const T temp = -row[c0]; - row[c0] = -row[c1]; - row[c1] = temp; - } -} - - -void Matrix::Impl::mulRow(int r, const T& v) { - T* row = elt[r]; - - for (int c = 0; c < C; ++c) { - row[c] *= v; - } -} - - -void Matrix::Impl::mul(const Impl& B, Impl& out) const { - const Impl& A = *this; - - debugAssertM( - (this != &out) && (&B != &out), - "Output argument to mul cannot be the same as an input argument."); - - debugAssert(A.C == B.R); - debugAssert(A.R == out.R); - debugAssert(B.C == out.C); - - for (int r = 0; r < out.R; ++r) { - for (int c = 0; c < out.C; ++c) { - T sum = 0.0; - for (int i = 0; i < A.C; ++i) { - sum += A.get(r, i) * B.get(i, c); - } - out.set(r, c, sum); - } - } -} - - -// We're about to define several similar methods, -// so use a macro to share implementations. This -// must be a macro because the difference between -// the macros is the operation in the inner loop. -#define IMPLEMENT_ARRAY_2(method, OP)\ -void Matrix::Impl::method(const Impl& B, Impl& out) const {\ - const Impl& A = *this;\ - \ - debugAssert(A.C == B.C);\ - debugAssert(A.R == B.R);\ - debugAssert(A.C == out.C);\ - debugAssert(A.R == out.R);\ - \ - for (int i = R * C - 1; i >= 0; --i) {\ - out.data[i] = A.data[i] OP B.data[i];\ - }\ -} - - -#define IMPLEMENT_ARRAY_1(method, f)\ -void Matrix::Impl::method(Impl& out) const {\ - const Impl& A = *this;\ - \ - debugAssert(A.C == out.C);\ - debugAssert(A.R == out.R);\ - \ - for (int i = R * C - 1; i >= 0; --i) {\ - out.data[i] = f(A.data[i]);\ - }\ -} - - -#define IMPLEMENT_ARRAY_SCALAR(method, OP)\ -void Matrix::Impl::method(Matrix::T B, Impl& out) const {\ - const Impl& A = *this;\ - \ - debugAssert(A.C == out.C);\ - debugAssert(A.R == out.R);\ - \ - for (int i = R * C - 1; i >= 0; --i) {\ - out.data[i] = A.data[i] OP B;\ - }\ -} - -IMPLEMENT_ARRAY_2(add, +) -IMPLEMENT_ARRAY_2(sub, -) -IMPLEMENT_ARRAY_2(arrayMul, *) -IMPLEMENT_ARRAY_2(arrayDiv, /) - -IMPLEMENT_ARRAY_SCALAR(add, +) -IMPLEMENT_ARRAY_SCALAR(sub, -) -IMPLEMENT_ARRAY_SCALAR(mul, *) -IMPLEMENT_ARRAY_SCALAR(div, /) - -IMPLEMENT_ARRAY_1(abs, ::fabs) -IMPLEMENT_ARRAY_1(negate, ::negate) -IMPLEMENT_ARRAY_1(arrayLog, ::log) -IMPLEMENT_ARRAY_1(arraySqrt, ::sqrt) -IMPLEMENT_ARRAY_1(arrayExp, ::exp) -IMPLEMENT_ARRAY_1(arrayCos, ::cos) -IMPLEMENT_ARRAY_1(arraySin, ::sin) - -#undef IMPLEMENT_ARRAY_SCALAR -#undef IMPLEMENT_ARRAY_1 -#undef IMPLEMENT_ARRAY_2 - -// lsub is special because the argument order is reversed -void Matrix::Impl::lsub(Matrix::T B, Impl& out) const { - const Impl& A = *this; - - debugAssert(A.C == out.C); - debugAssert(A.R == out.R); - - for (int i = R * C - 1; i >= 0; --i) { - out.data[i] = B - A.data[i]; - } -} - - -void Matrix::Impl::inverseViaAdjoint(Impl& out) const { - debugAssert(&out != this); - - // Inverse = adjoint / determinant - - adjoint(out); - - // Don't call the determinant method when we already have an - // adjoint matrix; there's a faster way of computing it: the dot - // product of the first row and the adjoint's first col. - double det = 0.0; - for (int r = R - 1; r >= 0; --r) { - det += elt[0][r] * out.elt[r][0]; - } - - out.div(Matrix::T(det), out); -} - - -void Matrix::Impl::transpose(Impl& out) const { - debugAssert(out.R == C); - debugAssert(out.C == R); - - if (&out == this) { - // Square matrix in place - for (int r = 0; r < R; ++r) { - for (int c = r + 1; c < C; ++c) { - T temp = get(r, c); - out.set(r, c, get(c, r)); - out.set(c, r, temp); - } - } - } else { - for (int r = 0; r < R; ++r) { - for (int c = 0; c < C; ++c) { - out.set(c, r, get(r, c)); - } - } - } -} - - -void Matrix::Impl::adjoint(Impl& out) const { - cofactor(out); - // Transpose is safe to perform in place - out.transpose(out); -} - - -void Matrix::Impl::cofactor(Impl& out) const { - debugAssert(&out != this); - for(int r = 0; r < R; ++r) { - for(int c = 0; c < C; ++c) { - out.set(r, c, cofactor(r, c)); - } - } -} - - -Matrix::T Matrix::Impl::cofactor(int r, int c) const { - // Strang p. 217 - float s = isEven(r + c) ? 1.0f : -1.0f; - - return s * determinant(r, c); -} - - -Matrix::T Matrix::Impl::determinant(int nr, int nc) const { - debugAssert(R > 0); - debugAssert(C > 0); - Impl A(R - 1, C - 1); - withoutRowAndCol(nr, nc, A); - return A.determinant(); -} - - -void Matrix::Impl::setRow(int r, const T* vals) { - debugAssert(r >= 0); - System::memcpy(elt[r], vals, sizeof(T) * C); -} - - -void Matrix::Impl::setCol(int c, const T* vals) { - for (int r = 0; r < R; ++r) { - elt[r][c] = vals[r]; - } -} - - -Matrix::T Matrix::Impl::determinant() const { - - debugAssert(R == C); - - // Compute using cofactors - switch(R) { - case 0: - return 0; - - case 1: - // Determinant of a 1x1 is the element - return elt[0][0]; - - case 2: - // Determinant of a 2x2 is ad-bc - return elt[0][0] * elt[1][1] - elt[0][1] * elt[1][0]; - - case 3: - { - // Determinant of an nxn matrix is the dot product of the first - // row with the first row of cofactors. The base cases of this - // method get called a lot, so we spell out the implementation - // for the 3x3 case. - - double cofactor00 = elt[1][1] * elt[2][2] - elt[1][2] * elt[2][1]; - double cofactor10 = elt[1][2] * elt[2][0] - elt[1][0] * elt[2][2]; - double cofactor20 = elt[1][0] * elt[2][1] - elt[1][1] * elt[2][0]; - - return Matrix::T( - elt[0][0] * cofactor00 + - elt[0][1] * cofactor10 + - elt[0][2] * cofactor20); - } - - default: - { - // Determinant of an n x n matrix is the dot product of the first - // row with the first row of cofactors - T det = 0.0; - - for (int c = 0; c < C; ++c) { - det += elt[0][c] * cofactor(0, c); - } - - return det; - } - } -} - - -void Matrix::Impl::withoutRowAndCol(int excludeRow, int excludeCol, Impl& out) const { - debugAssert(out.R == R - 1); - debugAssert(out.C == C - 1); - - for (int r = 0; r < out.R; ++r) { - for (int c = 0; c < out.C; ++c) { - out.elt[r][c] = elt[r + ((r >= excludeRow) ? 1 : 0)][c + ((c >= excludeCol) ? 1 : 0)]; - } - } -} - - -Matrix Matrix::pseudoInverse(float tolerance) const { - if ((cols() == 1) || (rows() == 1)) { - return vectorPseudoInverse(); - } else if ((cols() <= 4) || (rows() <= 4)) { - return partitionPseudoInverse(); - } else { - return svdPseudoInverse(tolerance); - } -} - -/* - Public function for testing purposes only. Use pseudoInverse(), as it contains optimizations for - nonsingular matrices with at least one small (<5) dimension. -*/ -Matrix Matrix::svdPseudoInverse(float tolerance) const { - if (cols() > rows()) { - return transpose().svdPseudoInverse(tolerance).transpose(); - } - - // Matrices from SVD - Matrix U, V; - - // Diagonal elements - Array d; - - svd(U, d, V); - - if (rows() == 1) { - d.resize(1, false); - } - - if (tolerance < 0) { - // TODO: Should be eps(d[0]), which is the largest diagonal - tolerance = G3D::max(rows(), cols()) * 0.0001f; - } - - Matrix X; - - int r = 0; - for (int i = 0; i < d.size(); ++i) { - if (d[i] > tolerance) { - d[i] = Matrix::T(1) / d[i]; - ++r; - } - } - - if (r == 0) { - // There were no non-zero elements - X = zero(cols(), rows()); - } else { - // Use the first r columns - - // Test code (the rest is below) - /* - d.resize(r); - Matrix testU = U.subMatrix(0, U.rows() - 1, 0, r - 1); - Matrix testV = V.subMatrix(0, V.rows() - 1, 0, r - 1); - Matrix testX = testV * Matrix::fromDiagonal(d) * testU.transpose(); - X = testX; - */ - - - // We want to do this: - // - // d.resize(r); - // U = U.subMatrix(0, U.rows() - 1, 0, r - 1); - // X = V * Matrix::fromDiagonal(d) * U.transpose(); - // - // but creating a large diagonal matrix and then - // multiplying by it is wasteful. So we instead - // explicitly perform A = (D * U')' = U * D, and - // then multiply X = V * A'. - - Matrix A = Matrix(U.rows(), r); - - const T* dPtr = d.getCArray(); - for (int i = 0; i < A.rows(); ++i) { - const T* Urow = U.impl->elt[i]; - T* Arow = A.impl->elt[i]; - const int Acols = A.cols(); - for (int j = 0; j < Acols; ++j) { - // A(i,j) = U(i,:) * D(:,j) - // This is non-zero only at j = i because D is diagonal - // A(i,j) = U(i,j) * D(j,j) - Arow[j] = Urow[j] * dPtr[j]; - } - } - - // - // Compute X = V.subMatrix(0, V.rows() - 1, 0, r - 1) * A.transpose() - // - // Avoid the explicit subMatrix call, and by storing A' instead of A, avoid - // both the transpose and the memory incoherence of striding across memory - // in big steps. - - alwaysAssertM(A.cols() == r, - "Internal dimension mismatch during pseudoInverse()"); - alwaysAssertM(V.cols() >= r, - "Internal dimension mismatch during pseudoInverse()"); - - X = Matrix(V.rows(), A.rows()); - T** Xelt = X.impl->elt; - for (int i = 0; i < X.rows(); ++i) { - const T* Vrow = V.impl->elt[i]; - for (int j = 0; j < X.cols(); ++j) { - const T* Arow = A.impl->elt[j]; - T sum = 0; - for (int k = 0; k < r; ++k) { - sum += Vrow[k] * Arow[k]; - } - Xelt[i][j] = sum; - } - } - - /* - // Test that results are the same after optimizations: - Matrix diff = X - testX; - T n = diff.norm(); - debugAssert(n < 0.0001); - */ - } - return X; -} - -// Computes pseudoinverse for a vector -Matrix Matrix::vectorPseudoInverse() const { - // If vector A has nonzero elements: transpose A, then divide each elt. by the squared norm - // If A is zero vector: transpose A - double x = 0.0; - - if (anyNonZero()) { - x = 1.0 / normSquared(); - } - - Matrix A(cols(), rows()); - T** Aelt = A.impl->elt; - for (int r = 0; r < rows(); ++r) { - const T* MyRow = impl->elt[r]; - for (int c = 0; c < cols(); ++c) { - Aelt[c][r] = T(MyRow[c] * x); - } - } - return Matrix(A); -} - - -Matrix Matrix::rowPartPseudoInverse() const{ - int m = rows(); - int n = cols(); - alwaysAssertM((m<=n),"Row-partitioned block matrix pseudoinverse requires Relt; - T** Belt = B.impl->elt; - for (int i = 0; i < m; ++i) { - const T* Arow = Aelt[i]; - for (int j = 0; j < m; ++j) { - const T* Brow = Aelt[j]; - T sum = 0; - for (int k = 0; k < n; ++k) { - sum += Arow[k] * Brow[k]; - } - Belt[i][j] = sum; - } - } - - // B has size m x m - switch (m) { - case 2: - return row2PseudoInverse(B); - - case 3: - return row3PseudoInverse(B); - - case 4: - return row4PseudoInverse(B); - - default: - alwaysAssertM(false, "G3D internal error: Should have used the vector or general case!"); - return Matrix(); - } -} - -Matrix Matrix::colPartPseudoInverse() const{ - int m = rows(); - int n = cols(); - alwaysAssertM((m>=n),"Column-partitioned block matrix pseudoinverse requires R>C"); - // TODO: Put each of the individual cases in its own helper function - // TODO: Push the B computation down into the individual cases - // B = A' * A - Matrix A = *this; - Matrix B = Matrix(n, n); - T** Aelt = A.impl->elt; - T** Belt = B.impl->elt; - for (int i = 0; i < n; ++i) { - for (int j = 0; j < n; ++j) { - T sum = 0; - for (int k = 0; k < m; ++k) { - sum += Aelt[k][i] * Aelt[k][j]; - } - Belt[i][j] = sum; - } - } - - // B has size n x n - switch (n) { - case 2: - return col2PseudoInverse(B); - - case 3: - return col3PseudoInverse(B); - - case 4: - return col4PseudoInverse(B); - - default: - alwaysAssertM(false, "G3D internal error: Should have used the vector or general case!"); - return Matrix(); - } -} - -Matrix Matrix::col2PseudoInverse(const Matrix& B) const { - - Matrix A = *this; - int m = rows(); - int n = cols(); - (void)n; - - // Row-major 2x2 matrix - const float B2[2][2] = - {{B.get(0,0), B.get(0,1)}, - {B.get(1,0), B.get(1,1)}}; - - float det = (B2[0][0]*B2[1][1]) - (B2[0][1]*B2[1][0]); - - if (fuzzyEq(det, T(0))) { - - // Matrix was singular; the block matrix pseudo-inverse can't - // handle that, so fall back to the old case - return svdPseudoInverse(); - - } else { - // invert using formula at http://www.netsoc.tcd.ie/~jgilbert/maths_site/applets/algebra/matrix_inversion.html - - // Multiply by Binv * A' - Matrix X(cols(), rows()); - - T** Xelt = X.impl->elt; - T** Aelt = A.impl->elt; - float binv00 = B2[1][1]/det, binv01 = -B2[1][0]/det; - float binv10 = -B2[0][1]/det, binv11 = B2[0][0]/det; - for (int j = 0; j < m; ++j) { - const T* Arow = Aelt[j]; - float a0 = Arow[0]; - float a1 = Arow[1]; - Xelt[0][j] = binv00 * a0 + binv01 * a1; - Xelt[1][j] = binv10 * a0 + binv11 * a1; - } - return X; - } -} - -Matrix Matrix::col3PseudoInverse(const Matrix& B) const { - Matrix A = *this; - int m = rows(); - int n = cols(); - - Matrix3 B3 = B.toMatrix3(); - if (fuzzyEq(B3.determinant(), (T)0.0)) { - - // Matrix was singular; the block matrix pseudo-inverse can't - // handle that, so fall back to the old case - return svdPseudoInverse(); - - } else { - Matrix3 B3inv = B3.inverse(); - - // Multiply by Binv * A' - Matrix X(cols(), rows()); - - T** Xelt = X.impl->elt; - T** Aelt = A.impl->elt; - for (int i = 0; i < n; ++i) { - T* Xrow = Xelt[i]; - for (int j = 0; j < m; ++j) { - const T* Arow = Aelt[j]; - T sum = 0; - const float* Binvrow = B3inv[i]; - for (int k = 0; k < n; ++k) { - sum += Binvrow[k] * Arow[k]; - } - Xrow[j] = sum; - } - } - return X; - } -} - -Matrix Matrix::col4PseudoInverse(const Matrix& B) const { - Matrix A = *this; - int m = rows(); - int n = cols(); - - Matrix4 B4 = B.toMatrix4(); - if (fuzzyEq(B4.determinant(), (T)0.0)) { - - // Matrix was singular; the block matrix pseudo-inverse can't - // handle that, so fall back to the old case - return svdPseudoInverse(); - - } else { - Matrix4 B4inv = B4.inverse(); - - // Multiply by Binv * A' - Matrix X(cols(), rows()); - - T** Xelt = X.impl->elt; - T** Aelt = A.impl->elt; - for (int i = 0; i < n; ++i) { - T* Xrow = Xelt[i]; - for (int j = 0; j < m; ++j) { - const T* Arow = Aelt[j]; - T sum = 0; - const float* Binvrow = B4inv[i]; - for (int k = 0; k < n; ++k) { - sum += Binvrow[k] * Arow[k]; - } - Xrow[j] = sum; - } - } - return X; - } -} - -Matrix Matrix::row2PseudoInverse(const Matrix& B) const { - - Matrix A = *this; - int m = rows(); - int n = cols(); - (void)m; - - // Row-major 2x2 matrix - const float B2[2][2] = - {{B.get(0,0), B.get(0,1)}, - {B.get(1,0), B.get(1,1)}}; - - float det = (B2[0][0]*B2[1][1]) - (B2[0][1]*B2[1][0]); - - if (fuzzyEq(det, T(0))) { - - // Matrix was singular; the block matrix pseudo-inverse can't - // handle that, so fall back to the old case - return svdPseudoInverse(); - - } else { - // invert using formula at http://www.netsoc.tcd.ie/~jgilbert/maths_site/applets/algebra/matrix_inversion.html - - // Multiply by Binv * A' - Matrix X(cols(), rows()); - - T** Xelt = X.impl->elt; - T** Aelt = A.impl->elt; - float binv00 = B2[1][1]/det, binv01 = -B2[1][0]/det; - float binv10 = -B2[0][1]/det, binv11 = B2[0][0]/det; - for (int j = 0; j < n; ++j) { - Xelt[j][0] = Aelt[0][j] * binv00 + Aelt[1][j] * binv10; - Xelt[j][1] = Aelt[0][j] * binv01 + Aelt[1][j] * binv11; - } - return X; - } -} - -Matrix Matrix::row3PseudoInverse(const Matrix& B) const { - - Matrix A = *this; - int m = rows(); - int n = cols(); - - Matrix3 B3 = B.toMatrix3(); - if (fuzzyEq(B3.determinant(), (T)0.0)) { - - // Matrix was singular; the block matrix pseudo-inverse can't - // handle that, so fall back to the old case - return svdPseudoInverse(); - - } else { - Matrix3 B3inv = B3.inverse(); - - // Multiply by Binv * A' - Matrix X(cols(), rows()); - - T** Xelt = X.impl->elt; - T** Aelt = A.impl->elt; - for (int i = 0; i < n; ++i) { - T* Xrow = Xelt[i]; - for (int j = 0; j < m; ++j) { - T sum = 0; - for (int k = 0; k < m; ++k) { - sum += Aelt[k][i] * B3inv[j][k]; - } - Xrow[j] = sum; - } - } - return X; - } -} - -Matrix Matrix::row4PseudoInverse(const Matrix& B) const { - - Matrix A = *this; - int m = rows(); - int n = cols(); - - Matrix4 B4 = B.toMatrix4(); - if (fuzzyEq(B4.determinant(), (T)0.0)) { - - // Matrix was singular; the block matrix pseudo-inverse can't - // handle that, so fall back to the old case - return svdPseudoInverse(); - - } else { - Matrix4 B4inv = B4.inverse(); - - // Multiply by Binv * A' - Matrix X(cols(), rows()); - - T** Xelt = X.impl->elt; - T** Aelt = A.impl->elt; - for (int i = 0; i < n; ++i) { - T* Xrow = Xelt[i]; - for (int j = 0; j < m; ++j) { - T sum = 0; - for (int k = 0; k < m; ++k) { - sum += Aelt[k][i] * B4inv[j][k]; - } - Xrow[j] = sum; - } - } - return X; - } -} - -// Uses the block matrix pseudoinverse to compute the pseudoinverse of a full-rank mxn matrix with m >= n -// http://en.wikipedia.org/wiki/Block_matrix_pseudoinverse -Matrix Matrix::partitionPseudoInverse() const { - - // Logic: - // A^-1 = (A'A)^-1 A' - // A has few (n) columns, so A'A is small (n x n) and fast to invert - - int m = rows(); - int n = cols(); - - if (m < n) { - // TODO: optimize by pushing through the transpose - //return transpose().partitionPseudoInverse().transpose(); - return rowPartPseudoInverse(); - - } else { - return colPartPseudoInverse(); - } -} - -void Matrix::Impl::inverseInPlaceGaussJordan() { - debugAssertM(R == C, - format( - "Cannot perform Gauss-Jordan inverse on a non-square matrix." - " (Argument was %dx%d)", - R, C)); - - // Exchange to float elements -# define SWAP(x, y) {float temp = x; x = y; y = temp;} - - // The integer arrays pivot, rowIndex, and colIndex are - // used for bookkeeping on the pivoting - static Array colIndex, rowIndex, pivot; - - int col = 0, row = 0; - - colIndex.resize(R); - rowIndex.resize(R); - pivot.resize(R); - - static const int NO_PIVOT = -1; - - // Initialize the pivot array to default values. - for (int i = 0; i < R; ++i) { - pivot[i] = NO_PIVOT; - } - - // This is the main loop over the columns to be reduced - // Loop over the columns. - for (int c = 0; c < R; ++c) { - - // Find the largest element and use that as a pivot - float largestMagnitude = 0.0; - - // This is the outer loop of the search for a pivot element - for (int r = 0; r < R; ++r) { - - // Unless we've already found the pivot, keep going - if (pivot[r] != 0) { - - // Find the largest pivot - for (int k = 0; k < R; ++k) { - if (pivot[k] == NO_PIVOT) { - const float mag = fabs(elt[r][k]); - - if (mag >= largestMagnitude) { - largestMagnitude = mag; - row = r; col = k; - } - } - } - } - } - - pivot[col] += 1; - - // Interchange columns so that the pivot element is on the diagonal (we'll have to undo this - // at the end) - if (row != col) { - for (int k = 0; k < R; ++k) { - SWAP(elt[row][k], elt[col][k]) - } - } - - // The pivot is now at [row, col] - rowIndex[c] = row; - colIndex[c] = col; - - double piv = elt[col][col]; - - debugAssertM(piv != 0.0, "Matrix is singular"); - - // Divide everything by the pivot (avoid computing the division - // multiple times). - const double pivotInverse = 1.0 / piv; - elt[col][col] = 1.0; - - for (int k = 0; k < R; ++k) { - elt[col][k] *= Matrix::T(pivotInverse); - } - - // Reduce all rows - for (int r = 0; r < R; ++r) { - // Skip over the pivot row - if (r != col) { - - double oldValue = elt[r][col]; - elt[r][col] = 0.0; - - for (int k = 0; k < R; ++k) { - elt[r][k] -= Matrix::T(elt[col][k] * oldValue); - } - } - } - } - - - // Put the columns back in the correct locations - for (int i = R - 1; i >= 0; --i) { - if (rowIndex[i] != colIndex[i]) { - for (int k = 0; k < R; ++k) { - SWAP(elt[k][rowIndex[i]], elt[k][colIndex[i]]); - } - } - } - -# undef SWAP -} - - -bool Matrix::Impl::anyNonZero() const { - int N = R * C; - for (int i = 0; i < N; ++i) { - if (data[i] != 0.0) { - return true; - } - } - return false; -} - - -bool Matrix::Impl::allNonZero() const { - int N = R * C; - for (int i = 0; i < N; ++i) { - if (data[i] == 0.0) { - return false; - } - } - return true; -} - - -/** Helper for svdCore */ -static double pythag(double a, double b) { - - double at = fabs(a), bt = fabs(b), ct, result; - - if (at > bt) { - ct = bt / at; - result = at * sqrt(1.0 + square(ct)); - } else if (bt > 0.0) { - ct = at / bt; - result = bt * sqrt(1.0 + square(ct)); - } else { - result = 0.0; - } - - return result; -} - -#define SIGN(a, b) ((b) >= 0.0 ? fabs(a) : -fabs(a)) - -const char* Matrix::svdCore(float** U, int rows, int cols, float* D, float** V) { - const int MAX_ITERATIONS = 30; - - int flag, i, its, j, jj, k, l = 0, nm = 0; - double c, f, h, s, x, y, z; - double anorm = 0.0, g = 0.0, scale = 0.0; - - // Temp row vector - double* rv1; - - debugAssertM(rows >= cols, "Must have more rows than columns"); - - rv1 = (double*)System::alignedMalloc(cols * sizeof(double), 16); - debugAssert(rv1); - - // Householder reduction to bidiagonal form - for (i = 0; i < cols; ++i) { - - // Left-hand reduction - l = i + 1; - rv1[i] = scale * g; - g = s = scale = 0.0; - - if (i < rows) { - - for (k = i; k < rows; ++k) { - scale += fabs((double)U[k][i]); - } - - if (scale) { - for (k = i; k < rows; ++k) { - U[k][i] = (float)((double)U[k][i]/scale); - s += ((double)U[k][i] * (double)U[k][i]); - } - - f = (double)U[i][i]; - - // TODO: what is this 2-arg sign function? - g = -SIGN(sqrt(s), f); - h = f * g - s; - U[i][i] = (float)(f - g); - - if (i != cols - 1) { - for (j = l; j < cols; j++) { - - for (s = 0.0, k = i; k < rows; ++k) { - s += ((double)U[k][i] * (double)U[k][j]); - } - - f = s / h; - for (k = i; k < rows; ++k) { - U[k][j] += (float)(f * (double)U[k][i]); - } - } - } - for (k = i; k < rows; ++k) { - U[k][i] = (float)((double)U[k][i]*scale); - } - } - } - D[i] = (float)(scale * g); - - // right-hand reduction - g = s = scale = 0.0; - if (i < rows && i != cols - 1) { - for (k = l; k < cols; ++k) { - scale += fabs((double)U[i][k]); - } - - if (scale) { - for (k = l; k < cols; ++k) { - U[i][k] = (float)((double)U[i][k]/scale); - s += ((double)U[i][k] * (double)U[i][k]); - } - - f = (double)U[i][l]; - g = -SIGN(sqrt(s), f); - h = f * g - s; - U[i][l] = (float)(f - g); - - for (k = l; k < cols; ++k) { - rv1[k] = (double)U[i][k] / h; - } - - if (i != rows - 1) { - - for (j = l; j < rows; ++j) { - for (s = 0.0, k = l; k < cols; ++k) { - s += ((double)U[j][k] * (double)U[i][k]); - } - - for (k = l; k < cols; ++k) { - U[j][k] += (float)(s * rv1[k]); - } - } - } - - for (k = l; k < cols; ++k) { - U[i][k] = (float)((double)U[i][k]*scale); - } - } - } - - anorm = max(anorm, fabs((double)D[i]) + fabs(rv1[i])); - } - - // accumulate the right-hand transformation - for (i = cols - 1; i >= 0; --i) { - if (i < cols - 1) { - if (g) { - for (j = l; j < cols; j++) { - V[j][i] = (float)(((double)U[i][j] / (double)U[i][l]) / g); - } - - // double division to avoid underflow - for (j = l; j < cols; ++j) { - for (s = 0.0, k = l; k < cols; k++) { - s += ((double)U[i][k] * (double)V[k][j]); - } - - for (k = l; k < cols; ++k) { - V[k][j] += (float)(s * (double)V[k][i]); - } - } - } - - for (j = l; j < cols; ++j) { - V[i][j] = V[j][i] = 0.0; - } - } - - V[i][i] = 1.0; - g = rv1[i]; - l = i; - } - - // accumulate the left-hand transformation - for (i = cols - 1; i >= 0; --i) { - l = i + 1; - g = (double)D[i]; - if (i < cols - 1) { - for (j = l; j < cols; ++j) { - U[i][j] = 0.0; - } - } - - if (g) { - g = 1.0 / g; - if (i != cols - 1) { - for (j = l; j < cols; ++j) { - for (s = 0.0, k = l; k < rows; ++k) { - s += ((double)U[k][i] * (double)U[k][j]); - } - - f = (s / (double)U[i][i]) * g; - - for (k = i; k < rows; ++k) { - U[k][j] += (float)(f * (double)U[k][i]); - } - } - } - - for (j = i; j < rows; ++j) { - U[j][i] = (float)((double)U[j][i]*g); - } - - } else { - for (j = i; j < rows; ++j) { - U[j][i] = 0.0; - } - } - ++U[i][i]; - } - - // diagonalize the bidiagonal form - for (k = cols - 1; k >= 0; --k) { - // loop over singular values - for (its = 0; its < MAX_ITERATIONS; ++its) { - // loop over allowed iterations - flag = 1; - - for (l = k; l >= 0; --l) { - // test for splitting - nm = l - 1; - if (fabs(rv1[l]) + anorm == anorm) { - flag = 0; - break; - } - - if (fabs((double)D[nm]) + anorm == anorm) { - break; - } - } - - if (flag) { - c = 0.0; - s = 1.0; - for (i = l; i <= k; ++i) { - f = s * rv1[i]; - if (fabs(f) + anorm != anorm) { - g = (double)D[i]; - h = pythag(f, g); - D[i] = (float)h; - h = 1.0 / h; - c = g * h; - s = (- f * h); - for (j = 0; j < rows; ++j) { - y = (double)U[j][nm]; - z = (double)U[j][i]; - U[j][nm] = (float)(y * c + z * s); - U[j][i] = (float)(z * c - y * s); - } - } - } - } - - z = (double)D[k]; - if (l == k) { - // convergence - if (z < 0.0) { - // make singular value nonnegative - D[k] = (float)(-z); - - for (j = 0; j < cols; ++j) { - V[j][k] = (-V[j][k]); - } - } - break; - } - - if (its >= MAX_ITERATIONS) { - free(rv1); - rv1 = NULL; - return "Failed to converge."; - } - - // shift from bottom 2 x 2 minor - x = (double)D[l]; - nm = k - 1; - y = (double)D[nm]; - g = rv1[nm]; - h = rv1[k]; - f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y); - g = pythag(f, 1.0); - f = ((x - z) * (x + z) + h * ((y / (f + SIGN(g, f))) - h)) / x; - - // next QR transformation - c = s = 1.0; - for (j = l; j <= nm; ++j) { - i = j + 1; - g = rv1[i]; - y = (double)D[i]; - h = s * g; - g = c * g; - z = pythag(f, h); - rv1[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 (jj = 0; jj < cols; ++jj) { - x = (double)V[jj][j]; - z = (double)V[jj][i]; - V[jj][j] = (float)(x * c + z * s); - V[jj][i] = (float)(z * c - x * s); - } - z = pythag(f, h); - D[j] = (float)z; - if (z) { - z = 1.0 / z; - c = f * z; - s = h * z; - } - f = (c * g) + (s * y); - x = (c * y) - (s * g); - for (jj = 0; jj < rows; jj++) { - y = (double)U[jj][j]; - z = (double)U[jj][i]; - U[jj][j] = (float)(y * c + z * s); - U[jj][i] = (float)(z * c - y * s); - } - } - rv1[l] = 0.0; - rv1[k] = f; - D[k] = (float)x; - } - } - - System::alignedFree(rv1); - rv1 = NULL; - - return NULL; -} - -#undef SIGN - -} diff --git a/externals/g3dlite/G3D.lib/source/Matrix3.cpp b/externals/g3dlite/G3D.lib/source/Matrix3.cpp deleted file mode 100644 index 7fb6648d3f7..00000000000 --- a/externals/g3dlite/G3D.lib/source/Matrix3.cpp +++ /dev/null @@ -1,1725 +0,0 @@ -/** - @file Matrix3.cpp - - 3x3 matrix class - - @author Morgan McGuire, graphics3d.com - - @created 2001-06-02 - @edited 2006-04-06 -*/ - -#include "G3D/platform.h" -#include -#include -#include "G3D/Matrix3.h" -#include "G3D/g3dmath.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/Quat.h" - -namespace G3D { - -const float Matrix3::EPSILON = 1e-06f; - -const Matrix3& Matrix3::zero() { - static Matrix3 m(0, 0, 0, 0, 0, 0, 0, 0, 0); - return m; -} - -const Matrix3& Matrix3::identity() { - static Matrix3 m(1, 0, 0, 0, 1, 0, 0, 0, 1); - return m; -} - - -const float Matrix3::ms_fSvdEpsilon = 1e-04f; -const int Matrix3::ms_iSvdMaxIterations = 32; - -Matrix3::Matrix3(BinaryInput& b) { - deserialize(b); -} - -bool Matrix3::fuzzyEq(const Matrix3& b) const { - for (int r = 0; r < 3; ++r) { - for (int c = 0; c < 3; ++c) { - if (! G3D::fuzzyEq(elt[r][c], b[r][c])) { - return false; - } - } - } - return true; -} - - -bool Matrix3::isOrthonormal() const { - Vector3 X = column(0); - Vector3 Y = column(1); - Vector3 Z = column(2); - - return - (G3D::fuzzyEq(X.dot(Y), 0.0f) && - G3D::fuzzyEq(Y.dot(Z), 0.0f) && - G3D::fuzzyEq(X.dot(Z), 0.0f) && - G3D::fuzzyEq(X.squaredMagnitude(), 1.0f) && - G3D::fuzzyEq(Y.squaredMagnitude(), 1.0f) && - G3D::fuzzyEq(Z.squaredMagnitude(), 1.0f)); -} - -//---------------------------------------------------------------------------- -Matrix3::Matrix3(const Quat& _q) { - // Implementation from Watt and Watt, pg 362 - // See also http://www.flipcode.com/documents/matrfaq.html#Q54 - Quat q = _q; - q.unitize(); - float xx = 2.0f * q.x * q.x; - float xy = 2.0f * q.x * q.y; - float xz = 2.0f * q.x * q.z; - float xw = 2.0f * q.x * q.w; - - float yy = 2.0f * q.y * q.y; - float yz = 2.0f * q.y * q.z; - float yw = 2.0f * q.y * q.w; - - float zz = 2.0f * q.z * q.z; - float zw = 2.0f * q.z * q.w; - - set(1.0f - yy - zz, xy - zw, xz + yw, - xy + zw, 1.0f - xx - zz, yz - xw, - xz - yw, yz + xw, 1.0f - xx - yy); -} - -//---------------------------------------------------------------------------- - -Matrix3::Matrix3 (const float aafEntry[3][3]) { - memcpy(elt, aafEntry, 9*sizeof(float)); -} - -//---------------------------------------------------------------------------- -Matrix3::Matrix3 (const Matrix3& rkMatrix) { - memcpy(elt, rkMatrix.elt, 9*sizeof(float)); -} - -//---------------------------------------------------------------------------- -Matrix3::Matrix3( - float fEntry00, float fEntry01, float fEntry02, - float fEntry10, float fEntry11, float fEntry12, - float fEntry20, float fEntry21, float fEntry22) { - set(fEntry00, fEntry01, fEntry02, - fEntry10, fEntry11, fEntry12, - fEntry20, fEntry21, fEntry22); -} - -void Matrix3::set( - float fEntry00, float fEntry01, float fEntry02, - float fEntry10, float fEntry11, float fEntry12, - float fEntry20, float fEntry21, float fEntry22) { - - elt[0][0] = fEntry00; - elt[0][1] = fEntry01; - elt[0][2] = fEntry02; - elt[1][0] = fEntry10; - elt[1][1] = fEntry11; - elt[1][2] = fEntry12; - elt[2][0] = fEntry20; - elt[2][1] = fEntry21; - elt[2][2] = fEntry22; -} - - -void Matrix3::deserialize(BinaryInput& b) { - int r,c; - for (c = 0; c < 3; ++c) { - for (r = 0; r < 3; ++r) { - elt[r][c] = b.readFloat32(); - } - } -} - - -void Matrix3::serialize(BinaryOutput& b) const { - int r,c; - for (c = 0; c < 3; ++c) { - for (r = 0; r < 3; ++r) { - b.writeFloat32(elt[r][c]); - } - } -} - - -//---------------------------------------------------------------------------- -Vector3 Matrix3::column (int iCol) const { - assert((0 <= iCol) && (iCol < 3)); - return Vector3(elt[0][iCol], elt[1][iCol], - elt[2][iCol]); -} - -const Vector3& Matrix3::row (int iRow) const { - assert((0 <= iRow) && (iRow < 3)); - return *reinterpret_cast(elt[iRow]); -} - - -Vector3 Matrix3::getColumn (int iCol) const { - assert((0 <= iCol) && (iCol < 3)); - return Vector3(elt[0][iCol], elt[1][iCol], - elt[2][iCol]); -} - -Vector3 Matrix3::getRow (int iRow) const { - return Vector3(elt[iRow][0], elt[iRow][1], elt[iRow][2]); -} - -void Matrix3::setColumn(int iCol, const Vector3 &vector) { - debugAssert((iCol >= 0) && (iCol < 3)); - elt[0][iCol] = vector.x; - elt[1][iCol] = vector.y; - elt[2][iCol] = vector.z; -} - - -void Matrix3::setRow(int iRow, const Vector3 &vector) { - debugAssert((iRow >= 0) && (iRow < 3)); - elt[iRow][0] = vector.x; - elt[iRow][1] = vector.y; - elt[iRow][2] = vector.z; -} - - -//---------------------------------------------------------------------------- -bool Matrix3::operator== (const Matrix3& rkMatrix) const { - for (int iRow = 0; iRow < 3; iRow++) { - for (int iCol = 0; iCol < 3; iCol++) { - if ( elt[iRow][iCol] != rkMatrix.elt[iRow][iCol] ) - return false; - } - } - - return true; -} - -//---------------------------------------------------------------------------- -bool Matrix3::operator!= (const Matrix3& rkMatrix) const { - return !operator==(rkMatrix); -} - -//---------------------------------------------------------------------------- -Matrix3 Matrix3::operator+ (const Matrix3& rkMatrix) const { - Matrix3 kSum; - - for (int iRow = 0; iRow < 3; iRow++) { - for (int iCol = 0; iCol < 3; iCol++) { - kSum.elt[iRow][iCol] = elt[iRow][iCol] + - rkMatrix.elt[iRow][iCol]; - } - } - - return kSum; -} - -//---------------------------------------------------------------------------- -Matrix3 Matrix3::operator- (const Matrix3& rkMatrix) const { - Matrix3 kDiff; - - for (int iRow = 0; iRow < 3; iRow++) { - for (int iCol = 0; iCol < 3; iCol++) { - kDiff.elt[iRow][iCol] = elt[iRow][iCol] - - rkMatrix.elt[iRow][iCol]; - } - } - - return kDiff; -} - -//---------------------------------------------------------------------------- -Matrix3 Matrix3::operator* (const Matrix3& rkMatrix) const { - Matrix3 kProd; - - for (int iRow = 0; iRow < 3; iRow++) { - for (int iCol = 0; iCol < 3; iCol++) { - kProd.elt[iRow][iCol] = - elt[iRow][0] * rkMatrix.elt[0][iCol] + - elt[iRow][1] * rkMatrix.elt[1][iCol] + - elt[iRow][2] * rkMatrix.elt[2][iCol]; - } - } - - return kProd; -} - -Matrix3& Matrix3::operator+= (const Matrix3& rkMatrix) { - for (int iRow = 0; iRow < 3; iRow++) { - for (int iCol = 0; iCol < 3; iCol++) { - elt[iRow][iCol] = elt[iRow][iCol] + rkMatrix.elt[iRow][iCol]; - } - } - - return *this; -} - -Matrix3& Matrix3::operator-= (const Matrix3& rkMatrix) { - for (int iRow = 0; iRow < 3; iRow++) { - for (int iCol = 0; iCol < 3; iCol++) { - elt[iRow][iCol] = elt[iRow][iCol] - rkMatrix.elt[iRow][iCol]; - } - } - - return *this; -} - -Matrix3& Matrix3::operator*= (const Matrix3& rkMatrix) { - Matrix3 mulMat; - for (int iRow = 0; iRow < 3; iRow++) { - for (int iCol = 0; iCol < 3; iCol++) { - mulMat.elt[iRow][iCol] = - elt[iRow][0] * rkMatrix.elt[0][iCol] + - elt[iRow][1] * rkMatrix.elt[1][iCol] + - elt[iRow][2] * rkMatrix.elt[2][iCol]; - } - } - - *this = mulMat; - return *this; -} - -//---------------------------------------------------------------------------- -Matrix3 Matrix3::operator- () const { - Matrix3 kNeg; - - for (int iRow = 0; iRow < 3; iRow++) { - for (int iCol = 0; iCol < 3; iCol++) { - kNeg[iRow][iCol] = -elt[iRow][iCol]; - } - } - - return kNeg; -} - -//---------------------------------------------------------------------------- -Matrix3 Matrix3::operator* (float fScalar) const { - Matrix3 kProd; - - for (int iRow = 0; iRow < 3; iRow++) { - for (int iCol = 0; iCol < 3; iCol++) { - kProd[iRow][iCol] = fScalar * elt[iRow][iCol]; - } - } - - return kProd; -} - -//---------------------------------------------------------------------------- -Matrix3 operator* (double fScalar, const Matrix3& rkMatrix) { - Matrix3 kProd; - - for (int iRow = 0; iRow < 3; iRow++) { - for (int iCol = 0; iCol < 3; iCol++) { - kProd[iRow][iCol] = fScalar * rkMatrix.elt[iRow][iCol]; - } - } - - return kProd; -} - -Matrix3 operator* (float fScalar, const Matrix3& rkMatrix) { - return (double)fScalar * rkMatrix; -} - - -Matrix3 operator* (int fScalar, const Matrix3& rkMatrix) { - return (double)fScalar * rkMatrix; -} -//---------------------------------------------------------------------------- -Matrix3 Matrix3::transpose () const { - Matrix3 kTranspose; - - for (int iRow = 0; iRow < 3; iRow++) { - for (int iCol = 0; iCol < 3; iCol++) { - kTranspose[iRow][iCol] = elt[iCol][iRow]; - } - } - - return kTranspose; -} - -//---------------------------------------------------------------------------- -bool Matrix3::inverse (Matrix3& rkInverse, float fTolerance) const { - // Invert a 3x3 using cofactors. This is about 8 times faster than - // the Numerical Recipes code which uses Gaussian elimination. - - rkInverse[0][0] = elt[1][1] * elt[2][2] - - elt[1][2] * elt[2][1]; - rkInverse[0][1] = elt[0][2] * elt[2][1] - - elt[0][1] * elt[2][2]; - rkInverse[0][2] = elt[0][1] * elt[1][2] - - elt[0][2] * elt[1][1]; - rkInverse[1][0] = elt[1][2] * elt[2][0] - - elt[1][0] * elt[2][2]; - rkInverse[1][1] = elt[0][0] * elt[2][2] - - elt[0][2] * elt[2][0]; - rkInverse[1][2] = elt[0][2] * elt[1][0] - - elt[0][0] * elt[1][2]; - rkInverse[2][0] = elt[1][0] * elt[2][1] - - elt[1][1] * elt[2][0]; - rkInverse[2][1] = elt[0][1] * elt[2][0] - - elt[0][0] * elt[2][1]; - rkInverse[2][2] = elt[0][0] * elt[1][1] - - elt[0][1] * elt[1][0]; - - float fDet = - elt[0][0] * rkInverse[0][0] + - elt[0][1] * rkInverse[1][0] + - elt[0][2] * rkInverse[2][0]; - - if ( G3D::abs(fDet) <= fTolerance ) - return false; - - float fInvDet = 1.0 / fDet; - - for (int iRow = 0; iRow < 3; iRow++) { - for (int iCol = 0; iCol < 3; iCol++) - rkInverse[iRow][iCol] *= fInvDet; - } - - return true; -} - -//---------------------------------------------------------------------------- -Matrix3 Matrix3::inverse (float fTolerance) const { - Matrix3 kInverse = Matrix3::zero(); - inverse(kInverse, fTolerance); - return kInverse; -} - -//---------------------------------------------------------------------------- -float Matrix3::determinant () const { - float fCofactor00 = elt[1][1] * elt[2][2] - - elt[1][2] * elt[2][1]; - float fCofactor10 = elt[1][2] * elt[2][0] - - elt[1][0] * elt[2][2]; - float fCofactor20 = elt[1][0] * elt[2][1] - - elt[1][1] * elt[2][0]; - - float fDet = - elt[0][0] * fCofactor00 + - elt[0][1] * fCofactor10 + - elt[0][2] * fCofactor20; - - return fDet; -} - -//---------------------------------------------------------------------------- -void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL, - Matrix3& kR) { - float afV[3], afW[3]; - float fLength, fSign, fT1, fInvT1, fT2; - bool bIdentity; - - // map first column to (*,0,0) - fLength = sqrt(kA[0][0] * kA[0][0] + kA[1][0] * kA[1][0] + - kA[2][0] * kA[2][0]); - - if ( fLength > 0.0 ) { - fSign = (kA[0][0] > 0.0 ? 1.0 : -1.0); - fT1 = kA[0][0] + fSign * fLength; - fInvT1 = 1.0 / fT1; - afV[1] = kA[1][0] * fInvT1; - afV[2] = kA[2][0] * fInvT1; - - fT2 = -2.0 / (1.0 + afV[1] * afV[1] + afV[2] * afV[2]); - afW[0] = fT2 * (kA[0][0] + kA[1][0] * afV[1] + kA[2][0] * afV[2]); - afW[1] = fT2 * (kA[0][1] + kA[1][1] * afV[1] + kA[2][1] * afV[2]); - afW[2] = fT2 * (kA[0][2] + kA[1][2] * afV[1] + kA[2][2] * afV[2]); - kA[0][0] += afW[0]; - kA[0][1] += afW[1]; - kA[0][2] += afW[2]; - kA[1][1] += afV[1] * afW[1]; - kA[1][2] += afV[1] * afW[2]; - kA[2][1] += afV[2] * afW[1]; - kA[2][2] += afV[2] * afW[2]; - - kL[0][0] = 1.0 + fT2; - kL[0][1] = kL[1][0] = fT2 * afV[1]; - kL[0][2] = kL[2][0] = fT2 * afV[2]; - kL[1][1] = 1.0 + fT2 * afV[1] * afV[1]; - kL[1][2] = kL[2][1] = fT2 * afV[1] * afV[2]; - kL[2][2] = 1.0 + fT2 * afV[2] * afV[2]; - bIdentity = false; - } else { - kL = Matrix3::identity(); - bIdentity = true; - } - - // map first row to (*,*,0) - fLength = sqrt(kA[0][1] * kA[0][1] + kA[0][2] * kA[0][2]); - - if ( fLength > 0.0 ) { - fSign = (kA[0][1] > 0.0 ? 1.0 : -1.0); - fT1 = kA[0][1] + fSign * fLength; - afV[2] = kA[0][2] / fT1; - - fT2 = -2.0 / (1.0 + afV[2] * afV[2]); - afW[0] = fT2 * (kA[0][1] + kA[0][2] * afV[2]); - afW[1] = fT2 * (kA[1][1] + kA[1][2] * afV[2]); - afW[2] = fT2 * (kA[2][1] + kA[2][2] * afV[2]); - kA[0][1] += afW[0]; - kA[1][1] += afW[1]; - kA[1][2] += afW[1] * afV[2]; - kA[2][1] += afW[2]; - kA[2][2] += afW[2] * afV[2]; - - kR[0][0] = 1.0; - kR[0][1] = kR[1][0] = 0.0; - kR[0][2] = kR[2][0] = 0.0; - kR[1][1] = 1.0 + fT2; - kR[1][2] = kR[2][1] = fT2 * afV[2]; - kR[2][2] = 1.0 + fT2 * afV[2] * afV[2]; - } else { - kR = Matrix3::identity(); - } - - // map second column to (*,*,0) - fLength = sqrt(kA[1][1] * kA[1][1] + kA[2][1] * kA[2][1]); - - if ( fLength > 0.0 ) { - fSign = (kA[1][1] > 0.0 ? 1.0 : -1.0); - fT1 = kA[1][1] + fSign * fLength; - afV[2] = kA[2][1] / fT1; - - fT2 = -2.0 / (1.0 + afV[2] * afV[2]); - afW[1] = fT2 * (kA[1][1] + kA[2][1] * afV[2]); - afW[2] = fT2 * (kA[1][2] + kA[2][2] * afV[2]); - kA[1][1] += afW[1]; - kA[1][2] += afW[2]; - kA[2][2] += afV[2] * afW[2]; - - float fA = 1.0 + fT2; - float fB = fT2 * afV[2]; - float fC = 1.0 + fB * afV[2]; - - if ( bIdentity ) { - kL[0][0] = 1.0; - kL[0][1] = kL[1][0] = 0.0; - kL[0][2] = kL[2][0] = 0.0; - kL[1][1] = fA; - kL[1][2] = kL[2][1] = fB; - kL[2][2] = fC; - } else { - for (int iRow = 0; iRow < 3; iRow++) { - float fTmp0 = kL[iRow][1]; - float fTmp1 = kL[iRow][2]; - kL[iRow][1] = fA * fTmp0 + fB * fTmp1; - kL[iRow][2] = fB * fTmp0 + fC * fTmp1; - } - } - } -} - -//---------------------------------------------------------------------------- -void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL, - Matrix3& kR) { - float fT11 = kA[0][1] * kA[0][1] + kA[1][1] * kA[1][1]; - float fT22 = kA[1][2] * kA[1][2] + kA[2][2] * kA[2][2]; - float fT12 = kA[1][1] * kA[1][2]; - float fTrace = fT11 + fT22; - float fDiff = fT11 - fT22; - float fDiscr = sqrt(fDiff * fDiff + 4.0 * fT12 * fT12); - float fRoot1 = 0.5 * (fTrace + fDiscr); - float fRoot2 = 0.5 * (fTrace - fDiscr); - - // adjust right - float fY = kA[0][0] - (G3D::abs(fRoot1 - fT22) <= - G3D::abs(fRoot2 - fT22) ? fRoot1 : fRoot2); - float fZ = kA[0][1]; - float fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ); - float fSin = fZ * fInvLength; - float fCos = -fY * fInvLength; - - float fTmp0 = kA[0][0]; - float fTmp1 = kA[0][1]; - kA[0][0] = fCos * fTmp0 - fSin * fTmp1; - kA[0][1] = fSin * fTmp0 + fCos * fTmp1; - kA[1][0] = -fSin * kA[1][1]; - kA[1][1] *= fCos; - - int iRow; - - for (iRow = 0; iRow < 3; iRow++) { - fTmp0 = kR[0][iRow]; - fTmp1 = kR[1][iRow]; - kR[0][iRow] = fCos * fTmp0 - fSin * fTmp1; - kR[1][iRow] = fSin * fTmp0 + fCos * fTmp1; - } - - // adjust left - fY = kA[0][0]; - - fZ = kA[1][0]; - - fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ); - - fSin = fZ * fInvLength; - - fCos = -fY * fInvLength; - - kA[0][0] = fCos * kA[0][0] - fSin * kA[1][0]; - - fTmp0 = kA[0][1]; - - fTmp1 = kA[1][1]; - - kA[0][1] = fCos * fTmp0 - fSin * fTmp1; - - kA[1][1] = fSin * fTmp0 + fCos * fTmp1; - - kA[0][2] = -fSin * kA[1][2]; - - kA[1][2] *= fCos; - - int iCol; - - for (iCol = 0; iCol < 3; iCol++) { - fTmp0 = kL[iCol][0]; - fTmp1 = kL[iCol][1]; - kL[iCol][0] = fCos * fTmp0 - fSin * fTmp1; - kL[iCol][1] = fSin * fTmp0 + fCos * fTmp1; - } - - // adjust right - fY = kA[0][1]; - - fZ = kA[0][2]; - - fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ); - - fSin = fZ * fInvLength; - - fCos = -fY * fInvLength; - - kA[0][1] = fCos * kA[0][1] - fSin * kA[0][2]; - - fTmp0 = kA[1][1]; - - fTmp1 = kA[1][2]; - - kA[1][1] = fCos * fTmp0 - fSin * fTmp1; - - kA[1][2] = fSin * fTmp0 + fCos * fTmp1; - - kA[2][1] = -fSin * kA[2][2]; - - kA[2][2] *= fCos; - - for (iRow = 0; iRow < 3; iRow++) { - fTmp0 = kR[1][iRow]; - fTmp1 = kR[2][iRow]; - kR[1][iRow] = fCos * fTmp0 - fSin * fTmp1; - kR[2][iRow] = fSin * fTmp0 + fCos * fTmp1; - } - - // adjust left - fY = kA[1][1]; - - fZ = kA[2][1]; - - fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ); - - fSin = fZ * fInvLength; - - fCos = -fY * fInvLength; - - kA[1][1] = fCos * kA[1][1] - fSin * kA[2][1]; - - fTmp0 = kA[1][2]; - - fTmp1 = kA[2][2]; - - kA[1][2] = fCos * fTmp0 - fSin * fTmp1; - - kA[2][2] = fSin * fTmp0 + fCos * fTmp1; - - for (iCol = 0; iCol < 3; iCol++) { - fTmp0 = kL[iCol][1]; - fTmp1 = kL[iCol][2]; - kL[iCol][1] = fCos * fTmp0 - fSin * fTmp1; - kL[iCol][2] = fSin * fTmp0 + fCos * fTmp1; - } -} - -//---------------------------------------------------------------------------- -void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS, - Matrix3& kR) const { - int iRow, iCol; - - Matrix3 kA = *this; - bidiagonalize(kA, kL, kR); - - for (int i = 0; i < ms_iSvdMaxIterations; i++) { - float fTmp, fTmp0, fTmp1; - float fSin0, fCos0, fTan0; - float fSin1, fCos1, fTan1; - - bool bTest1 = (G3D::abs(kA[0][1]) <= - ms_fSvdEpsilon * (G3D::abs(kA[0][0]) + G3D::abs(kA[1][1]))); - bool bTest2 = (G3D::abs(kA[1][2]) <= - ms_fSvdEpsilon * (G3D::abs(kA[1][1]) + G3D::abs(kA[2][2]))); - - if ( bTest1 ) { - if ( bTest2 ) { - kS[0] = kA[0][0]; - kS[1] = kA[1][1]; - kS[2] = kA[2][2]; - break; - } else { - // 2x2 closed form factorization - fTmp = (kA[1][1] * kA[1][1] - kA[2][2] * kA[2][2] + - kA[1][2] * kA[1][2]) / (kA[1][2] * kA[2][2]); - fTan0 = 0.5 * (fTmp + sqrt(fTmp * fTmp + 4.0)); - fCos0 = 1.0 / sqrt(1.0 + fTan0 * fTan0); - fSin0 = fTan0 * fCos0; - - for (iCol = 0; iCol < 3; iCol++) { - fTmp0 = kL[iCol][1]; - fTmp1 = kL[iCol][2]; - kL[iCol][1] = fCos0 * fTmp0 - fSin0 * fTmp1; - kL[iCol][2] = fSin0 * fTmp0 + fCos0 * fTmp1; - } - - fTan1 = (kA[1][2] - kA[2][2] * fTan0) / kA[1][1]; - fCos1 = 1.0 / sqrt(1.0 + fTan1 * fTan1); - fSin1 = -fTan1 * fCos1; - - for (iRow = 0; iRow < 3; iRow++) { - fTmp0 = kR[1][iRow]; - fTmp1 = kR[2][iRow]; - kR[1][iRow] = fCos1 * fTmp0 - fSin1 * fTmp1; - kR[2][iRow] = fSin1 * fTmp0 + fCos1 * fTmp1; - } - - kS[0] = kA[0][0]; - kS[1] = fCos0 * fCos1 * kA[1][1] - - fSin1 * (fCos0 * kA[1][2] - fSin0 * kA[2][2]); - kS[2] = fSin0 * fSin1 * kA[1][1] + - fCos1 * (fSin0 * kA[1][2] + fCos0 * kA[2][2]); - break; - } - } else { - if ( bTest2 ) { - // 2x2 closed form factorization - fTmp = (kA[0][0] * kA[0][0] + kA[1][1] * kA[1][1] - - kA[0][1] * kA[0][1]) / (kA[0][1] * kA[1][1]); - fTan0 = 0.5 * ( -fTmp + sqrt(fTmp * fTmp + 4.0)); - fCos0 = 1.0 / sqrt(1.0 + fTan0 * fTan0); - fSin0 = fTan0 * fCos0; - - for (iCol = 0; iCol < 3; iCol++) { - fTmp0 = kL[iCol][0]; - fTmp1 = kL[iCol][1]; - kL[iCol][0] = fCos0 * fTmp0 - fSin0 * fTmp1; - kL[iCol][1] = fSin0 * fTmp0 + fCos0 * fTmp1; - } - - fTan1 = (kA[0][1] - kA[1][1] * fTan0) / kA[0][0]; - fCos1 = 1.0 / sqrt(1.0 + fTan1 * fTan1); - fSin1 = -fTan1 * fCos1; - - for (iRow = 0; iRow < 3; iRow++) { - fTmp0 = kR[0][iRow]; - fTmp1 = kR[1][iRow]; - kR[0][iRow] = fCos1 * fTmp0 - fSin1 * fTmp1; - kR[1][iRow] = fSin1 * fTmp0 + fCos1 * fTmp1; - } - - kS[0] = fCos0 * fCos1 * kA[0][0] - - fSin1 * (fCos0 * kA[0][1] - fSin0 * kA[1][1]); - kS[1] = fSin0 * fSin1 * kA[0][0] + - fCos1 * (fSin0 * kA[0][1] + fCos0 * kA[1][1]); - kS[2] = kA[2][2]; - break; - } else { - golubKahanStep(kA, kL, kR); - } - } - } - - // positize diagonal - for (iRow = 0; iRow < 3; iRow++) { - if ( kS[iRow] < 0.0 ) { - kS[iRow] = -kS[iRow]; - - for (iCol = 0; iCol < 3; iCol++) - kR[iRow][iCol] = -kR[iRow][iCol]; - } - } -} - -//---------------------------------------------------------------------------- -void Matrix3::singularValueComposition (const Matrix3& kL, - const Vector3& kS, const Matrix3& kR) { - int iRow, iCol; - Matrix3 kTmp; - - // product S*R - for (iRow = 0; iRow < 3; iRow++) { - for (iCol = 0; iCol < 3; iCol++) - kTmp[iRow][iCol] = kS[iRow] * kR[iRow][iCol]; - } - - // product L*S*R - for (iRow = 0; iRow < 3; iRow++) { - for (iCol = 0; iCol < 3; iCol++) { - elt[iRow][iCol] = 0.0; - - for (int iMid = 0; iMid < 3; iMid++) - elt[iRow][iCol] += kL[iRow][iMid] * kTmp[iMid][iCol]; - } - } -} - -//---------------------------------------------------------------------------- -void Matrix3::orthonormalize () { - // Algorithm uses Gram-Schmidt orthogonalization. If 'this' matrix is - // M = [m0|m1|m2], then orthonormal output matrix is Q = [q0|q1|q2], - // - // q0 = m0/|m0| - // q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0| - // q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1| - // - // where |V| indicates length of vector V and A*B indicates dot - // product of vectors A and B. - - // compute q0 - float fInvLength = 1.0 / sqrt(elt[0][0] * elt[0][0] - + elt[1][0] * elt[1][0] + - elt[2][0] * elt[2][0]); - - elt[0][0] *= fInvLength; - elt[1][0] *= fInvLength; - elt[2][0] *= fInvLength; - - // compute q1 - float fDot0 = - elt[0][0] * elt[0][1] + - elt[1][0] * elt[1][1] + - elt[2][0] * elt[2][1]; - - elt[0][1] -= fDot0 * elt[0][0]; - elt[1][1] -= fDot0 * elt[1][0]; - elt[2][1] -= fDot0 * elt[2][0]; - - fInvLength = 1.0 / sqrt(elt[0][1] * elt[0][1] + - elt[1][1] * elt[1][1] + - elt[2][1] * elt[2][1]); - - elt[0][1] *= fInvLength; - elt[1][1] *= fInvLength; - elt[2][1] *= fInvLength; - - // compute q2 - float fDot1 = - elt[0][1] * elt[0][2] + - elt[1][1] * elt[1][2] + - elt[2][1] * elt[2][2]; - - fDot0 = - elt[0][0] * elt[0][2] + - elt[1][0] * elt[1][2] + - elt[2][0] * elt[2][2]; - - elt[0][2] -= fDot0 * elt[0][0] + fDot1 * elt[0][1]; - elt[1][2] -= fDot0 * elt[1][0] + fDot1 * elt[1][1]; - elt[2][2] -= fDot0 * elt[2][0] + fDot1 * elt[2][1]; - - fInvLength = 1.0 / sqrt(elt[0][2] * elt[0][2] + - elt[1][2] * elt[1][2] + - elt[2][2] * elt[2][2]); - - elt[0][2] *= fInvLength; - elt[1][2] *= fInvLength; - elt[2][2] *= fInvLength; -} - -//---------------------------------------------------------------------------- -void Matrix3::qDUDecomposition (Matrix3& kQ, - Vector3& kD, Vector3& kU) const { - // Factor M = QR = QDU where Q is orthogonal, D is diagonal, - // and U is upper triangular with ones on its diagonal. Algorithm uses - // Gram-Schmidt orthogonalization (the QR algorithm). - // - // If M = [ m0 | m1 | m2 ] and Q = [ q0 | q1 | q2 ], then - // - // q0 = m0/|m0| - // q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0| - // q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1| - // - // where |V| indicates length of vector V and A*B indicates dot - // product of vectors A and B. The matrix R has entries - // - // r00 = q0*m0 r01 = q0*m1 r02 = q0*m2 - // r10 = 0 r11 = q1*m1 r12 = q1*m2 - // r20 = 0 r21 = 0 r22 = q2*m2 - // - // so D = diag(r00,r11,r22) and U has entries u01 = r01/r00, - // u02 = r02/r00, and u12 = r12/r11. - - // Q = rotation - // D = scaling - // U = shear - - // D stores the three diagonal entries r00, r11, r22 - // U stores the entries U[0] = u01, U[1] = u02, U[2] = u12 - - // build orthogonal matrix Q - float fInvLength = 1.0 / sqrt(elt[0][0] * elt[0][0] - + elt[1][0] * elt[1][0] + - elt[2][0] * elt[2][0]); - kQ[0][0] = elt[0][0] * fInvLength; - kQ[1][0] = elt[1][0] * fInvLength; - kQ[2][0] = elt[2][0] * fInvLength; - - float fDot = kQ[0][0] * elt[0][1] + kQ[1][0] * elt[1][1] + - kQ[2][0] * elt[2][1]; - kQ[0][1] = elt[0][1] - fDot * kQ[0][0]; - kQ[1][1] = elt[1][1] - fDot * kQ[1][0]; - kQ[2][1] = elt[2][1] - fDot * kQ[2][0]; - fInvLength = 1.0 / sqrt(kQ[0][1] * kQ[0][1] + kQ[1][1] * kQ[1][1] + - kQ[2][1] * kQ[2][1]); - kQ[0][1] *= fInvLength; - kQ[1][1] *= fInvLength; - kQ[2][1] *= fInvLength; - - fDot = kQ[0][0] * elt[0][2] + kQ[1][0] * elt[1][2] + - kQ[2][0] * elt[2][2]; - kQ[0][2] = elt[0][2] - fDot * kQ[0][0]; - kQ[1][2] = elt[1][2] - fDot * kQ[1][0]; - kQ[2][2] = elt[2][2] - fDot * kQ[2][0]; - fDot = kQ[0][1] * elt[0][2] + kQ[1][1] * elt[1][2] + - kQ[2][1] * elt[2][2]; - kQ[0][2] -= fDot * kQ[0][1]; - kQ[1][2] -= fDot * kQ[1][1]; - kQ[2][2] -= fDot * kQ[2][1]; - fInvLength = 1.0 / sqrt(kQ[0][2] * kQ[0][2] + kQ[1][2] * kQ[1][2] + - kQ[2][2] * kQ[2][2]); - kQ[0][2] *= fInvLength; - kQ[1][2] *= fInvLength; - kQ[2][2] *= fInvLength; - - // guarantee that orthogonal matrix has determinant 1 (no reflections) - float fDet = kQ[0][0] * kQ[1][1] * kQ[2][2] + kQ[0][1] * kQ[1][2] * kQ[2][0] + - kQ[0][2] * kQ[1][0] * kQ[2][1] - kQ[0][2] * kQ[1][1] * kQ[2][0] - - kQ[0][1] * kQ[1][0] * kQ[2][2] - kQ[0][0] * kQ[1][2] * kQ[2][1]; - - if ( fDet < 0.0 ) { - for (int iRow = 0; iRow < 3; iRow++) - for (int iCol = 0; iCol < 3; iCol++) - kQ[iRow][iCol] = -kQ[iRow][iCol]; - } - - // build "right" matrix R - Matrix3 kR; - - kR[0][0] = kQ[0][0] * elt[0][0] + kQ[1][0] * elt[1][0] + - kQ[2][0] * elt[2][0]; - - kR[0][1] = kQ[0][0] * elt[0][1] + kQ[1][0] * elt[1][1] + - kQ[2][0] * elt[2][1]; - - kR[1][1] = kQ[0][1] * elt[0][1] + kQ[1][1] * elt[1][1] + - kQ[2][1] * elt[2][1]; - - kR[0][2] = kQ[0][0] * elt[0][2] + kQ[1][0] * elt[1][2] + - kQ[2][0] * elt[2][2]; - - kR[1][2] = kQ[0][1] * elt[0][2] + kQ[1][1] * elt[1][2] + - kQ[2][1] * elt[2][2]; - - kR[2][2] = kQ[0][2] * elt[0][2] + kQ[1][2] * elt[1][2] + - kQ[2][2] * elt[2][2]; - - // the scaling component - kD[0] = kR[0][0]; - - kD[1] = kR[1][1]; - - kD[2] = kR[2][2]; - - // the shear component - float fInvD0 = 1.0 / kD[0]; - - kU[0] = kR[0][1] * fInvD0; - - kU[1] = kR[0][2] * fInvD0; - - kU[2] = kR[1][2] / kD[1]; -} - -//---------------------------------------------------------------------------- -float Matrix3::maxCubicRoot (float afCoeff[3]) { - // Spectral norm is for A^T*A, so characteristic polynomial - // P(x) = c[0]+c[1]*x+c[2]*x^2+x^3 has three positive float roots. - // This yields the assertions c[0] < 0 and c[2]*c[2] >= 3*c[1]. - - // quick out for uniform scale (triple root) - const float fOneThird = 1.0f / 3.0f; - const float fEpsilon = 1e-06f; - float fDiscr = afCoeff[2] * afCoeff[2] - 3.0f * afCoeff[1]; - - if ( fDiscr <= fEpsilon ) - return -fOneThird*afCoeff[2]; - - // Compute an upper bound on roots of P(x). This assumes that A^T*A - // has been scaled by its largest entry. - float fX = 1.0f; - - float fPoly = afCoeff[0] + fX * (afCoeff[1] + fX * (afCoeff[2] + fX)); - - if ( fPoly < 0.0f ) { - // uses a matrix norm to find an upper bound on maximum root - fX = G3D::abs(afCoeff[0]); - float fTmp = 1.0 + G3D::abs(afCoeff[1]); - - if ( fTmp > fX ) - fX = fTmp; - - fTmp = 1.0 + G3D::abs(afCoeff[2]); - - if ( fTmp > fX ) - fX = fTmp; - } - - // Newton's method to find root - float fTwoC2 = 2.0f * afCoeff[2]; - - for (int i = 0; i < 16; i++) { - fPoly = afCoeff[0] + fX * (afCoeff[1] + fX * (afCoeff[2] + fX)); - - if ( G3D::abs(fPoly) <= fEpsilon ) - return fX; - - float fDeriv = afCoeff[1] + fX * (fTwoC2 + 3.0f * fX); - - fX -= fPoly / fDeriv; - } - - return fX; -} - -//---------------------------------------------------------------------------- -float Matrix3::spectralNorm () const { - Matrix3 kP; - int iRow, iCol; - float fPmax = 0.0; - - for (iRow = 0; iRow < 3; iRow++) { - for (iCol = 0; iCol < 3; iCol++) { - kP[iRow][iCol] = 0.0; - - for (int iMid = 0; iMid < 3; iMid++) { - kP[iRow][iCol] += - elt[iMid][iRow] * elt[iMid][iCol]; - } - - if ( kP[iRow][iCol] > fPmax ) - fPmax = kP[iRow][iCol]; - } - } - - float fInvPmax = 1.0 / fPmax; - - for (iRow = 0; iRow < 3; iRow++) { - for (iCol = 0; iCol < 3; iCol++) - kP[iRow][iCol] *= fInvPmax; - } - - float afCoeff[3]; - afCoeff[0] = -(kP[0][0] * (kP[1][1] * kP[2][2] - kP[1][2] * kP[2][1]) + - kP[0][1] * (kP[2][0] * kP[1][2] - kP[1][0] * kP[2][2]) + - kP[0][2] * (kP[1][0] * kP[2][1] - kP[2][0] * kP[1][1])); - afCoeff[1] = kP[0][0] * kP[1][1] - kP[0][1] * kP[1][0] + - kP[0][0] * kP[2][2] - kP[0][2] * kP[2][0] + - kP[1][1] * kP[2][2] - kP[1][2] * kP[2][1]; - afCoeff[2] = -(kP[0][0] + kP[1][1] + kP[2][2]); - - float fRoot = maxCubicRoot(afCoeff); - float fNorm = sqrt(fPmax * fRoot); - return fNorm; -} - -//---------------------------------------------------------------------------- -void Matrix3::toAxisAngle (Vector3& rkAxis, float& rfRadians) const { - // - // Let (x,y,z) be the unit-length axis and let A be an angle of rotation. - // The rotation matrix is R = I + sin(A)*P + (1-cos(A))*P^2 (Rodrigues' formula) where - // I is the identity and - // - // +- -+ - // P = | 0 -z +y | - // | +z 0 -x | - // | -y +x 0 | - // +- -+ - // - // If A > 0, R represents a counterclockwise rotation about the axis in - // the sense of looking from the tip of the axis vector towards the - // origin. Some algebra will show that - // - // cos(A) = (trace(R)-1)/2 and R - R^t = 2*sin(A)*P - // - // In the event that A = pi, R-R^t = 0 which prevents us from extracting - // the axis through P. Instead note that R = I+2*P^2 when A = pi, so - // P^2 = (R-I)/2. The diagonal entries of P^2 are x^2-1, y^2-1, and - // z^2-1. We can solve these for axis (x,y,z). Because the angle is pi, - // it does not matter which sign you choose on the square roots. - - float fTrace = elt[0][0] + elt[1][1] + elt[2][2]; - float fCos = 0.5f * (fTrace - 1.0f); - rfRadians = G3D::aCos(fCos); // in [0,PI] - - if ( rfRadians > 0.0 ) { - if ( rfRadians < pi() ) { - rkAxis.x = elt[2][1] - elt[1][2]; - rkAxis.y = elt[0][2] - elt[2][0]; - rkAxis.z = elt[1][0] - elt[0][1]; - rkAxis.unitize(); - } else { - // angle is PI - float fHalfInverse; - - if ( elt[0][0] >= elt[1][1] ) { - // r00 >= r11 - if ( elt[0][0] >= elt[2][2] ) { - // r00 is maximum diagonal term - rkAxis.x = 0.5 * sqrt(elt[0][0] - - elt[1][1] - elt[2][2] + 1.0); - fHalfInverse = 0.5 / rkAxis.x; - rkAxis.y = fHalfInverse * elt[0][1]; - rkAxis.z = fHalfInverse * elt[0][2]; - } else { - // r22 is maximum diagonal term - rkAxis.z = 0.5 * sqrt(elt[2][2] - - elt[0][0] - elt[1][1] + 1.0); - fHalfInverse = 0.5 / rkAxis.z; - rkAxis.x = fHalfInverse * elt[0][2]; - rkAxis.y = fHalfInverse * elt[1][2]; - } - } else { - // r11 > r00 - if ( elt[1][1] >= elt[2][2] ) { - // r11 is maximum diagonal term - rkAxis.y = 0.5 * sqrt(elt[1][1] - - elt[0][0] - elt[2][2] + 1.0); - fHalfInverse = 0.5 / rkAxis.y; - rkAxis.x = fHalfInverse * elt[0][1]; - rkAxis.z = fHalfInverse * elt[1][2]; - } else { - // r22 is maximum diagonal term - rkAxis.z = 0.5 * sqrt(elt[2][2] - - elt[0][0] - elt[1][1] + 1.0); - fHalfInverse = 0.5 / rkAxis.z; - rkAxis.x = fHalfInverse * elt[0][2]; - rkAxis.y = fHalfInverse * elt[1][2]; - } - } - } - } else { - // The angle is 0 and the matrix is the identity. Any axis will - // work, so just use the x-axis. - rkAxis.x = 1.0; - rkAxis.y = 0.0; - rkAxis.z = 0.0; - } -} - -//---------------------------------------------------------------------------- -Matrix3 Matrix3::fromAxisAngle (const Vector3& _axis, float fRadians) { - Vector3 axis = _axis.direction(); - - Matrix3 m; - float fCos = cos(fRadians); - float fSin = sin(fRadians); - float fOneMinusCos = 1.0 - fCos; - float fX2 = square(axis.x); - float fY2 = square(axis.y); - float fZ2 = square(axis.z); - float fXYM = axis.x * axis.y * fOneMinusCos; - float fXZM = axis.x * axis.z * fOneMinusCos; - float fYZM = axis.y * axis.z * fOneMinusCos; - float fXSin = axis.x * fSin; - float fYSin = axis.y * fSin; - float fZSin = axis.z * fSin; - - m.elt[0][0] = fX2 * fOneMinusCos + fCos; - m.elt[0][1] = fXYM - fZSin; - m.elt[0][2] = fXZM + fYSin; - - m.elt[1][0] = fXYM + fZSin; - m.elt[1][1] = fY2 * fOneMinusCos + fCos; - m.elt[1][2] = fYZM - fXSin; - - m.elt[2][0] = fXZM - fYSin; - m.elt[2][1] = fYZM + fXSin; - m.elt[2][2] = fZ2 * fOneMinusCos + fCos; - - return m; -} - -//---------------------------------------------------------------------------- -bool Matrix3::toEulerAnglesXYZ (float& rfXAngle, float& rfYAngle, - float& rfZAngle) const { - // 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 - - if ( elt[0][2] < 1.0f ) { - if ( elt[0][2] > -1.0f ) { - rfXAngle = G3D::aTan2( -elt[1][2], elt[2][2]); - rfYAngle = (float) G3D::aSin(elt[0][2]); - rfZAngle = G3D::aTan2( -elt[0][1], elt[0][0]); - return true; - } else { - // WARNING. Not unique. XA - ZA = -atan2(r10,r11) - rfXAngle = -G3D::aTan2(elt[1][0], elt[1][1]); - rfYAngle = -(float)halfPi(); - rfZAngle = 0.0f; - return false; - } - } else { - // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) - rfXAngle = G3D::aTan2(elt[1][0], elt[1][1]); - rfYAngle = (float)halfPi(); - rfZAngle = 0.0f; - return false; - } -} - -//---------------------------------------------------------------------------- -bool Matrix3::toEulerAnglesXZY (float& rfXAngle, float& rfZAngle, - float& rfYAngle) const { - // rot = cy*cz -sz cz*sy - // sx*sy+cx*cy*sz cx*cz -cy*sx+cx*sy*sz - // -cx*sy+cy*sx*sz cz*sx cx*cy+sx*sy*sz - - if ( elt[0][1] < 1.0f ) { - if ( elt[0][1] > -1.0f ) { - rfXAngle = G3D::aTan2(elt[2][1], elt[1][1]); - rfZAngle = (float) asin( -elt[0][1]); - rfYAngle = G3D::aTan2(elt[0][2], elt[0][0]); - return true; - } else { - // WARNING. Not unique. XA - YA = atan2(r20,r22) - rfXAngle = G3D::aTan2(elt[2][0], elt[2][2]); - rfZAngle = (float)halfPi(); - rfYAngle = 0.0; - return false; - } - } else { - // WARNING. Not unique. XA + YA = atan2(-r20,r22) - rfXAngle = G3D::aTan2( -elt[2][0], elt[2][2]); - rfZAngle = -(float)halfPi(); - rfYAngle = 0.0f; - return false; - } -} - -//---------------------------------------------------------------------------- -bool Matrix3::toEulerAnglesYXZ (float& rfYAngle, float& rfXAngle, - float& rfZAngle) const { - // rot = cy*cz+sx*sy*sz cz*sx*sy-cy*sz cx*sy - // cx*sz cx*cz -sx - // -cz*sy+cy*sx*sz cy*cz*sx+sy*sz cx*cy - - if ( elt[1][2] < 1.0 ) { - if ( elt[1][2] > -1.0 ) { - rfYAngle = G3D::aTan2(elt[0][2], elt[2][2]); - rfXAngle = (float) asin( -elt[1][2]); - rfZAngle = G3D::aTan2(elt[1][0], elt[1][1]); - return true; - } else { - // WARNING. Not unique. YA - ZA = atan2(r01,r00) - rfYAngle = G3D::aTan2(elt[0][1], elt[0][0]); - rfXAngle = (float)halfPi(); - rfZAngle = 0.0; - return false; - } - } else { - // WARNING. Not unique. YA + ZA = atan2(-r01,r00) - rfYAngle = G3D::aTan2( -elt[0][1], elt[0][0]); - rfXAngle = -(float)halfPi(); - rfZAngle = 0.0f; - return false; - } -} - -//---------------------------------------------------------------------------- -bool Matrix3::toEulerAnglesYZX (float& rfYAngle, float& rfZAngle, - float& rfXAngle) const { - // rot = cy*cz sx*sy-cx*cy*sz cx*sy+cy*sx*sz - // sz cx*cz -cz*sx - // -cz*sy cy*sx+cx*sy*sz cx*cy-sx*sy*sz - - if ( elt[1][0] < 1.0 ) { - if ( elt[1][0] > -1.0 ) { - rfYAngle = G3D::aTan2( -elt[2][0], elt[0][0]); - rfZAngle = (float) asin(elt[1][0]); - rfXAngle = G3D::aTan2( -elt[1][2], elt[1][1]); - return true; - } else { - // WARNING. Not unique. YA - XA = -atan2(r21,r22); - rfYAngle = -G3D::aTan2(elt[2][1], elt[2][2]); - rfZAngle = -(float)halfPi(); - rfXAngle = 0.0; - return false; - } - } else { - // WARNING. Not unique. YA + XA = atan2(r21,r22) - rfYAngle = G3D::aTan2(elt[2][1], elt[2][2]); - rfZAngle = (float)halfPi(); - rfXAngle = 0.0f; - return false; - } -} - -//---------------------------------------------------------------------------- -bool Matrix3::toEulerAnglesZXY (float& rfZAngle, float& rfXAngle, - float& rfYAngle) const { - // rot = cy*cz-sx*sy*sz -cx*sz cz*sy+cy*sx*sz - // cz*sx*sy+cy*sz cx*cz -cy*cz*sx+sy*sz - // -cx*sy sx cx*cy - - if ( elt[2][1] < 1.0 ) { - if ( elt[2][1] > -1.0 ) { - rfZAngle = G3D::aTan2( -elt[0][1], elt[1][1]); - rfXAngle = (float) asin(elt[2][1]); - rfYAngle = G3D::aTan2( -elt[2][0], elt[2][2]); - return true; - } else { - // WARNING. Not unique. ZA - YA = -atan(r02,r00) - rfZAngle = -G3D::aTan2(elt[0][2], elt[0][0]); - rfXAngle = -(float)halfPi(); - rfYAngle = 0.0f; - return false; - } - } else { - // WARNING. Not unique. ZA + YA = atan2(r02,r00) - rfZAngle = G3D::aTan2(elt[0][2], elt[0][0]); - rfXAngle = (float)halfPi(); - rfYAngle = 0.0f; - return false; - } -} - -//---------------------------------------------------------------------------- -bool Matrix3::toEulerAnglesZYX (float& rfZAngle, float& rfYAngle, - float& rfXAngle) const { - // rot = cy*cz cz*sx*sy-cx*sz cx*cz*sy+sx*sz - // cy*sz cx*cz+sx*sy*sz -cz*sx+cx*sy*sz - // -sy cy*sx cx*cy - - if ( elt[2][0] < 1.0 ) { - if ( elt[2][0] > -1.0 ) { - rfZAngle = atan2f(elt[1][0], elt[0][0]); - rfYAngle = asinf(-(double)elt[2][1]); - rfXAngle = atan2f(elt[2][1], elt[2][2]); - return true; - } else { - // WARNING. Not unique. ZA - XA = -atan2(r01,r02) - rfZAngle = -G3D::aTan2(elt[0][1], elt[0][2]); - rfYAngle = (float)halfPi(); - rfXAngle = 0.0f; - return false; - } - } else { - // WARNING. Not unique. ZA + XA = atan2(-r01,-r02) - rfZAngle = G3D::aTan2( -elt[0][1], -elt[0][2]); - rfYAngle = -(float)halfPi(); - rfXAngle = 0.0f; - return false; - } -} - -//---------------------------------------------------------------------------- -Matrix3 Matrix3::fromEulerAnglesXYZ (float fYAngle, float fPAngle, - float fRAngle) { - float fCos, fSin; - - fCos = cosf(fYAngle); - fSin = sinf(fYAngle); - Matrix3 kXMat(1.0f, 0.0f, 0.0f, 0.0f, fCos, -fSin, 0.0, fSin, fCos); - - fCos = cosf(fPAngle); - fSin = sinf(fPAngle); - Matrix3 kYMat(fCos, 0.0f, fSin, 0.0f, 1.0f, 0.0f, -fSin, 0.0f, fCos); - - fCos = cosf(fRAngle); - fSin = sinf(fRAngle); - Matrix3 kZMat(fCos, -fSin, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 1.0f); - - return kXMat * (kYMat * kZMat); -} - -//---------------------------------------------------------------------------- -Matrix3 Matrix3::fromEulerAnglesXZY (float fYAngle, float fPAngle, - float fRAngle) { - - float fCos, fSin; - - fCos = cosf(fYAngle); - fSin = sinf(fYAngle); - Matrix3 kXMat(1.0, 0.0, 0.0, 0.0, fCos, -fSin, 0.0, fSin, fCos); - - fCos = cosf(fPAngle); - fSin = sinf(fPAngle); - Matrix3 kZMat(fCos, -fSin, 0.0, fSin, fCos, 0.0, 0.0, 0.0, 1.0); - - fCos = cosf(fRAngle); - fSin = sinf(fRAngle); - Matrix3 kYMat(fCos, 0.0, fSin, 0.0, 1.0, 0.0, -fSin, 0.0, fCos); - - return kXMat * (kZMat * kYMat); -} - -//---------------------------------------------------------------------------- -Matrix3 Matrix3::fromEulerAnglesYXZ( - float fYAngle, - float fPAngle, - float fRAngle) { - - float fCos, fSin; - - fCos = cos(fYAngle); - fSin = sin(fYAngle); - Matrix3 kYMat(fCos, 0.0f, fSin, 0.0f, 1.0f, 0.0f, -fSin, 0.0f, fCos); - - fCos = cos(fPAngle); - fSin = sin(fPAngle); - Matrix3 kXMat(1.0f, 0.0f, 0.0f, 0.0f, fCos, -fSin, 0.0f, fSin, fCos); - - fCos = cos(fRAngle); - fSin = sin(fRAngle); - Matrix3 kZMat(fCos, -fSin, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 1.0f); - - return kYMat * (kXMat * kZMat); -} - -//---------------------------------------------------------------------------- -Matrix3 Matrix3::fromEulerAnglesYZX( - float fYAngle, - float fPAngle, - float fRAngle) { - - float fCos, fSin; - - fCos = cos(fYAngle); - fSin = sin(fYAngle); - Matrix3 kYMat(fCos, 0.0f, fSin, 0.0f, 1.0f, 0.0f, -fSin, 0.0f, fCos); - - fCos = cos(fPAngle); - fSin = sin(fPAngle); - Matrix3 kZMat(fCos, -fSin, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 1.0f); - - fCos = cos(fRAngle); - fSin = sin(fRAngle); - Matrix3 kXMat(1.0f, 0.0f, 0.0f, 0.0f, fCos, -fSin, 0.0f, fSin, fCos); - - return kYMat * (kZMat * kXMat); -} - -//---------------------------------------------------------------------------- -Matrix3 Matrix3::fromEulerAnglesZXY (float fYAngle, float fPAngle, - float fRAngle) { - float fCos, fSin; - - fCos = cos(fYAngle); - fSin = sin(fYAngle); - Matrix3 kZMat(fCos, -fSin, 0.0, fSin, fCos, 0.0, 0.0, 0.0, 1.0); - - fCos = cos(fPAngle); - fSin = sin(fPAngle); - Matrix3 kXMat(1.0, 0.0, 0.0, 0.0, fCos, -fSin, 0.0, fSin, fCos); - - fCos = cos(fRAngle); - fSin = sin(fRAngle); - Matrix3 kYMat(fCos, 0.0, fSin, 0.0, 1.0, 0.0, -fSin, 0.0, fCos); - - return kZMat * (kXMat * kYMat); -} - -//---------------------------------------------------------------------------- -Matrix3 Matrix3::fromEulerAnglesZYX (float fYAngle, float fPAngle, - float fRAngle) { - float fCos, fSin; - - fCos = cos(fYAngle); - fSin = sin(fYAngle); - Matrix3 kZMat(fCos, -fSin, 0.0, fSin, fCos, 0.0, 0.0, 0.0, 1.0); - - fCos = cos(fPAngle); - fSin = sin(fPAngle); - Matrix3 kYMat(fCos, 0.0, fSin, 0.0, 1.0, 0.0, -fSin, 0.0, fCos); - - fCos = cos(fRAngle); - fSin = sin(fRAngle); - Matrix3 kXMat(1.0, 0.0, 0.0, 0.0, fCos, -fSin, 0.0, fSin, fCos); - - return kZMat * (kYMat * kXMat); -} - -//---------------------------------------------------------------------------- -void Matrix3::tridiagonal (float afDiag[3], float afSubDiag[3]) { - // 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) - - float fA = elt[0][0]; - float fB = elt[0][1]; - float fC = elt[0][2]; - float fD = elt[1][1]; - float fE = elt[1][2]; - float fF = elt[2][2]; - - afDiag[0] = fA; - afSubDiag[2] = 0.0; - - if ( G3D::abs(fC) >= EPSILON ) { - float fLength = sqrt(fB * fB + fC * fC); - float fInvLength = 1.0 / fLength; - fB *= fInvLength; - fC *= fInvLength; - float fQ = 2.0 * fB * fE + fC * (fF - fD); - afDiag[1] = fD + fC * fQ; - afDiag[2] = fF - fC * fQ; - afSubDiag[0] = fLength; - afSubDiag[1] = fE - fB * fQ; - elt[0][0] = 1.0; - elt[0][1] = 0.0; - elt[0][2] = 0.0; - elt[1][0] = 0.0; - elt[1][1] = fB; - elt[1][2] = fC; - elt[2][0] = 0.0; - elt[2][1] = fC; - elt[2][2] = -fB; - } else { - afDiag[1] = fD; - afDiag[2] = fF; - afSubDiag[0] = fB; - afSubDiag[1] = fE; - elt[0][0] = 1.0; - elt[0][1] = 0.0; - elt[0][2] = 0.0; - elt[1][0] = 0.0; - elt[1][1] = 1.0; - elt[1][2] = 0.0; - elt[2][0] = 0.0; - elt[2][1] = 0.0; - elt[2][2] = 1.0; - } -} - -//---------------------------------------------------------------------------- -bool Matrix3::qLAlgorithm (float afDiag[3], float afSubDiag[3]) { - // QL iteration with implicit shifting to reduce matrix from tridiagonal - // to diagonal - - for (int i0 = 0; i0 < 3; i0++) { - const int iMaxIter = 32; - int iIter; - - for (iIter = 0; iIter < iMaxIter; iIter++) { - int i1; - - for (i1 = i0; i1 <= 1; i1++) { - float fSum = G3D::abs(afDiag[i1]) + - G3D::abs(afDiag[i1 + 1]); - - if ( G3D::abs(afSubDiag[i1]) + fSum == fSum ) - break; - } - - if ( i1 == i0 ) - break; - - float fTmp0 = (afDiag[i0 + 1] - afDiag[i0]) / (2.0 * afSubDiag[i0]); - - float fTmp1 = sqrt(fTmp0 * fTmp0 + 1.0); - - if ( fTmp0 < 0.0 ) - fTmp0 = afDiag[i1] - afDiag[i0] + afSubDiag[i0] / (fTmp0 - fTmp1); - else - fTmp0 = afDiag[i1] - afDiag[i0] + afSubDiag[i0] / (fTmp0 + fTmp1); - - float fSin = 1.0; - - float fCos = 1.0; - - float fTmp2 = 0.0; - - for (int i2 = i1 - 1; i2 >= i0; i2--) { - float fTmp3 = fSin * afSubDiag[i2]; - float fTmp4 = fCos * afSubDiag[i2]; - - if (G3D::abs(fTmp3) >= G3D::abs(fTmp0)) { - fCos = fTmp0 / fTmp3; - fTmp1 = sqrt(fCos * fCos + 1.0); - afSubDiag[i2 + 1] = fTmp3 * fTmp1; - fSin = 1.0 / fTmp1; - fCos *= fSin; - } else { - fSin = fTmp3 / fTmp0; - fTmp1 = sqrt(fSin * fSin + 1.0); - afSubDiag[i2 + 1] = fTmp0 * fTmp1; - fCos = 1.0 / fTmp1; - fSin *= fCos; - } - - fTmp0 = afDiag[i2 + 1] - fTmp2; - fTmp1 = (afDiag[i2] - fTmp0) * fSin + 2.0 * fTmp4 * fCos; - fTmp2 = fSin * fTmp1; - afDiag[i2 + 1] = fTmp0 + fTmp2; - fTmp0 = fCos * fTmp1 - fTmp4; - - for (int iRow = 0; iRow < 3; iRow++) { - fTmp3 = elt[iRow][i2 + 1]; - elt[iRow][i2 + 1] = fSin * elt[iRow][i2] + - fCos * fTmp3; - elt[iRow][i2] = fCos * elt[iRow][i2] - - fSin * fTmp3; - } - } - - afDiag[i0] -= fTmp2; - afSubDiag[i0] = fTmp0; - afSubDiag[i1] = 0.0; - } - - if ( iIter == iMaxIter ) { - // should not get here under normal circumstances - return false; - } - } - - return true; -} - -//---------------------------------------------------------------------------- -void Matrix3::eigenSolveSymmetric (float afEigenvalue[3], - Vector3 akEigenvector[3]) const { - Matrix3 kMatrix = *this; - float afSubDiag[3]; - kMatrix.tridiagonal(afEigenvalue, afSubDiag); - kMatrix.qLAlgorithm(afEigenvalue, afSubDiag); - - for (int i = 0; i < 3; i++) { - akEigenvector[i][0] = kMatrix[0][i]; - akEigenvector[i][1] = kMatrix[1][i]; - akEigenvector[i][2] = kMatrix[2][i]; - } - - // make eigenvectors form a right--handed system - Vector3 kCross = akEigenvector[1].cross(akEigenvector[2]); - - float fDet = akEigenvector[0].dot(kCross); - - if ( fDet < 0.0 ) { - akEigenvector[2][0] = - akEigenvector[2][0]; - akEigenvector[2][1] = - akEigenvector[2][1]; - akEigenvector[2][2] = - akEigenvector[2][2]; - } -} - -//---------------------------------------------------------------------------- -void Matrix3::tensorProduct (const Vector3& rkU, const Vector3& rkV, - Matrix3& rkProduct) { - for (int iRow = 0; iRow < 3; iRow++) { - for (int iCol = 0; iCol < 3; iCol++) { - rkProduct[iRow][iCol] = rkU[iRow] * rkV[iCol]; - } - } -} - -//---------------------------------------------------------------------------- - -// Runs in 52 cycles on AMD, 76 cycles on Intel Centrino -// -// The loop unrolling is necessary for performance. -// I was unable to improve performance further by flattening the matrices -// into float*'s instead of 2D arrays. -// -// -morgan -void Matrix3::_mul(const Matrix3& A, const Matrix3& B, Matrix3& out) { - const float* ARowPtr = A.elt[0]; - float* outRowPtr = out.elt[0]; - outRowPtr[0] = - ARowPtr[0] * B.elt[0][0] + - ARowPtr[1] * B.elt[1][0] + - ARowPtr[2] * B.elt[2][0]; - outRowPtr[1] = - ARowPtr[0] * B.elt[0][1] + - ARowPtr[1] * B.elt[1][1] + - ARowPtr[2] * B.elt[2][1]; - outRowPtr[2] = - ARowPtr[0] * B.elt[0][2] + - ARowPtr[1] * B.elt[1][2] + - ARowPtr[2] * B.elt[2][2]; - - ARowPtr = A.elt[1]; - outRowPtr = out.elt[1]; - - outRowPtr[0] = - ARowPtr[0] * B.elt[0][0] + - ARowPtr[1] * B.elt[1][0] + - ARowPtr[2] * B.elt[2][0]; - outRowPtr[1] = - ARowPtr[0] * B.elt[0][1] + - ARowPtr[1] * B.elt[1][1] + - ARowPtr[2] * B.elt[2][1]; - outRowPtr[2] = - ARowPtr[0] * B.elt[0][2] + - ARowPtr[1] * B.elt[1][2] + - ARowPtr[2] * B.elt[2][2]; - - ARowPtr = A.elt[2]; - outRowPtr = out.elt[2]; - - outRowPtr[0] = - ARowPtr[0] * B.elt[0][0] + - ARowPtr[1] * B.elt[1][0] + - ARowPtr[2] * B.elt[2][0]; - outRowPtr[1] = - ARowPtr[0] * B.elt[0][1] + - ARowPtr[1] * B.elt[1][1] + - ARowPtr[2] * B.elt[2][1]; - outRowPtr[2] = - ARowPtr[0] * B.elt[0][2] + - ARowPtr[1] * B.elt[1][2] + - ARowPtr[2] * B.elt[2][2]; -} - -//---------------------------------------------------------------------------- -void Matrix3::_transpose(const Matrix3& A, Matrix3& out) { - out[0][0] = A.elt[0][0]; - out[0][1] = A.elt[1][0]; - out[0][2] = A.elt[2][0]; - out[1][0] = A.elt[0][1]; - out[1][1] = A.elt[1][1]; - out[1][2] = A.elt[2][1]; - out[2][0] = A.elt[0][2]; - out[2][1] = A.elt[1][2]; - out[2][2] = A.elt[2][2]; -} - -//----------------------------------------------------------------------------- -std::string Matrix3::toString() const { - return G3D::format("[%g, %g, %g; %g, %g, %g; %g, %g, %g]", - elt[0][0], elt[0][1], elt[0][2], - elt[1][0], elt[1][1], elt[1][2], - elt[2][0], elt[2][1], elt[2][2]); -} - - - -} // namespace - diff --git a/externals/g3dlite/G3D.lib/source/Matrix4.cpp b/externals/g3dlite/G3D.lib/source/Matrix4.cpp deleted file mode 100644 index 091af4a9bd5..00000000000 --- a/externals/g3dlite/G3D.lib/source/Matrix4.cpp +++ /dev/null @@ -1,433 +0,0 @@ -/** - @file Matrix4.cpp - - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-10-02 - @edited 2008-07-17 - */ - -#include "G3D/platform.h" -#include "G3D/Matrix4.h" -#include "G3D/Matrix3.h" -#include "G3D/Vector4.h" -#include "G3D/Vector3.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/CoordinateFrame.h" -#include "G3D/Rect2D.h" - -namespace G3D { - -const Matrix4& Matrix4::identity() { - static Matrix4 m( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - return m; -} - - -const Matrix4& Matrix4::zero() { - static Matrix4 m( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0); - return m; -} - - -Matrix4::Matrix4(const class CoordinateFrame& cframe) { - for (int r = 0; r < 3; ++r) { - for (int c = 0; c < 3; ++c) { - elt[r][c] = cframe.rotation[r][c]; - } - elt[r][3] = cframe.translation[r]; - } - elt[3][0] = 0.0f; - elt[3][1] = 0.0f; - elt[3][2] = 0.0f; - elt[3][3] = 1.0f; -} - -Matrix4::Matrix4(const Matrix3& upper3x3, const Vector3& lastCol) { - for (int r = 0; r < 3; ++r) { - for (int c = 0; c < 3; ++c) { - elt[r][c] = upper3x3[r][c]; - } - elt[r][3] = lastCol[r]; - } - elt[3][0] = 0.0f; - elt[3][1] = 0.0f; - elt[3][2] = 0.0f; - elt[3][3] = 1.0f; -} - - -Matrix3 Matrix4::upper3x3() const { - return Matrix3(elt[0][0], elt[0][1], elt[0][2], - elt[1][0], elt[1][1], elt[1][2], - elt[2][0], elt[2][1], elt[2][2]); -} - - -Matrix4 Matrix4::orthogonalProjection( - const class Rect2D& rect, - float nearval, - float farval) { - return Matrix4::orthogonalProjection(rect.x0(), rect.x1(), rect.y1(), rect.y0(), nearval, farval); -} - - -Matrix4 Matrix4::orthogonalProjection( - float left, - float right, - float bottom, - float top, - float nearval, - float farval) { - - // Adapted from Mesa. Note that Microsoft (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/opengl/glfunc03_8qnj.asp) - // and Linux (http://www.xfree86.org/current/glOrtho.3.html) have different matrices shown in their documentation. - - float x, y, z; - float tx, ty, tz; - - x = 2.0f / (right-left); - y = 2.0f / (top-bottom); - z = -2.0f / (farval-nearval); - tx = -(right+left) / (right-left); - ty = -(top+bottom) / (top-bottom); - tz = -(farval+nearval) / (farval-nearval); - - return - Matrix4( x , 0.0f, 0.0f, tx, - 0.0f, y , 0.0f, ty, - 0.0f, 0.0f, z , tz, - 0.0f, 0.0f, 0.0f, 1.0f); -} - - -Matrix4 Matrix4::perspectiveProjection( - float left, - float right, - float bottom, - float top, - float nearval, - float farval) { - - float x, y, a, b, c, d; - - x = (2.0f*nearval) / (right-left); - y = (2.0f*nearval) / (top-bottom); - a = (right+left) / (right-left); - b = (top+bottom) / (top-bottom); - - if ((float)farval >= (float)inf()) { - // Infinite view frustum - c = -1.0f; - d = -2.0f * nearval; - } else { - c = -(farval+nearval) / (farval-nearval); - d = -(2.0f*farval*nearval) / (farval-nearval); - } - - return Matrix4( - x, 0, a, 0, - 0, y, b, 0, - 0, 0, c, d, - 0, 0, -1, 0); -} - - -Matrix4::Matrix4( - float r1c1, float r1c2, float r1c3, float r1c4, - float r2c1, float r2c2, float r2c3, float r2c4, - float r3c1, float r3c2, float r3c3, float r3c4, - float r4c1, float r4c2, float r4c3, float r4c4) { - elt[0][0] = r1c1; elt[0][1] = r1c2; elt[0][2] = r1c3; elt[0][3] = r1c4; - elt[1][0] = r2c1; elt[1][1] = r2c2; elt[1][2] = r2c3; elt[1][3] = r2c4; - elt[2][0] = r3c1; elt[2][1] = r3c2; elt[2][2] = r3c3; elt[2][3] = r3c4; - elt[3][0] = r4c1; elt[3][1] = r4c2; elt[3][2] = r4c3; elt[3][3] = r4c4; -} - -/** - init should be row major. - */ -Matrix4::Matrix4(const float* init) { - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - elt[r][c] = init[r * 4 + c]; - } - } -} - - -Matrix4::Matrix4(const double* init) { - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - elt[r][c] = (float)init[r * 4 + c]; - } - } -} - - -Matrix4::Matrix4() { - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - elt[r][c] = 0; - } - } -} - - -void Matrix4::setRow(int r, const Vector4& v) { - for (int c = 0; c < 4; ++c) { - elt[r][c] = v[c]; - } -} - - -void Matrix4::setColumn(int c, const Vector4& v) { - for (int r = 0; r < 4; ++r) { - elt[r][c] = v[r]; - } -} - - -Vector4 Matrix4::getRow(int r) const { - return row(r); -} - - -const Vector4& Matrix4::row(int r) const { - return reinterpret_cast(elt[r])[0]; -} - - -Vector4 Matrix4::getColumn(int c) const { - return column(c); -} - -Vector4 Matrix4::column(int c) const { - Vector4 v; - for (int r = 0; r < 4; ++r) { - v[r] = elt[r][c]; - } - return v; -} - - -Matrix4 Matrix4::operator*(const Matrix4& other) const { - Matrix4 result; - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - for (int i = 0; i < 4; ++i) { - result.elt[r][c] += elt[r][i] * other.elt[i][c]; - } - } - } - - return result; -} - - -Matrix4 Matrix4::operator*(const float s) const { - Matrix4 result; - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - result.elt[r][c] = elt[r][c] * s; - } - } - - return result; -} - - -Vector3 Matrix4::homoMul(const class Vector3& v, float w) const { - Vector4 r = (*this) * Vector4(v, w); - return r.xyz() * (1.0f / r.w); -} - - -Vector4 Matrix4::operator*(const Vector4& vector) const { - Vector4 result(0,0,0,0); - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - result[r] += elt[r][c] * vector[c]; - } - } - - return result; -} - - -Matrix4 Matrix4::transpose() const { - Matrix4 result; - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - result.elt[c][r] = elt[r][c]; - } - } - - return result; -} - - -bool Matrix4::operator!=(const Matrix4& other) const { - return ! (*this == other); -} - - -bool Matrix4::operator==(const Matrix4& other) const { - - // If the bit patterns are identical, they must be - // the same matrix. If not, they *might* still have - // equal elements due to floating point weirdness. - if (memcmp(this, &other, sizeof(Matrix4) == 0)) { - return true; - } - - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - if (elt[r][c] != other.elt[r][c]) { - return false; - } - } - } - - return true; -} - - -float Matrix4::determinant() const { - // Determinant is the dot product of the first row and the first row - // of cofactors (i.e. the first col of the adjoint matrix) - return cofactor().getRow(0).dot(getRow(0)); -} - - -Matrix4 Matrix4::adjoint() const { - return cofactor().transpose(); -} - - -Matrix4 Matrix4::inverse() const { - // Inverse = adjoint / determinant - - Matrix4 A = adjoint(); - - // Determinant is the dot product of the first row and the first row - // of cofactors (i.e. the first col of the adjoint matrix) - float det = A.getColumn(0).dot(getRow(0)); - - return A * (1.0f / det); -} - - -Matrix4 Matrix4::cofactor() const { - Matrix4 out; - - // We'll use i to incrementally compute -1 ^ (r+c) - int i = 1; - - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - // Compute the determinant of the 3x3 submatrix - float det = subDeterminant(r, c); - out.elt[r][c] = i * det; - i = -i; - } - i = -i; - } - - return out; -} - - -float Matrix4::subDeterminant(int excludeRow, int excludeCol) const { - // Compute non-excluded row and column indices - int row[3]; - int col[3]; - - for (int i = 0; i < 3; ++i) { - row[i] = i; - col[i] = i; - - if (i >= excludeRow) { - ++row[i]; - } - if (i >= excludeCol) { - ++col[i]; - } - } - - // Compute the first row of cofactors - float cofactor00 = - elt[row[1]][col[1]] * elt[row[2]][col[2]] - - elt[row[1]][col[2]] * elt[row[2]][col[1]]; - - float cofactor10 = - elt[row[1]][col[2]] * elt[row[2]][col[0]] - - elt[row[1]][col[0]] * elt[row[2]][col[2]]; - - float cofactor20 = - elt[row[1]][col[0]] * elt[row[2]][col[1]] - - elt[row[1]][col[1]] * elt[row[2]][col[0]]; - - // Product of the first row and the cofactors along the first row - return - elt[row[0]][col[0]] * cofactor00 + - elt[row[0]][col[1]] * cofactor10 + - elt[row[0]][col[2]] * cofactor20; -} - - -CoordinateFrame Matrix4::approxCoordinateFrame() const { - CoordinateFrame cframe; - - for (int r = 0; r < 3; ++r) { - for (int c = 0; c < 3; ++c) { - cframe.rotation[r][c] = elt[r][c]; - } - cframe.translation[r] = elt[r][3]; - } - - // Ensure that the rotation matrix is orthonormal - cframe.rotation.orthonormalize(); - - return cframe; -} - - -void Matrix4::serialize(class BinaryOutput& b) const { - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - b.writeFloat32(elt[r][c]); - } - } -} - - -void Matrix4::deserialize(class BinaryInput& b) { - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - elt[r][c] = b.readFloat32(); - } - } -} - -std::string Matrix4::toString() const { - return G3D::format("[%g, %g, %g, %g; %g, %g, %g, %g; %g, %g, %g, %g; %g, %g, %g, %g]", - elt[0][0], elt[0][1], elt[0][2], elt[0][3], - elt[1][0], elt[1][1], elt[1][2], elt[1][3], - elt[2][0], elt[2][1], elt[2][2], elt[2][3], - elt[3][0], elt[3][1], elt[3][2], elt[3][3]); -} - -} // namespace - - diff --git a/externals/g3dlite/G3D.lib/source/MeshAlg.cpp b/externals/g3dlite/G3D.lib/source/MeshAlg.cpp deleted file mode 100644 index 24b90ab5a92..00000000000 --- a/externals/g3dlite/G3D.lib/source/MeshAlg.cpp +++ /dev/null @@ -1,733 +0,0 @@ -/** - @file MeshAlg.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - @created 2003-09-14 - @edited 2008-09-03 - - Copyright 2000-2008, Morgan McGuire. - All rights reserved. - - */ - -#include "G3D/MeshAlg.h" -#include "G3D/Table.h" -#include "G3D/Set.h" -#include "G3D/Box.h" -#include "G3D/Sphere.h" -#include "G3D/vectorMath.h" -#include "G3D/AABox.h" - -#include - -namespace G3D { - -const int MeshAlg::Face::NONE = INT_MIN; - -void MeshAlg::generateGrid( - Array& vertex, - Array& texCoord, - Array& index, - int wCells, - int hCells, - const Vector2& textureScale, - bool spaceCentered, - bool twoSided, - const CoordinateFrame& xform) { - - vertex.fastClear(); - texCoord.fastClear(); - index.fastClear(); - - // Generate vertices - for (int z = 0; z <= hCells; ++z) { - for (int x = 0; x <= wCells; ++x) { - Vector3 v(x / (float)wCells, 0, z / (float)hCells); - - Vector2 t = v.xz() * textureScale; - - texCoord.append(t); - - if (spaceCentered) { - v -= Vector3(0.5f, 0, 0.5f); - } - v = xform.pointToWorldSpace(v); - vertex.append(v); - } - } - - // Generate indices - for (int z = 0; z < hCells; ++z) { - for (int x = 0; x < wCells; ++x) { - int A = x + z * (wCells + 1); - int B = A + 1; - int C = A + (wCells + 1); - int D = C + 1; - - // A B - // *-----* - // | \ | - // | \ | - // *-----* - // C D - - index.append(A, D, B); - index.append(A, C, D); - } - } - - if (twoSided) { - // The index array needs to have reversed winding for the bottom - // and offset by the original number of vertices - Array ti = index; - ti.reverse(); - for (int i = 0; i < ti.size(); ++i) { - ti[i] += vertex.size(); - } - index.append(ti); - - // Duplicate the arrays - vertex.append(Array(vertex)); - texCoord.append(Array(texCoord)); - } -} - -MeshAlg::Face::Face() { - for (int i = 0; i < 3; ++i) { - edgeIndex[i] = 0; - vertexIndex[i] = 0; - } -} - - -MeshAlg::Edge::Edge() { - for (int i = 0; i < 2; ++i) { - vertexIndex[i] = 0; - // Negative face indices are faces that don't exist - faceIndex[i] = -1; - } -} - - -MeshAlg::Geometry& MeshAlg::Geometry::operator=(const MeshAlg::Geometry& src) { - vertexArray.resize(src.vertexArray.size()); - normalArray.resize(src.vertexArray.size()); - - System::memcpy(vertexArray.getCArray(), src.vertexArray.getCArray(), sizeof(Vector3)*vertexArray.size()); - System::memcpy(normalArray.getCArray(), src.normalArray.getCArray(), sizeof(Vector3)*normalArray.size()); - - return *this; -} - - -void MeshAlg::computeNormals( - Geometry& geometry, - const Array& indexArray) { - - Array faceArray; - Array vertexArray; - Array edgeArray; - Array faceNormalArray; - - computeAdjacency(geometry.vertexArray, indexArray, faceArray, edgeArray, vertexArray); - - computeNormals(geometry.vertexArray, faceArray, vertexArray, - geometry.normalArray, faceNormalArray); -} - - -void MeshAlg::computeNormals( - const Array& vertexGeometry, - const Array& faceArray, - const Array< Array >& adjacentFaceArray, - Array& vertexNormalArray, - Array& faceNormalArray) { - - // Construct a fake vertex array for backwards compatibility - Array fakeVertexArray(adjacentFaceArray.size()); - - for (int v = 0; v < adjacentFaceArray.size(); ++v) { - fakeVertexArray[v].faceIndex = adjacentFaceArray[v]; - // We leave out the edges because they aren't used to compute normals - } - - computeNormals(vertexGeometry, faceArray, fakeVertexArray, - vertexNormalArray, faceNormalArray); -} - - -void MeshAlg::computeNormals( - const Array& vertexGeometry, - const Array& faceArray, - const Array& vertexArray, - Array& vertexNormalArray, - Array& faceNormalArray) { - - // Face normals (not unit length) - faceNormalArray.resize(faceArray.size()); - for (int f = 0; f < faceArray.size(); ++f) { - const Face& face = faceArray[f]; - - Vector3 vertex[3]; - for (int j = 0; j < 3; ++j) { - vertex[j] = vertexGeometry[face.vertexIndex[j]]; - debugAssert(vertex[j].isFinite()); - } - - faceNormalArray[f] = (vertex[1] - vertex[0]).cross(vertex[2] - vertex[0]); -# ifdef G3D_DEBUG - const Vector3& N = faceNormalArray[f]; - debugAssert(N.isFinite()); -# endif - } - - // Per-vertex normals, computed by averaging - vertexNormalArray.resize(vertexGeometry.size()); - for (int v = 0; v < vertexNormalArray.size(); ++v) { - Vector3 sum = Vector3::zero(); - for (int k = 0; k < vertexArray[v].faceIndex.size(); ++k) { - const int f = vertexArray[v].faceIndex[k]; - sum += faceNormalArray[f]; - } - vertexNormalArray[v] = sum.directionOrZero(); -# ifdef G3D_DEBUG - const Vector3& N = vertexNormalArray[v]; - debugAssert(N.isUnit() || N.isZero()); -# endif - } - - - for (int f = 0; f < faceArray.size(); ++f) { - faceNormalArray[f] = faceNormalArray[f].directionOrZero(); -# ifdef G3D_DEBUG - const Vector3& N = faceNormalArray[f]; - debugAssert(N.isUnit() || N.isZero()); -# endif - } - -} - - -void MeshAlg::computeFaceNormals( - const Array& vertexArray, - const Array& faceArray, - Array& faceNormals, - bool normalize) { - - faceNormals.resize(faceArray.size()); - - for (int f = 0; f < faceArray.size(); ++f) { - const MeshAlg::Face& face = faceArray[f]; - - const Vector3& v0 = vertexArray[face.vertexIndex[0]]; - const Vector3& v1 = vertexArray[face.vertexIndex[1]]; - const Vector3& v2 = vertexArray[face.vertexIndex[2]]; - - faceNormals[f] = (v1 - v0).cross(v2 - v0); - } - - if (normalize) { - for (int f = 0; f < faceArray.size(); ++f) { - faceNormals[f] = faceNormals[f].direction(); - } - } -} - - -void MeshAlg::identifyBackfaces( - const Array& vertexArray, - const Array& faceArray, - const Vector4& HP, - Array& backface) { - - Vector3 P = HP.xyz(); - - backface.resize(faceArray.size()); - - if (fuzzyEq(HP.w, 0.0)) { - // Infinite case - for (int f = faceArray.size() - 1; f >= 0; --f) { - const MeshAlg::Face& face = faceArray[f]; - - const Vector3& v0 = vertexArray[face.vertexIndex[0]]; - const Vector3& v1 = vertexArray[face.vertexIndex[1]]; - const Vector3& v2 = vertexArray[face.vertexIndex[2]]; - - const Vector3 N = (v1 - v0).cross(v2 - v0); - - backface[f] = N.dot(P) < 0; - } - } else { - // Finite case - for (int f = faceArray.size() - 1; f >= 0; --f) { - const MeshAlg::Face& face = faceArray[f]; - - const Vector3& v0 = vertexArray[face.vertexIndex[0]]; - const Vector3& v1 = vertexArray[face.vertexIndex[1]]; - const Vector3& v2 = vertexArray[face.vertexIndex[2]]; - - const Vector3 N = (v1 - v0).cross(v2 - v0); - - backface[f] = N.dot(P - v0) < 0; - } - } -} - - -void MeshAlg::identifyBackfaces( - const Array& vertexArray, - const Array& faceArray, - const Vector4& HP, - Array& backface, - const Array& faceNormals) { - - Vector3 P = HP.xyz(); - - backface.resize(faceArray.size()); - - if (fuzzyEq(HP.w, 0.0)) { - // Infinite case - for (int f = faceArray.size() - 1; f >= 0; --f) { - const Vector3& N = faceNormals[f]; - backface[f] = N.dot(P) < 0; - } - } else { - // Finite case - for (int f = faceArray.size() - 1; f >= 0; --f) { - const MeshAlg::Face& face = faceArray[f]; - const Vector3& v0 = vertexArray[face.vertexIndex[0]]; - const Vector3& N = faceNormals[f]; - - backface[f] = N.dot(P - v0) < 0; - } - } -} - - -void MeshAlg::createIndexArray(int n, Array& array, int start, int run, int skip) { - debugAssert(skip >= 0); - debugAssert(run >= 0); - - array.resize(n); - if (skip == 0) { - for (int i = 0; i < n; ++i) { - array[i] = start + i; - } - } else { - int rcount = 0; - int j = start; - for (int i = 0; i < n; ++i) { - array[i] = j; - - ++j; - ++rcount; - - if (rcount == run) { - rcount = 0; - j += skip; - } - } - } -} - - -void MeshAlg::computeAreaStatistics( - const Array& vertexArray, - const Array& indexArray, - double& minEdgeLength, - double& meanEdgeLength, - double& medianEdgeLength, - double& maxEdgeLength, - double& minFaceArea, - double& meanFaceArea, - double& medianFaceArea, - double& maxFaceArea) { - - debugAssert(indexArray.size() % 3 == 0); - - Array area(indexArray.size() / 3); - Array magnitude(indexArray.size()); - - for (int i = 0; i < indexArray.size(); i += 3) { - const Vector3& v0 = vertexArray[indexArray[i]]; - const Vector3& v1 = vertexArray[indexArray[i + 1]]; - const Vector3& v2 = vertexArray[indexArray[i + 2]]; - - area[i / 3] = (v1 - v0).cross(v2 - v0).magnitude() / 2.0; - magnitude[i] = (v1 - v0).magnitude(); - magnitude[i + 1] = (v2 - v1).magnitude(); - magnitude[i + 2] = (v0 - v2).magnitude(); - } - - area.sort(); - magnitude.sort(); - - minEdgeLength = max(0.0, magnitude[0]); - maxEdgeLength = max(0.0, magnitude.last()); - medianEdgeLength = max(0.0, magnitude[magnitude.size() / 2]); - meanEdgeLength = 0; - for (int i = 0; i < magnitude.size(); ++i) { - meanEdgeLength += magnitude[i]; - } - meanEdgeLength /= magnitude.size(); - - minFaceArea = max(0.0, area[0]); - maxFaceArea = max(0.0, area.last()); - medianFaceArea = max(0.0, area[area.size() / 2]); - meanFaceArea = 0; - for (int i = 0; i < area.size(); ++i) { - meanFaceArea += area[i]; - } - meanFaceArea /= area.size(); - - - // Make sure round-off hasn't pushed values less than zero - meanFaceArea = max(0.0, meanFaceArea); - meanEdgeLength = max(0.0, meanEdgeLength); -} - - -int MeshAlg::countBoundaryEdges(const Array& edgeArray) { - int b = 0; - - for (int i = 0; i < edgeArray.size(); ++i) { - if ((edgeArray[i].faceIndex[0] == MeshAlg::Face::NONE) != - (edgeArray[i].faceIndex[1] == MeshAlg::Face::NONE)) { - ++b; - } - } - - return b; -} - -void MeshAlg::computeBounds( - const Array& vertexArray, - const Array& indexArray, - Box& box, - Sphere& sphere) { - - Array newArray(indexArray.size()); - for (int i = 0; i < indexArray.size(); ++i) { - newArray[i] = vertexArray[indexArray[i]]; - } - computeBounds(newArray, box, sphere); -} - - -void MeshAlg::computeBounds( - const Array& vertexArray, - Box& box, - Sphere& sphere) { - - Vector3 xmin, xmax, ymin, ymax, zmin, zmax; - - // FIRST PASS: find 6 minima/maxima points - xmin.x = ymin.y = zmin.z = inf(); - xmax.x = ymax.y = zmax.z = -inf(); - - for (int v = 0; v < vertexArray.size(); ++v) { - const Vector3& vertex = vertexArray[v]; - - if (vertex.x < xmin.x) { - xmin = vertex; - } - - if (vertex.x > xmax.x) { - xmax = vertex; - } - - if (vertex.y < ymin.y) { - ymin = vertex; - } - - if (vertex.y > ymax.y) { - ymax = vertex; - } - - if (vertex.z < zmin.z) { - zmin = vertex; - } - - if (vertex.z > zmax.z) { - zmax = vertex; - } - } - - // Set points dia1 & dia2 to the maximally separated pair - Vector3 dia1 = xmin; - Vector3 dia2 = xmax; - { - // Set xspan = distance between the 2 points xmin & xmax (squared) - double xspan = (xmax - xmin).squaredMagnitude(); - - // Same for y & z spans - double yspan = (ymax - ymin).squaredMagnitude(); - double zspan = (zmax - zmin).squaredMagnitude(); - - double maxspan = xspan; - - if (yspan > maxspan) { - maxspan = yspan; - dia1 = ymin; - dia2 = ymax; - } - - if (zspan > maxspan) { - maxspan = zspan; - dia1 = zmin; - dia2 = zmax; - } - } - - - // dia1, dia2 is a diameter of initial sphere - - // calc initial center - Vector3 center = (dia1 + dia2) / 2.0; - - // calculate initial radius^2 and radius - Vector3 d = dia2 - sphere.center; - - double radSq = d.squaredMagnitude(); - double rad = sqrt(radSq); - - // SECOND PASS: increment current sphere - double old_to_p, old_to_new; - - for (int v = 0; v < vertexArray.size(); ++v) { - const Vector3& vertex = vertexArray[v]; - - d = vertex - center; - - double old_to_p_sq = d.squaredMagnitude(); - - // do r^2 test first - if (old_to_p_sq > radSq) { - // this point is outside of current sphere - old_to_p = sqrt(old_to_p_sq); - - // calc radius of new sphere - rad = (rad + old_to_p) / 2.0; - - // for next r^2 compare - radSq = rad * rad; - old_to_new = old_to_p - rad; - - // calc center of new sphere - center = (rad * center + old_to_new * vertex) / old_to_p; - } - } - - const Vector3 min(xmin.x, ymin.y, zmin.z); - const Vector3 max(xmax.x, ymax.y, zmax.z); - - box = Box(min, max); - - const double boxRadSq = (max - min).squaredMagnitude() * 0.25; - - if (boxRadSq >= radSq){ - if (isNaN(center.x) || ! isFinite(rad)) { - sphere = Sphere(Vector3::zero(), inf()); - } else { - sphere = Sphere(center, rad); - } - }else{ - sphere = Sphere((max + min) * 0.5, sqrt(boxRadSq)); - } -} - - -void MeshAlg::computeTangentVectors( - const Vector3& normal, - const Vector3 position[3], - const Vector2 texCoord[3], - Vector3& tangent, - Vector3& binormal) { - - Vector3 v[3]; - Vector2 t[3]; - - // TODO: don't need the copy - // Make a copy so that we can sort - for (int i = 0; i < 3; ++i) { - v[i] = position[i]; - t[i] = texCoord[i]; - } - - ///////////////////////////////////////////////// - // Begin by computing the tangent - - // Bubble sort the vertices by decreasing texture coordinate y. - if (t[0].y < t[1].y) { - std::swap(v[0], v[1]); - std::swap(t[0], t[1]); - } - - // t0 >= t1 - - if (t[0].y < t[2].y) { - std::swap(v[0], v[2]); - std::swap(t[0], t[2]); - } - - // t0 >= t2, t0 >= t1 - - if (t[1].y < t[2].y) { - std::swap(v[1], v[2]); - std::swap(t[1], t[2]); - } - - // t0 >= t1 >= t2 - - float amount; - - // Compute the direction of constant y. - if (fuzzyEq(t[2].y, t[0].y)) { - // Degenerate case-- the texture coordinates do not vary across this - // triangle. - amount = 1.0; - } else { - // Solve lerp(t[0].y, t[2].y, amount) = t[1].y for amount: - // - // t0 + (t2 - t0) * a = t1 - // a = (t1 - t0) / (t2 - t0) - - amount = (t[1].y - t[0].y) / (t[2].y - t[0].y); - } - - tangent = lerp(v[0], v[2], amount) - v[1]; - - // Make sure the tangent points in the right direction and is - // perpendicular to the normal. - if (lerp(t[0].x, t[2].x, amount) < t[1].x) { - tangent = -tangent; - } - - // TODO: do we need this? We take this component off - // at the end anyway - tangent -= tangent.dot(normal) * normal; - - // Normalize the tangent so it contributes - // equally at the vertex (TODO: do we need this?) - if (fuzzyEq(tangent.magnitude(), 0.0)) { - tangent = Vector3::unitX(); - } else { - tangent = tangent.direction(); - } - - ////////////////////////////////////////////////// - // Now compute the binormal (same code, but in x) - - // Sort the vertices by texture coordinate x. - if (t[0].x < t[1].x) { - std::swap(v[0], v[1]); - std::swap(t[0], t[1]); - } - - if (t[0].x < t[2].x) { - std::swap(v[0], v[2]); - std::swap(t[0], t[2]); - } - - if (t[1].x < t[2].x) { - std::swap(v[1], v[2]); - std::swap(t[1], t[2]); - } - - // Compute the direction of constant x. - if (fuzzyEq(t[2].x, t[0].x)) { - amount = 1.0; - } else { - amount = (t[1].x - t[0].x) / (t[2].x - t[0].x); - } - - binormal = lerp(v[0], v[2], amount) - v[1]; - - // Make sure the binormal points in the right direction and is - // perpendicular to the normal. - if (lerp(t[0].y, t[2].y, amount) < t[1].y) { - binormal = -binormal; - } - - binormal -= binormal.dot(normal) * normal; - - // Normalize the binormal so that it contributes - // an equal amount to the per-vertex value (TODO: do we need this? - // Nelson Max showed that we don't for computing per-vertex normals) - if (fuzzyEq(binormal.magnitude(), 0.0)) { - binormal = Vector3::unitZ(); - } else { - binormal = binormal.direction(); - } - - // This computation gives the opposite convention of what we want. - binormal = -binormal; - -} - - -void MeshAlg::computeTangentSpaceBasis( - const Array& vertexArray, - const Array& texCoordArray, - const Array& vertexNormalArray, - const Array& faceArray, - Array& tangent, - Array& binormal) { - - debugAssertM(faceArray.size() != 0, "Unable to calculate valid tangent space without faces."); - - // The three vertices and texCoords of each face - Vector3 position[3]; - Vector2 texCoord[3]; - Vector3 t, b; - - tangent.resize(vertexArray.size()); - binormal.resize(vertexArray.size()); - - // Zero the output arrays. - System::memset(tangent.getCArray(), 0, sizeof(Vector3) * tangent.size()); - System::memset(binormal.getCArray(), 0, sizeof(Vector3) * binormal.size()); - - // Iterate over faces, computing the tangent vectors for each - // vertex. Accumulate those into the tangent and binormal arrays - // and then orthonormalize at the end. - - for (int f = 0; f < faceArray.size(); ++f) { - const Face& face = faceArray[f]; - - for (int v = 0; v < 3; ++v) { - int i = face.vertexIndex[v]; - position[v] = vertexArray[i]; - texCoord[v] = texCoordArray[i]; - } - - const Vector3 faceNormal((position[1] - position[0]).cross(position[2] - position[0]).direction()); - computeTangentVectors(faceNormal, position, texCoord, t, b); - - for (int v = 0; v < 3; ++v) { - int i = face.vertexIndex[v]; - tangent[i] += t; - binormal[i] += b; - } - } - - // Normalize the basis vectors - for (int v = 0; v < vertexArray.size(); ++v) { - // Remove the component parallel to the normal - const Vector3& N = vertexNormalArray[v]; - debugAssertM(N.isUnit() || N.isZero(), "Input normals must have unit length"); - - tangent[v] -= tangent[v].dot(N) * N; - binormal[v] -= binormal[v].dot(N) * N; - - // Normalize - tangent[v] = tangent[v].directionOrZero(); - binormal[v] = binormal[v].directionOrZero(); - - // Note that the tangent and binormal might not be perpendicular anymore - } -} - - - -} // G3D namespace diff --git a/externals/g3dlite/G3D.lib/source/MeshAlgAdjacency.cpp b/externals/g3dlite/G3D.lib/source/MeshAlgAdjacency.cpp deleted file mode 100644 index a8b35f32c86..00000000000 --- a/externals/g3dlite/G3D.lib/source/MeshAlgAdjacency.cpp +++ /dev/null @@ -1,729 +0,0 @@ -/** - @file MeshAlgAdjacency.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - @created 2003-09-14 - @edited 2005-02-24 - - Copyright 2000-2003, Morgan McGuire. - All rights reserved. - - */ - -#include "G3D/Table.h" -#include "G3D/MeshAlg.h" -#include "G3D/Set.h" - - -namespace G3D { - -/** - A half [i.e. directed] edge. - */ -class MeshDirectedEdgeKey { -public: - - /** vertexIndex[0] <= vertexIndex[1] */ - int vertexIndex[2]; - - MeshDirectedEdgeKey() {} - - MeshDirectedEdgeKey( - const int i0, - const int i1) { - - if (i0 <= i1) { - vertexIndex[0] = i0; - vertexIndex[1] = i1; - } else { - vertexIndex[0] = i1; - vertexIndex[1] = i0; - } - } - - - bool operator==(const MeshDirectedEdgeKey& e2) const { - for (int i = 0; i < 2; ++i) { - if (vertexIndex[i] != e2.vertexIndex[i]) { - return false; - } - } - return true; - } -}; - -} - -template<> struct HashTrait { - static size_t hashCode(const G3D::MeshDirectedEdgeKey& key) { - return key.vertexIndex[0] + (key.vertexIndex[1] << 16); - } -}; - -namespace G3D { - -/** - A hashtable mapping edges to lists of indices for - faces. This is used instead of Table because of the - special logic in insert. - - Used only for MeshAlg::computeAdjacency. - - In the face lists, index f >= 0 indicates that - f contains the edge as a forward edge. Index f < 0 - indicates that ~f contains the edge as a backward edge. - */ -class MeshEdgeTable { -public: - typedef Table > ET; - -private: - - ET table; - -public: - - /** - Clears the table. - */ - void clear() { - table.clear(); - } - - /** - Inserts the faceIndex into the edge's face list. - The index may be a negative number indicating a backface. - */ - void insert(const MeshDirectedEdgeKey& edge, int faceIndex) { - - // debugAssertM((table.size() > 20) && (table.debugGetLoad() < 0.5 || table.debugGetNumBuckets() < 20), - // "MeshEdgeTable is using a poor hash function."); - - if (! table.containsKey(edge)) { - // First time - Array x(1); - x[0] = faceIndex; - table.set(edge, x); - } else { - table[edge].append(faceIndex); - } - } - - /** - Returns the face list for a given edge - */ - const Array& get(const MeshDirectedEdgeKey& edge) { - return table[edge]; - } - - ET::Iterator begin() { - return table.begin(); - } - - const ET::Iterator end() const { - return table.end(); - } - -}; - - -/** - edgeTable[edgeKey] is a list of faces containing - - Used and cleared by MeshModel::computeAdjacency() - */ -static MeshEdgeTable edgeTable; - -/** - Assigns the edge index into the next unassigned edge - index. The edge index may be negative, indicating - a reverse edge. - */ -static void assignEdgeIndex(MeshAlg::Face& face, int e) { - for (int i = 0; i < 3; ++i) { - if (face.edgeIndex[i] == MeshAlg::Face::NONE) { - face.edgeIndex[i] = e; - return; - } - } - - debugAssertM(false, "Face has already been assigned 3 edges"); -} - - -void MeshAlg::computeAdjacency( - const Array& vertexGeometry, - const Array& indexArray, - Array& faceArray, - Array& edgeArray, - Array< Array >& adjacentFaceArray) { - - Array vertexArray; - - computeAdjacency(vertexGeometry, indexArray, faceArray, edgeArray, vertexArray); - - // Convert the vertexArray into adjacentFaceArray - adjacentFaceArray.clear(); - adjacentFaceArray.resize(vertexArray.size()); - for (int v = 0; v < adjacentFaceArray.size(); ++v) { - adjacentFaceArray[v] = vertexArray[v].faceIndex; - } -} - - -void MeshAlg::computeAdjacency( - const Array& vertexGeometry, - const Array& indexArray, - Array& faceArray, - Array& edgeArray, - Array& vertexArray) { - - edgeArray.clear(); - vertexArray.clear(); - faceArray.clear(); - edgeTable.clear(); - - // Face normals - Array faceNormal; - - // This array has the same size as the vertex array - vertexArray.resize(vertexGeometry.size()); - - // Iterate through the triangle list - for (int q = 0; q < indexArray.size(); q += 3) { - - Vector3 vertex[3]; - int f = faceArray.size(); - MeshAlg::Face& face = faceArray.next(); - - // Construct the face - for (int j = 0; j < 3; ++j) { - int v = indexArray[q + j]; - face.vertexIndex[j] = v; - face.edgeIndex[j] = Face::NONE; - - // Store back pointers in the vertices - vertexArray[v].faceIndex.append(f); - - // We'll need these vertices to find the face normal - vertex[j] = vertexGeometry[v]; - } - - // Compute the face normal - Vector3 N = (vertex[1] - vertex[0]).cross(vertex[2] - vertex[0]); - faceNormal.append(N.directionOrZero()); - - static const int nextIndex[] = {1, 2, 0}; - - // Add each edge to the edge table. - for (int j = 0; j < 3; ++j) { - const int i0 = indexArray[q + j]; - const int i1 = indexArray[q + nextIndex[j]]; - - const MeshDirectedEdgeKey edge(i0, i1); - - if (i0 == edge.vertexIndex[0]) { - // The edge was directed in the same manner as in the face - edgeTable.insert(edge, f); - } else { - // The edge was directed in the opposite manner as in the face - edgeTable.insert(edge, ~f); - } - } - } - - // For each edge in the edge table, create an edge in the edge array. - // Collapse every 2 edges from adjacent faces. - - MeshEdgeTable::ET::Iterator cur = edgeTable.begin(); - MeshEdgeTable::ET::Iterator end = edgeTable.end(); - - Array tempEdgeArray; - while (cur != end) { - MeshDirectedEdgeKey& edgeKey = cur->key; - Array& faceIndexArray = cur->value; - - // Process this edge - while (faceIndexArray.size() > 0) { - - // Remove the last index - int f0 = faceIndexArray.pop(); - - // Find the normal to that face - const Vector3& n0 = faceNormal[(f0 >= 0) ? f0 : ~f0]; - - bool found = false; - - // We try to find the matching face with the closest - // normal. This ensures that we don't introduce a lot - // of artificial ridges into flat parts of a mesh. - double ndotn = -2; - int f1 = -1, i1 = -1; - - // Try to Find the face with the matching edge - for (int i = faceIndexArray.size() - 1; i >= 0; --i) { - int f = faceIndexArray[i]; - - if ((f >= 0) != (f0 >= 0)) { - // This face contains the oppositely oriented edge - // and has not been assigned too many edges - - const Vector3& n1 = faceNormal[(f >= 0) ? f : ~f]; - double d = n1.dot(n0); - - if (found) { - // We previously found a good face; see if this - // one is better. - if (d > ndotn) { - // This face is better. - ndotn = d; - f1 = f; - i1 = i; - } - } else { - // This is the first face we've found - found = true; - ndotn = d; - f1 = f; - i1 = i; - } - } - } - - // Create the new edge - int e = tempEdgeArray.size(); - Edge& edge = tempEdgeArray.next(); - - edge.vertexIndex[0] = edgeKey.vertexIndex[0]; - edge.vertexIndex[1] = edgeKey.vertexIndex[1]; - - if (f0 >= 0) { - edge.faceIndex[0] = f0; - edge.faceIndex[1] = Face::NONE; - assignEdgeIndex(faceArray[f0], e); - } else { - // The face indices above are two's complemented. - // this code restores them to regular indices. - debugAssert((~f0) >= 0); - edge.faceIndex[1] = ~f0; - edge.faceIndex[0] = Face::NONE; - - // The edge index *does* need to be inverted, however. - assignEdgeIndex(faceArray[~f0], ~e); - } - - if (found) { - // We found a matching face; remove both - // faces from the active list. - faceIndexArray.fastRemove(i1); - - if (f1 >= 0) { - edge.faceIndex[0] = f1; - assignEdgeIndex(faceArray[f1], e); - } else { - edge.faceIndex[1] = ~f1; - assignEdgeIndex(faceArray[~f1], ~e); - } - } - } - - ++cur; - } - - edgeTable.clear(); - - // Move boundary edges to the end of the list and then - // clean up the face references into them - { - // Map old edge indices to new edge indices - Array newIndex(tempEdgeArray.size()); - - - // Index of the start and end of the edge array - int i = 0; - int j = tempEdgeArray.size() - 1; - - edgeArray.resize(tempEdgeArray.size()); - for (int e = 0; e < tempEdgeArray.size(); ++e) { - if (tempEdgeArray[e].boundary()) { - newIndex[e] = j; - --j; - } else { - newIndex[e] = i; - ++i; - } - edgeArray[newIndex[e]] = tempEdgeArray[e]; - } - - debugAssertM(i == j + 1, "Counting from front and back of array did not match"); - - // Fix the faces - for (int f = 0; f < faceArray.size(); ++f) { - Face& face = faceArray[f]; - for (int q = 0; q < 3; ++q) { - int e = face.edgeIndex[q]; - if (e < 0) { - // Backwards edge; twiddle before and after conversion - face.edgeIndex[q] = ~newIndex[~e]; - } else { - // Regular edge; remap the index - face.edgeIndex[q] = newIndex[e]; - } - } - } - } - - // Now order the edge indices inside the faces correctly. - for (int f = 0; f < faceArray.size(); ++f) { - Face& face = faceArray[f]; - int e0 = face.edgeIndex[0]; - int e1 = face.edgeIndex[1]; - int e2 = face.edgeIndex[2]; - - // e0 will always remain first. The only - // question is whether e1 and e2 should be swapped. - - // See if e1 begins at the vertex where e1 ends. - const int e0End = (e0 < 0) ? - edgeArray[~e0].vertexIndex[0] : - edgeArray[e0].vertexIndex[1]; - - const int e1Begin = (e1 < 0) ? - edgeArray[~e1].vertexIndex[1] : - edgeArray[e1].vertexIndex[0]; - - if (e0End != e1Begin) { - // We must swap e1 and e2 - face.edgeIndex[1] = e2; - face.edgeIndex[2] = e1; - } - } - - // Fill out the edge adjacency information in the vertex array - for (int e = 0; e < edgeArray.size(); ++e) { - const Edge& edge = edgeArray[e]; - vertexArray[edge.vertexIndex[0]].edgeIndex.append(e); - vertexArray[edge.vertexIndex[1]].edgeIndex.append(~e); - } -} - - -void MeshAlg::weldBoundaryEdges( - Array& faceArray, - Array& edgeArray, - Array& vertexArray) { - - // Copy over the original edge array - Array oldEdgeArray = edgeArray; - - // newEdgeIndex[e] is the new index of the old edge with index e - // Note that newEdgeIndex[e] might be negative, indicating that - // the edge switched direction between the arrays. - Array newEdgeIndex(edgeArray.size()); - edgeArray.resize(0); - - // boundaryEdgeIndices[v_low] is an array of the indices of - // all boundary edges whose lower vertex is v_low. - Table > boundaryEdgeIndices; - - // Copy over non-boundary edges to the new array - for (int e = 0; e < oldEdgeArray.size(); ++e) { - if (oldEdgeArray[e].boundary()) { - - // Add to the boundary table - const int v_low = iMin(oldEdgeArray[e].vertexIndex[0], oldEdgeArray[e].vertexIndex[1]); - if (! boundaryEdgeIndices.containsKey(v_low)) { - boundaryEdgeIndices.set(v_low, Array()); - } - boundaryEdgeIndices[v_low].append(e); - - // We'll fill out newEdgeIndex[e] later, when we find pairs - - } else { - - // Copy the edge to the new array - newEdgeIndex[e] = edgeArray.size(); - edgeArray.append(oldEdgeArray[e]); - - } - } - - - // Remove all edges from the table that have pairs. - Table >::Iterator cur = boundaryEdgeIndices.begin(); - Table >::Iterator end = boundaryEdgeIndices.end(); - while (cur != end) { - Array& boundaryEdge = cur->value; - - for (int i = 0; i < boundaryEdge.size(); ++i) { - int ei = boundaryEdge[i]; - const Edge& edgei = oldEdgeArray[ei]; - - for (int j = i + 1; j < boundaryEdge.size(); ++j) { - int ej = boundaryEdge[j]; - const Edge& edgej = oldEdgeArray[ej]; - - // See if edge ei is the reverse (match) of edge ej. - - // True if the edges match - bool match = false; - - // True if edgej's vertex indices are reversed from - // edgei's (usually true). - bool reversej = false; - - int u = edgei.vertexIndex[0]; - int v = edgei.vertexIndex[1]; - - if (edgei.faceIndex[0] != Face::NONE) { - // verts|faces - // edgei = [u v A /] - - if (edgej.faceIndex[0] != Face::NONE) { - if ((edgej.vertexIndex[0] == v) && (edgej.vertexIndex[1] == u)) { - // This is the most common of the four cases - - // edgej = [v u B /] - match = true; - reversej = true; - } - } else { - if ((edgej.vertexIndex[0] == u) && (edgej.vertexIndex[1] == v)) { - // edgej = [u v / B] - match = true; - } - } - } else { - // edgei = [u v / A] - if (edgej.faceIndex[0] != Face::NONE) { - if ((edgej.vertexIndex[0] == u) && (edgej.vertexIndex[1] == v)) { - // edgej = [u v B /] - match = true; - } - } else { - if ((edgej.vertexIndex[0] == v) && (edgej.vertexIndex[1] == u)) { - // edgej = [v u / B] - match = true; - reversej = true; - } - } - } - - if (match) { - // ei and ej can be paired as a single edge - int e = edgeArray.size(); - Edge& edge = edgeArray.next(); - - // Follow the direction of edgei. - edge = edgei; - newEdgeIndex[ei] = e; - - // Insert the face index for edgej. - int fj = edgej.faceIndex[0]; - if (fj == Face::NONE) { - fj = edgej.faceIndex[1]; - } - - if (edge.faceIndex[0] == Face::NONE) { - edge.faceIndex[0] = fj; - } else { - edge.faceIndex[1] = fj; - } - - if (reversej) { - // The new edge is backwards of the old edge for ej - newEdgeIndex[ej] = ~e; - } else { - newEdgeIndex[ej] = e; - } - - // Remove both ei and ej from being candidates for future pairing. - // Remove ej first since it comes later in the list (removing - // ei would decrease the index of ej to j - 1). - boundaryEdge.fastRemove(j); - boundaryEdge.fastRemove(i); - - // Re-process element i, which is now a new edge index - --i; - - // Jump out of the j for-loop - break; - } - } - } - ++cur; - } - - // Anything remaining in the table is a real boundary edge; just copy it to - // the end of the array. - cur = boundaryEdgeIndices.begin(); - end = boundaryEdgeIndices.end(); - while (cur != end) { - Array& boundaryEdge = cur->value; - - for (int b = 0; b < boundaryEdge.size(); ++b) { - const int e = boundaryEdge[b]; - - newEdgeIndex[e] = edgeArray.size(); - edgeArray.append(oldEdgeArray[e]); - } - - ++cur; - } - - // Finally, fix up edge indices in the face and vertex arrays - for (int f = 0; f < faceArray.size(); ++f) { - Face& face = faceArray[f]; - for (int i = 0; i < 3; ++i) { - int e = face.edgeIndex[i]; - - if (e < 0) { - face.edgeIndex[i] = ~newEdgeIndex[~e]; - } else { - face.edgeIndex[i] = newEdgeIndex[e]; - } - } - } - - for (int v = 0; v < vertexArray.size(); ++v) { - Vertex& vertex = vertexArray[v]; - for (int i = 0; i < vertex.edgeIndex.size(); ++i) { - int e = vertex.edgeIndex[i]; - - if (e < 0) { - vertex.edgeIndex[i] = ~newEdgeIndex[~e]; - } else { - vertex.edgeIndex[i] = newEdgeIndex[e]; - } - } - } -} - - -void MeshAlg::weldAdjacency( - const Array& originalGeometry, - Array& faceArray, - Array& edgeArray, - Array& vertexArray, - double radius) { - - // Num vertices - const int n = originalGeometry.size(); - - // canonical[v] = first occurance of any vertex near oldVertexArray[v] - Array canonical(n); - - Array toNew, toOld; - // Throw away the new vertex array - Array dummy; - computeWeld(originalGeometry, dummy, toNew, toOld, radius); - - for (int v = 0; v < canonical.size(); ++v) { - // Round-trip through the toNew/toOld process. This will give - // us the original vertex. - canonical[v] = toOld[toNew[v]]; - } - - // Destroy vertexArray (we reconstruct it below) - vertexArray.clear(); - vertexArray.resize(n); - - bool hasBoundaryEdges = false; - - // Fix edge vertex indices - for (int e = 0; e < edgeArray.size(); ++e) { - Edge& edge = edgeArray[e]; - - const int v0 = canonical[edge.vertexIndex[0]]; - const int v1 = canonical[edge.vertexIndex[1]]; - - edge.vertexIndex[0] = v0; - edge.vertexIndex[1] = v1; - - vertexArray[v0].edgeIndex.append(e); - vertexArray[v1].edgeIndex.append(~e); - - hasBoundaryEdges = hasBoundaryEdges || edge.boundary(); - } - - // Fix face vertex indices - for (int f = 0; f < faceArray.size(); ++f) { - Face& face = faceArray[f]; - for (int i = 0; i < 3; ++i) { - const int v = canonical[face.vertexIndex[i]]; - - face.vertexIndex[i] = v; - - // Add the back pointer - vertexArray[v].faceIndex.append(f); - } - } - - if (hasBoundaryEdges) { - // As a result of the welding, some of the boundary edges at - // the end of the array may now have mates and no longer be - // boundaries. Try to pair these up. - - weldBoundaryEdges(faceArray, edgeArray, vertexArray); - } -} - - -void MeshAlg::debugCheckConsistency( - const Array& faceArray, - const Array& edgeArray, - const Array& vertexArray) { - -#ifdef _DEBUG - for (int v = 0; v < vertexArray.size(); ++v) { - const MeshAlg::Vertex& vertex = vertexArray[v]; - - for (int i = 0; i < vertex.edgeIndex.size(); ++i) { - const int e = vertex.edgeIndex[i]; - debugAssert(edgeArray[(e >= 0) ? e : ~e].containsVertex(v)); - } - - for (int i = 0; i < vertex.faceIndex.size(); ++i) { - const int f = vertex.faceIndex[i]; - debugAssert(faceArray[f].containsVertex(v)); - } - - } - - for (int e = 0; e < edgeArray.size(); ++e) { - const MeshAlg::Edge& edge = edgeArray[e]; - - for (int i = 0; i < 2; ++i) { - debugAssert((edge.faceIndex[i] == MeshAlg::Face::NONE) || - faceArray[edge.faceIndex[i]].containsEdge(e)); - - debugAssert(vertexArray[edge.vertexIndex[i]].inEdge(e)); - } - } - - // Every face's edge must be on that face - for (int f = 0; f < faceArray.size(); ++f) { - const MeshAlg::Face& face = faceArray[f]; - for (int i = 0; i < 3; ++i) { - int e = face.edgeIndex[i]; - int ei = (e >= 0) ? e : ~e; - debugAssert(edgeArray[ei].inFace(f)); - - // Make sure the edge is oriented appropriately - if (e >= 0) { - debugAssert(edgeArray[ei].faceIndex[0] == (int)f); - } else { - debugAssert(edgeArray[ei].faceIndex[1] == (int)f); - } - - debugAssert(vertexArray[face.vertexIndex[i]].inFace(f)); - } - } -#else - (void)faceArray; - (void)edgeArray; - (void)vertexArray; -#endif // _DEBUG -} - -} // G3D namespace diff --git a/externals/g3dlite/G3D.lib/source/MeshAlgWeld.cpp b/externals/g3dlite/G3D.lib/source/MeshAlgWeld.cpp deleted file mode 100644 index cd4d1f9c7d5..00000000000 --- a/externals/g3dlite/G3D.lib/source/MeshAlgWeld.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/** - @file MeshAlgWeld.cpp - - The MeshAlg::computeWeld method. - - @maintainer Morgan McGuire, matrix@graphics3d.com - @created 2003-10-22 - @edited 2005-02-24 - - Copyright 2000-2003, Morgan McGuire. - All rights reserved. - - */ - -#include "G3D/MeshAlg.h" -#include "G3D/Table.h" -#include "G3D/Set.h" - -namespace G3D { - -namespace _internal { - -class Welder { -private: - - // Intentionally illegal - Welder& operator=(const Welder& w); - -public: - /** Indices of newVertexArray elements in or near a grid cell. */ - typedef Array List; - - enum {GRID_RES = 32}; - - List grid[GRID_RES][GRID_RES][GRID_RES]; - - const Array& oldVertexArray; - Array& newVertexArray; - Array& toNew; - Array& toOld; - - /** Must be less than one grid cell, not checked */ - const double radius; - - /** (oldVertexArray[i] - offset) * scale is on the range [0, 1] */ - Vector3 offset; - Vector3 scale; - - Welder( - const Array& _oldVertexArray, - Array& _newVertexArray, - Array& _toNew, - Array& _toOld, - double _radius); - - /** - Computes the grid index from an ordinate. - */ - void toGridCoords(Vector3 v, int& x, int& y, int& z) const; - - /** Gets the index of a vertex, adding it to - newVertexArray if necessary. */ - int getIndex(const Vector3& vertex); - - void weld(); -}; - -} // namespace _internal - -} // namespace G3D - -template<> struct HashTrait { - static size_t hashCode(const G3D::_internal::Welder::List* key) { return reinterpret_cast(key); } -}; - -namespace G3D { -namespace _internal { - -Welder::Welder( - const Array& _oldVertexArray, - Array& _newVertexArray, - Array& _toNew, - Array& _toOld, - double _radius) : - oldVertexArray(_oldVertexArray), - newVertexArray(_newVertexArray), - toNew(_toNew), - toOld(_toOld), - radius(_radius) { - - // Compute a scale factor that moves the range - // of all ordinates to [0, 1] - Vector3 minBound = Vector3::inf(); - Vector3 maxBound = -minBound; - - for (int i = 0; i < oldVertexArray.size(); ++i) { - minBound = minBound.min(oldVertexArray[i]); - maxBound = maxBound.max(oldVertexArray[i]); - } - - offset = minBound; - scale = maxBound - minBound; - for (int i = 0; i < 3; ++i) { - // The model might have zero extent along some axis - if (fuzzyEq(scale[i], 0.0)) { - scale[i] = 1.0; - } else { - scale[i] = 1.0 / scale[i]; - } - } -} - - -void Welder::toGridCoords(Vector3 v, int& x, int& y, int& z) const { - v = (v - offset) * scale; - x = iClamp(iFloor(v.x * GRID_RES), 0, GRID_RES - 1); - y = iClamp(iFloor(v.y * GRID_RES), 0, GRID_RES - 1); - z = iClamp(iFloor(v.z * GRID_RES), 0, GRID_RES - 1); -} - - -int Welder::getIndex(const Vector3& vertex) { - - int closestIndex = -1; - double distanceSquared = inf(); - - int ix, iy, iz; - toGridCoords(vertex, ix, iy, iz); - - // Check against all vertices within radius of this grid cube - const List& list = grid[ix][iy][iz]; - - for (int i = 0; i < list.size(); ++i) { - double d = (newVertexArray[list[i]] - vertex).squaredMagnitude(); - - if (d < distanceSquared) { - distanceSquared = d; - closestIndex = list[i]; - } - } - - if (distanceSquared <= radius * radius) { - - return closestIndex; - - } else { - - // This is a new vertex - int newIndex = newVertexArray.size(); - newVertexArray.append(vertex); - - // Create a new vertex and store its index in the - // neighboring grid cells (usually, only 1 neighbor) - - Set neighbors; - - for (float dx = -1; dx <= +1; ++dx) { - for (float dy = -1; dy <= +1; ++dy) { - for (float dz = -1; dz <= +1; ++dz) { - int ix, iy, iz; - toGridCoords(vertex + Vector3(dx, dy, dz) * radius, ix, iy, iz); - neighbors.insert(&(grid[ix][iy][iz])); - } - } - } - - Set::Iterator neighbor(neighbors.begin()); - Set::Iterator none(neighbors.end()); - - while (neighbor != none) { - (*neighbor)->append(newIndex); - ++neighbor; - } - - return newIndex; - } -} - - -void Welder::weld() { - newVertexArray.resize(0); - - // Prime the vertex positions - for (int i = 0; i < oldVertexArray.size(); ++i) { - getIndex(oldVertexArray[i]); - } - - // Now create the official remapping by snapping to - // nearby vertices. - toNew.resize(oldVertexArray.size()); - toOld.resize(newVertexArray.size()); - - for (int oi = 0; oi < oldVertexArray.size(); ++oi) { - toNew[oi] = getIndex(oldVertexArray[oi]); - toOld[toNew[oi]] = oi; - } -} - -} // internal namespace - - -void MeshAlg::computeWeld( - const Array& oldVertexArray, - Array& newVertexArray, - Array& toNew, - Array& toOld, - double radius) { - - _internal::Welder welder(oldVertexArray, newVertexArray, toNew, toOld, radius); - welder.weld(); -} - -} // G3D namespace diff --git a/externals/g3dlite/G3D.lib/source/MeshAlgWeld2.cpp b/externals/g3dlite/G3D.lib/source/MeshAlgWeld2.cpp deleted file mode 100644 index 13f731353a6..00000000000 --- a/externals/g3dlite/G3D.lib/source/MeshAlgWeld2.cpp +++ /dev/null @@ -1,377 +0,0 @@ -/** - @file MeshAlgWeld2.cpp - - @author Morgan McGuire, Kyle Whitson, Corey Taylor - - @created 2008-07-30 - @edited 2008-11-10 - */ - -#include "G3D/platform.h" -#include "G3D/Vector2.h" -#include "G3D/Vector3.h" -#include "G3D/Sphere.h" -#include "G3D/PointHashGrid.h" -#include "G3D/MeshAlg.h" - -namespace G3D { namespace _internal{ - -/** Used by WeldHelper2::smoothNormals. */ -class VN { -public: - Vector3 vertex; - Vector3 normal; - - VN() {} - VN(const Vector3& v, const Vector3& n) : vertex(v), normal(n) {} -}; - -/** Used by WeldHelper::getIndex to maintain a list of vertices by location. */ -class VNTi { -public: - Vector3 vertex; - Vector3 normal; - Vector2 texCoord; - int index; - - VNTi() : index(0) {} - - VNTi(const Vector3& v, const Vector3& n, const Vector2& t, int i) : - vertex(v), normal(n), texCoord(t), index(i) {} -}; - - -}} // G3D - -template <> struct HashTrait { - static size_t hashCode(const G3D::_internal::VN& k) { return static_cast(k.vertex.hashCode()); } -}; -template <> struct HashTrait { - static size_t hashCode(const G3D::_internal::VNTi& k) { return static_cast(k.vertex.hashCode()); } -}; - - -template<> struct EqualsTrait { - static bool equals(const G3D::_internal::VN& a, const G3D::_internal::VN& b) { return a.vertex == b.vertex; } -}; -template<> struct EqualsTrait { - static bool equals(const G3D::_internal::VNTi& a, const G3D::_internal::VNTi& b) { return a.vertex == b.vertex; } -}; - -template<> struct PositionTrait { - static void getPosition(const G3D::_internal::VN& v, G3D::Vector3& p) { p = v.vertex; } -}; -template<> struct PositionTrait { - static void getPosition(const G3D::_internal::VNTi& v, G3D::Vector3& p) { p = v.vertex; } -}; - -namespace G3D { namespace _internal { - -class WeldHelper { -private: - /** Used by getIndex and updateTriLists */ - PointHashGrid weldGrid; - - Array* outputVertexArray; - Array* outputNormalArray; - Array* outputTexCoordArray; - - float vertexWeldRadius; - /** Squared radius allowed for welding similar normals. */ - float normalWeldRadius2; - float texCoordWeldRadius2; - - float normalSmoothingAngle; - - /** - Returns the index of the vertex in - outputVertexArray/outputNormalArray/outputTexCoordArray - that is within the global tolerances of v,n,t. If there - is no such vertex, adds it to the arrays and returns that index. - - Called from updateTriLists(). - */ - int getIndex(const Vector3& v, const Vector3& n, const Vector2& t) { - PointHashGrid::SphereIterator it = - weldGrid.beginSphereIntersection(Sphere(v, vertexWeldRadius)); - - if (n.isZero()) { - // Don't bother trying to match the surface normal, since this vertex has no surface normal. - while (it.hasMore()) { - if ((t - it->texCoord).squaredLength() <= texCoordWeldRadius2) { - // This is the vertex - return it->index; - } - ++it; - } - } else { - while (it.hasMore()) { - if (((n - it->normal).squaredLength() <= normalWeldRadius2) && - ((t - it->texCoord).squaredLength() <= texCoordWeldRadius2)) { - // This is the vertex - return it->index; - } - ++it; - } - } - - // Note that a sliver triangle processed before its neighbors may reach here - // with a zero length normal. - - // The vertex does not exist. Create it. - const int i = outputVertexArray->size(); - outputVertexArray->append(v); - outputNormalArray->append(n); - outputTexCoordArray->append(t); - - // Store in the grid so that it will be remembered. - weldGrid.insert(VNTi(v, n, t, i)); - - return i; - } - - - /** - Updates each indexArray to refer to vertices in the - outputVertexArray. - - Called from process() - */ - void updateTriLists( - Array*>& indexArrayArray, - const Array& vertexArray, - const Array& normalArray, - const Array& texCoordArray) { - - // Compute a hash grid so that we can find neighbors quickly. - // It begins empty and is extended as the tri lists are iterated - // through. - weldGrid.clear(); - - // Process all triLists - int numTriLists = indexArrayArray.size(); - int u = 0; - for (int t = 0; t < numTriLists; ++t) { - Array& triList = *(indexArrayArray[t]); - - // For all vertices in this list - for (int v = 0; v < triList.size(); ++v) { - // This vertex mapped to u in the flatVertexArray - triList[v] = getIndex(vertexArray[u], normalArray[u], texCoordArray[u]); - - /* -# ifdef G3D_DEBUG - { - int i = triList[v]; - Vector3 N = normalArray[i]; - debugAssertM(N.length() > 0.9f, "Produced non-unit normal"); - } -# endif - */ - ++u; - } - } - } - - /** Expands the indexed triangle lists into a triangle list. - - Called from process() */ - void unroll( - const Array*>& indexArrayArray, - const Array& vertexArray, - const Array& texCoordArray, - Array& unrolledVertexArray, - Array& unrolledTexCoordArray) { - - int numTriLists = indexArrayArray.size(); - for (int t = 0; t < numTriLists; ++t) { - const Array& triList = *(indexArrayArray[t]); - for (int v = 0; v < triList.size(); ++v) { - int i = triList[v]; - unrolledVertexArray.append(vertexArray[i]); - unrolledTexCoordArray.append(texCoordArray[i]); - } - } - } - - /** For every three vertices, compute the face normal and store it three times. - Sliver triangles have a zero surface normal, which we will later take to - match *any* surface normal. */ - void computeFaceNormals( - const Array& vertexArray, - Array& faceNormalArray) { - - debugAssertM(vertexArray.size() % 3 == 0, "Input is not a triangle soup"); - debugAssertM(faceNormalArray.size() == 0, "Output must start empty."); - - for (int v = 0; v < vertexArray.size(); v += 3) { - const Vector3& e0 = vertexArray[v + 1] - vertexArray[v]; - const Vector3& e1 = vertexArray[v + 2] - vertexArray[v]; - - // Note that the length may be zero in the case of sliver polygons, e.g., - // those correcting a T-junction. - const Vector3& n = e0.cross(e1).directionOrZero(); - - // Append the normal once per vertex. - faceNormalArray.append(n, n, n); - } - } - - - /** - Computes @a smoothNormalArray, whose elements are those of normalArray averaged - with neighbors within the angular cutoff. - */ - void smoothNormals( - const Array& vertexArray, - const Array& normalArray, - Array& smoothNormalArray) { - - const float cosThresholdAngle = (float)cos(normalSmoothingAngle); - - debugAssert(vertexArray.size() == normalArray.size()); - smoothNormalArray.resize(normalArray.size()); - - // Compute a hash grid so that we can find neighbors quickly. - PointHashGrid grid(vertexWeldRadius); - for (int v = 0; v < normalArray.size(); ++v) { - grid.insert(VN(vertexArray[v], normalArray[v])); - } - - for (int v = 0; v < normalArray.size(); ++v) { - // Compute the sum of all nearby normals within the cutoff angle. - // Search within the vertexWeldRadius, since those are the vertices - // that will collapse to the same point. - PointHashGrid::SphereIterator it = - grid.beginSphereIntersection(Sphere(vertexArray[v], vertexWeldRadius)); - - Vector3 sum; - - const Vector3& original = normalArray[v]; - while (it.hasMore()) { - const Vector3& N = it->normal; - const float cosAngle = N.dot(original); - - if (cosAngle > cosThresholdAngle) { - // This normal is close enough to consider - sum += N; - } - ++it; - } - - const Vector3& average = sum.directionOrZero(); - - const bool indeterminate = average.isZero(); - // Never "smooth" a normal so far that it points backwards - const bool backFacing = original.dot(average) < 0; - - if (indeterminate || backFacing) { - // Revert to the face normal - smoothNormalArray[v] = original; - } else { - // Average available normals - smoothNormalArray[v] = average; - } - } - } - -public: - - - /** - Algorithm: - - 1. Unroll the indexed triangle list into a triangle list, where - there are duplicated vertices. - - 2. Compute face normals for all triangles, and expand those into - the triangle vertices. - - 3. At each vertex, average all normals that are within normalSmoothingAngle. - - 4. Generate output indexArrayArray. While doing so, merge all vertices where - the distance between position, texCoord, and normal is within the thresholds. - */ - void process( - Array& vertexArray, - Array& texCoordArray, - Array& normalArray, - Array*>& indexArrayArray, - float normAngle, - float texRadius, - float normRadius) { - - normalSmoothingAngle = normAngle; - normalWeldRadius2 = square(normRadius); - texCoordWeldRadius2 = square(texRadius); - - const bool hasTexCoords = (texCoordArray.size() > 0); - - if (hasTexCoords) { - debugAssertM(vertexArray.size() == texCoordArray.size(), - "Input arrays are not parallel."); - } - - Array unrolledVertexArray; - Array unrolledFaceNormalArray; - Array unrolledSmoothNormalArray; - Array unrolledTexCoordArray; - - if (! hasTexCoords) { - // Generate all zero texture coordinates - texCoordArray.resize(vertexArray.size()); - } - - // Generate a flat (unrolled) triangle list with texture coordinates. - unroll(indexArrayArray, vertexArray, texCoordArray, - unrolledVertexArray, unrolledTexCoordArray); - - // Put the output back into the input slots. Clear immediately to reduce peak - // memory. - outputVertexArray = &vertexArray; - outputNormalArray = &normalArray; - outputTexCoordArray = &texCoordArray; - outputVertexArray->fastClear(); - outputNormalArray->fastClear(); - outputTexCoordArray->fastClear(); - - // For every three vertices, generate their face normal and store it at - // each vertex. The output array has the same length as the input. - computeFaceNormals(unrolledVertexArray, unrolledFaceNormalArray); - - // Compute smooth normals at vertices. - smoothNormals(unrolledVertexArray, unrolledFaceNormalArray, unrolledSmoothNormalArray); - unrolledFaceNormalArray.clear(); - - // Regenerate the triangle lists - updateTriLists(indexArrayArray, unrolledVertexArray, unrolledSmoothNormalArray, unrolledTexCoordArray); - - if (! hasTexCoords) { - // Throw away the generated texCoords - texCoordArray.resize(0); - } - } - - WeldHelper(float vertRadius) : - weldGrid(vertRadius), - vertexWeldRadius(vertRadius) {} - -}; -} // Internal - -void MeshAlg::weld( - Array& vertexArray, - Array& texCoordArray, - Array& normalArray, - Array*>& indexArrayArray, - float normalSmoothingAngle, - float vertexWeldRadius, - float textureWeldRadius, - float normalWeldRadius) { - - _internal::WeldHelper(vertexWeldRadius).process( - vertexArray, texCoordArray, normalArray, indexArrayArray, - normalSmoothingAngle, textureWeldRadius, normalWeldRadius); -} - -} // G3D diff --git a/externals/g3dlite/G3D.lib/source/MeshBuilder.cpp b/externals/g3dlite/G3D.lib/source/MeshBuilder.cpp deleted file mode 100644 index 43ee6e50ac8..00000000000 --- a/externals/g3dlite/G3D.lib/source/MeshBuilder.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/** - @file MeshBuilder.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2002-02-27 - @edited 2005-02-24 - */ - -#include "G3D/MeshBuilder.h" -#include "G3D/MeshAlg.h" - -namespace G3D { - -void MeshBuilder::setName(const std::string& n) { - name = n; -} - - -void MeshBuilder::commit(std::string& n, Array& indexArray, Array& outvertexArray) { - n = name; - - // Make the data fit in a unit cube - centerTriList(); - - Array toNew, toOld; - - if (close == MeshBuilder::AUTO_WELD) { - Array index; - MeshAlg::createIndexArray(triList.size(), index); - double minEdgeLen, maxEdgeLen, meanEdgeLen, medianEdgeLen; - double minFaceArea, maxFaceArea, meanFaceArea, medianFaceArea; - MeshAlg::computeAreaStatistics(triList, index, - minEdgeLen, meanEdgeLen, medianEdgeLen, maxEdgeLen, - minFaceArea, meanFaceArea, medianFaceArea, maxFaceArea); - close = minEdgeLen * 0.1; - } - - MeshAlg::computeWeld(triList, outvertexArray, toNew, toOld, close); - - // Construct triangles - for (int t = 0; t < triList.size(); t += 3) { - int index[3]; - - for (int i = 0; i < 3; ++i) { - index[i] = toNew[t + i]; - } - - // Throw out zero size triangles - if ((index[0] != index[1]) && - (index[1] != index[2]) && - (index[2] != index[0])) { - indexArray.append(index[0], index[1], index[2]); - } - } -} - - -void MeshBuilder::centerTriList() { - // Compute the range of the vertices - Vector3 vmin, vmax; - - computeBounds(vmin, vmax); - - Vector3 diagonal = vmax - vmin; - double scale = max(max(diagonal.x, diagonal.y), diagonal.z) / 2; - debugAssert(scale > 0); - - Vector3 translation = vmin + diagonal / 2; - - // Center and scale all vertices in the input list - int v; - - //Matrix3 rot90 = Matrix3::fromAxisAngle(Vector3::UNIT_Y, toRadians(180)) * Matrix3::fromAxisAngle(Vector3::UNIT_X, toRadians(90)); - for (v = 0; v < triList.size(); ++v) { - triList[v] = (triList[v] - translation) / scale; - //triList[v] = rot90 * triList[v]; - } -} - - -void MeshBuilder::computeBounds(Vector3& min, Vector3& max) { - min = Vector3::inf(); - max = -min; - - int v; - for (v = 0; v < triList.size(); ++v) { - min = min.min(triList[v]); - max = max.max(triList[v]); - } -} - - -void MeshBuilder::addTriangle(const Vector3& a, const Vector3& b, const Vector3& c) { - triList.append(a, b, c); - - if (_twoSided) { - triList.append(c, b, a); - } -} - - -void MeshBuilder::addQuad(const Vector3& a, const Vector3& b, const Vector3& c, const Vector3& d) { - addTriangle(a, b, c); - addTriangle(a, c, d); -} - - -void MeshBuilder::addTriangle(const Triangle& t) { - addTriangle(t.vertex(0), t.vertex(1), t.vertex(2)); -} - -} // namespace diff --git a/externals/g3dlite/G3D.lib/source/NetAddress.cpp b/externals/g3dlite/G3D.lib/source/NetAddress.cpp deleted file mode 100644 index 64d692d4763..00000000000 --- a/externals/g3dlite/G3D.lib/source/NetAddress.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/** - @file NetMessage.cpp - - @maintainer Morgan McGuire, morgan@cs.brown.edu - @created 2005-02-06 - @edited 2005-02-06 - */ -#include "G3D/platform.h" -#include "G3D/NetAddress.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/Array.h" -#include "G3D/stringutils.h" -#include "G3D/System.h" -#include "G3D/NetworkDevice.h" - -#if defined(G3D_LINUX) || defined(G3D_OSX) - #include - #include - #include - #include - #include - #include - #include - #define _alloca alloca - -# ifndef SOCKADDR_IN -# define SOCKADDR_IN struct sockaddr_in -# endif -# ifndef SOCKET -# define SOCKET int -# endif - -// SOCKADDR_IN is supposed to be defined in NetAddress.h -#ifndef SOCKADDR_IN -# error Network headers included in wrong order -#endif -#endif - - -namespace G3D { - -NetAddress::NetAddress() { - System::memset(&addr, 0, sizeof(addr)); -} - -void NetAddress::init(uint32 host, uint16 port) { - if ((host != 0) || (port != 0)) { - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - if (host == 0) { - host = INADDR_ANY; - } - addr.sin_addr.s_addr = htonl(host); - } else { - System::memset(&addr, 0, sizeof(addr)); - } -} - - -NetAddress::NetAddress( - const std::string& hostname, - uint16 port) { - init(hostname, port); -} - - -void NetAddress::init( - const std::string& hostname, - uint16 port) { - - uint32 addr; - - if (hostname == "") { - addr = INADDR_NONE; - } else { - addr = inet_addr(hostname.c_str()); - } - - // The address wasn't in numeric form, resolve it - if (addr == INADDR_NONE) { - // Get the IP address of the server and store it in host - struct hostent* host = gethostbyname(hostname.c_str()); - - if (host == NULL) { - init(0, 0); - return; - } - - System::memcpy(&addr, host->h_addr_list[0], host->h_length); - } - - if (addr != INADDR_NONE) { - addr = ntohl(addr); - } - init(addr, port); -} - - -NetAddress::NetAddress(uint32 hostip, uint16 port) { - init(hostip, port); -} - - -NetAddress NetAddress::broadcastAddress(uint16 port) { - return NetAddress(NetworkDevice::instance()->broadcastAddressArray()[0], port); -} - - -NetAddress::NetAddress(const std::string& hostnameAndPort) { - - Array part = stringSplit(hostnameAndPort, ':'); - - debugAssert(part.length() == 2); - init(part[0], atoi(part[1].c_str())); -} - - -NetAddress::NetAddress(const SOCKADDR_IN& a) { - addr = a; -} - - -NetAddress::NetAddress(const struct in_addr& addr, uint16 port) { - #ifdef G3D_WIN32 - init(ntohl(addr.S_un.S_addr), port); - #else - init(htonl(addr.s_addr), port); - #endif -} - - -void NetAddress::serialize(class BinaryOutput& b) const { - b.writeUInt32(ip()); - b.writeUInt16(port()); -} - - -void NetAddress::deserialize(class BinaryInput& b) { - uint32 i; - uint16 p; - - i = b.readUInt32(); - p = b.readUInt16(); - - init(i, p); -} - - -bool NetAddress::ok() const { - return addr.sin_family != 0; -} - - -std::string NetAddress::ipString() const { - return format("%s", inet_ntoa(*(in_addr*)&(addr.sin_addr))); -} - - -std::string NetAddress::toString() const { - return ipString() + format(":%d", ntohs(addr.sin_port)); -} - -} diff --git a/externals/g3dlite/G3D.lib/source/NetworkDevice.cpp b/externals/g3dlite/G3D.lib/source/NetworkDevice.cpp deleted file mode 100644 index 246c97d4dbf..00000000000 --- a/externals/g3dlite/G3D.lib/source/NetworkDevice.cpp +++ /dev/null @@ -1,1362 +0,0 @@ -/** - @file NetworkDevice.cpp - - @maintainer Morgan McGuire, morgan@cs.brown.edu - @created 2002-11-22 - @edited 2006-02-24 - */ - -#include -#include -#include "G3D/platform.h" -#include "G3D/TextOutput.h" -#include "G3D/NetworkDevice.h" -#include "G3D/NetAddress.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/Log.h" -#include "G3D/G3DGameUnits.h" -#include "G3D/stringutils.h" -#include "G3D/debug.h" - -#include - -#if defined(G3D_LINUX) || defined(G3D_OSX) || defined(G3D_FREEBSD) -# include -# include -# include -# include -# include -# ifdef __linux__ -# include -# include -# include -# include -// Match Linux to FreeBSD -# define AF_LINK AF_PACKET -# else -# include -# include -# endif - - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #include - - #define _alloca alloca - - /** Define an error code for non-windows platforms. */ - int WSAGetLastError() { - return -1; - } - - #define SOCKET_ERROR -1 - - static std::string socketErrorCode(int code) { - return G3D::format("CODE %d: %s\n", code, strerror(code)); - } - - static std::string socketErrorCode() { - return socketErrorCode(errno); - } - - static const int WSAEWOULDBLOCK = -100; - - typedef int SOCKET; - typedef struct sockaddr_in SOCKADDR_IN; - -#else - - // Windows - static std::string socketErrorCode(int code) { - LPTSTR formatMsg = NULL; - - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - code, - 0, - (LPTSTR)&formatMsg, - 0, - NULL); - - return G3D::format("CODE %d: %s\n", code, formatMsg); - } - - static std::string socketErrorCode() { - return socketErrorCode(GetLastError()); - } - -#endif - - -#ifndef _SOCKLEN_T -# if defined(G3D_WIN32) || defined(G3D_OSX) - typedef int socklen_t; -# endif -#endif - -namespace G3D { - -NetworkDevice* NetworkDevice::s_instance = NULL; - -std::ostream& operator<<(std::ostream& os, const NetAddress& a) { - return os << a.toString(); -} - - -static void logSocketInfo(const SOCKET& sock) { - uint32 val; - socklen_t sz = 4; - int ret; - - ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, (socklen_t*)&sz); - logPrintf("SOL_SOCKET/SO_RCVBUF = %d\n", val); - - ret = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, (socklen_t*)&sz); - logPrintf("SOL_SOCKET/SO_SNDBUF = %d\n", val); - - // Note: timeout = 0 means no timeout - ret = getsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&val, (socklen_t*)&sz); - logPrintf("SOL_SOCKET/SO_RCVTIMEO = %d\n", val); - - ret = getsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&val, (socklen_t*)&sz); - logPrintf("SOL_SOCKET/SO_SNDTIMEO = %d\n", val); -} - - -///////////////////////////////////////////////////////////////////////////// - -/** Invokes select on one socket. Returns SOCKET_ERROR on error, 0 if - there is no read pending, sock if there a read pending. */ -static int selectOneReadSocket(const SOCKET& sock) { - // 0 time timeout is specified to poll and return immediately - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - - // Create a set that contains just this one socket - fd_set socketSet; - FD_ZERO(&socketSet); - FD_SET(sock, &socketSet); - - int ret = select(sock + 1, &socketSet, NULL, NULL, &timeout); - - return ret; -} - - -/** Returns true if the socket has a read pending */ -static bool readWaiting(const SOCKET& sock) { - int ret = selectOneReadSocket(sock); - - switch (ret) { - case SOCKET_ERROR: - logPrintf("ERROR: selectOneReadSocket returned " - "SOCKET_ERROR in readWaiting(). %s", socketErrorCode().c_str()); - // Return true so that we'll force an error on read and close - // the socket. - return true; - - case 0: - return false; - - default: - return true; - } -} - - -/** Invokes select on one socket. */ -static int selectOneWriteSocket(const SOCKET& sock) { - // 0 time timeout is specified to poll and return immediately - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - - // Create a set that contains just this one socket - fd_set socketSet; - FD_ZERO(&socketSet); - FD_SET(sock, &socketSet); - - return select(sock + 1, NULL, &socketSet, NULL, &timeout); -} - -/////////////////////////////////////////////////////////////////////////////// - -NetworkDevice* NetworkDevice::instance() { - if (s_instance == NULL) { - s_instance = new NetworkDevice(); - if (! s_instance->init()) { - delete s_instance; - s_instance = NULL; - } - } - return s_instance; -} - - -void NetworkDevice::cleanup() { - if (s_instance) { - s_instance->_cleanup(); - delete s_instance; - s_instance = NULL; - } -} - - -NetworkDevice::NetworkDevice() { - initialized = false; -} - - -NetworkDevice::~NetworkDevice() { -} - - -std::string NetworkDevice::localHostName() const { - char ac[128]; - if (gethostname(ac, sizeof(ac)) == -1) { - Log::common()->printf("Error while getting local host name\n"); - return "localhost"; - } - return gethostbyname(ac)->h_name; -} - -#ifndef G3D_WIN32 -const char* errnoToString() { - switch (errno) { - case EBADF: - return "file descriptor is invalid."; - - case EINVAL: - return "Request or argp is not valid."; - - case ENOTTY: - return - "file descriptor is not associated with a character special device OR " - "The specified request does not apply to the " - "kind of object that the descriptor fildes references."; - - case EADDRNOTAVAIL: - return "Address not available."; - - default: - { - static char buffer[20]; - sprintf(buffer, "Error %d", errno); - return buffer; - } - } -} -#endif - - -NetworkDevice::EthernetAdapter::EthernetAdapter() { - name = ""; - ip = 0; - hostname = ""; - subnet = 0; - broadcast = 0; - for (int i = 0; i < 6; ++i) { - mac[i] = 0; - } -} - -void NetworkDevice::EthernetAdapter::describe(TextOutput& t) const { - t.writeSymbol("{"); - t.pushIndent(); - t.writeNewline(); - - t.writeSymbols("hostname", "="); - t.writeString(hostname); - t.writeNewline(); - - t.writeSymbols("name", "="); - t.writeString(name); - t.writeNewline(); - - t.writeSymbols("ip", "="); - t.writeSymbol(formatIP(ip)); - t.writeNewline(); - - t.writeSymbols("subnet", "="); - t.writeSymbol(formatIP(subnet)); - t.writeNewline(); - - t.writeSymbols("broadcast", "="); - t.writeSymbol(formatIP(broadcast)); - t.writeNewline(); - - t.writeSymbols("mac", "="); - t.writeSymbol(formatMAC(mac)); - t.writeNewline(); - - t.popIndent(); - t.writeSymbol("}"); - t.writeNewline(); -} - - -void NetworkDevice::addAdapter(const EthernetAdapter& a) { - m_adapterArray.append(a); - if (a.broadcast != 0) { - int i = m_broadcastAddresses.findIndex(a.broadcast); - if (i == -1) { - m_broadcastAddresses.append(a.broadcast); - } - } -} - - -std::string NetworkDevice::formatIP(uint32 addr) { - return format("%3d.%3d.%3d.%3d", (addr >> 24) & 0xFF, (addr >> 16) & 0xFF, - (addr >> 8) & 0xFF, addr & 0xFF); -} - - -std::string NetworkDevice::formatMAC(const uint8 MAC[6]) { - return format("%02x:%02x:%02x:%02x:%02x:%02x", MAC[0], MAC[1], MAC[2], MAC[3], MAC[4], MAC[5]); -} - - -#ifdef G3D_WIN32 - -bool NetworkDevice::init() { - debugAssert(! initialized); - - logPrintf("Network Startup"); - logPrintf("Starting WinSock networking.\n"); - WSADATA wsda; - WSAStartup(MAKEWORD(G3D_WINSOCK_MAJOR_VERSION, G3D_WINSOCK_MINOR_VERSION), &wsda); - - std::string hostname = "localhost"; - { - char ac[128]; - if (gethostname(ac, sizeof(ac)) == -1) { - logPrintf("Warning: Error while getting local host name\n"); - } else { - hostname = gethostbyname(ac)->h_name; - } - } - - EthernetAdapter a; - a.hostname = hostname; - a.name = ""; - a.ip = NetAddress(hostname, 0).ip(); - - // TODO: Find subnet on Win32 - a.subnet = 0x0000FFFF; - - // TODO: Find broadcast on Win32 - a.broadcast = 0xFFFFFFFF; - - // TODO: find MAC on Win32 - - addAdapter(a); - - std::string machine = localHostName(); - std::string addr = NetAddress(machine, 0).ipString(); - logPrintf( - "Network:\n" - " Status: %s\n" - " Loaded winsock specification version %d (%d is " - "the highest available)\n" - " %d sockets available\n" - " Largest UDP datagram packet size is %d bytes\n\n", - wsda.szDescription, - wsda.szSystemStatus, - wsda.wVersion, - wsda.wHighVersion, - wsda.iMaxSockets, - wsda.iMaxUdpDg); - - // TODO: WSAIoctl for subnet and broadcast addresses - // http://msdn.microsoft.com/en-us/library/ms741621(VS.85).aspx - // - // TODO: SIO_GET_INTERFACE_LIST - - initialized = true; - - return true; -} -#endif - - -#if defined(G3D_LINUX) || defined(G3D_OSX) || defined(G3D_FREEBSD) - -const sockaddr_in* castToIP4(const sockaddr* addr) { - if (addr == NULL) { - return NULL; - } else if (addr->sa_family == AF_INET) { - // An IPv4 address - return reinterpret_cast(addr); - } else { - // Not an IPv4 address - return NULL; - } -} - -uint32 getIP(const sockaddr_in* addr) { - if (addr != NULL) { - return ntohl(addr->sin_addr.s_addr); - } else { - return 0; - } -} - - -bool NetworkDevice::init() { - debugAssert(! initialized); - - // Used for combining the MAC and ip information - typedef Table AdapterTable; - - AdapterTable table; - - // Head of a linked list of network interfaces on this machine - ifaddrs* ifap = NULL; - - int r = getifaddrs(&ifap); - - if (r != 0) { - logPrintf("ERROR: getifaddrs returned %d\n", r); - return false; - } - - ifaddrs* current = ifap; - - if (current == NULL) { - logPrintf("WARNING: No network interfaces found\n"); - EthernetAdapter a; - a.name = "fallback"; - a.hostname = "localhost"; - a.ip = (127 << 24) | 1; - a.broadcast = 0xFFFFFFFF; - a.subnet = 0x000000FF; - addAdapter(a); - - } else { - - while (current != NULL) { - - bool up = (current->ifa_flags & IFF_UP); - bool loopback = (current->ifa_flags & IFF_LOOPBACK); - - if (! up || loopback) { - // Skip this adapter; it is offline or is a loopback - current = current->ifa_next; - continue; - } - - if (! table.containsKey(current->ifa_name)) { - EthernetAdapter a; - a.name = current->ifa_name; - table.set(a.name, a); - } - - // This adapter must exist because it was created above - EthernetAdapter& adapter = table[current->ifa_name]; - - const sockaddr_in* interfaceAddress = castToIP4(current->ifa_addr); - const sockaddr_in* broadcastAddress = castToIP4(current->ifa_dstaddr); - const sockaddr_in* subnetMask = castToIP4(current->ifa_netmask); - - uint32 ip = getIP(interfaceAddress); - uint32 ba = getIP(broadcastAddress); - uint32 sn = getIP(subnetMask); - - if (ip != 0) { - adapter.ip = ip; - } - - if (ba != 0) { - adapter.broadcast = ba; - } - - if (sn != 0) { - adapter.subnet = sn; - } - - uint8_t* MAC = NULL; - // Extract MAC address - if ((current->ifa_addr != NULL) && (current->ifa_addr->sa_family == AF_LINK)) { -# ifdef __linux__ - { - // Linux - struct ifreq ifr; - - int fd = socket(AF_INET, SOCK_DGRAM, 0); - - ifr.ifr_addr.sa_family = AF_INET; - strcpy(ifr.ifr_name, current->ifa_name); - ioctl(fd, SIOCGIFHWADDR, &ifr); - close(fd); - - MAC = reinterpret_cast(ifr.ifr_hwaddr.sa_data); - } -# else - { - // The MAC address and the interfaceAddress come in as - // different interfaces with the same name. - - // Posix/FreeBSD/Mac OS - sockaddr_dl* sdl = (struct sockaddr_dl *)current->ifa_addr; - MAC = reinterpret_cast(LLADDR(sdl)); - } -# endif - - // See if there was a MAC address - if (MAC != NULL) { - bool anyNonZero = false; - for (int i = 0; i < 6; ++i) { - anyNonZero = anyNonZero || (MAC[i] != 0); - } - if (anyNonZero) { - System::memcpy(adapter.mac, MAC, 6); - } - } - } - - current = current->ifa_next; - } - - freeifaddrs(ifap); - ifap = NULL; - } - - // Extract all interesting adapters from the table - for (AdapterTable::Iterator it = table.begin(); it.hasMore(); ++it) { - const EthernetAdapter& adapter = it->value; - - // Only add adapters that have IP addresses - if (adapter.ip != 0) { - addAdapter(adapter); - } else { - logPrintf("NetworkDevice: Ignored adapter %s because ip = 0\n", adapter.name.c_str()); - } - } - - initialized = true; - - return true; -} - -#endif - - -void NetworkDevice::_cleanup() { - debugAssert(initialized); - - logPrintf("Network Cleanup"); -# ifdef G3D_WIN32 - WSACleanup(); -# endif - logPrintf("Network cleaned up."); -} - -bool NetworkDevice::bind(SOCKET sock, const NetAddress& addr) const { - Log::common()->printf("Binding socket %d on port %d ", - sock, htons(addr.addr.sin_port)); - if (::bind(sock, (struct sockaddr*)&(addr.addr), sizeof(addr.addr)) == - SOCKET_ERROR) { - - Log::common()->println("FAIL"); - Log::common()->println(socketErrorCode()); - closesocket(sock); - return false; - } - - Log::common()->println("Ok"); - return true; -} - - -void NetworkDevice::closesocket(SOCKET& sock) const { - if (sock != 0) { - #ifdef G3D_WIN32 - ::closesocket(sock); - #else - close(sock); - #endif - - Log::common()->printf("Closed socket %d\n", sock); - sock = 0; - } -} - - -void NetworkDevice::localHostAddresses(Array& array) const { - array.resize(0); - - char ac[128]; - - if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) { - Log::common()->printf("Error while getting local host name\n"); - return; - } - - struct hostent* phe = gethostbyname(ac); - if (phe == 0) { - Log::common()->printf("Error while getting local host address\n"); - return; - } - - for (int i = 0; (phe->h_addr_list[i] != 0); ++i) { - struct in_addr addr; - memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr)); - array.append(NetAddress(addr)); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -Conduit::Conduit() : binaryOutput("", G3D_LITTLE_ENDIAN) { - sock = 0; - mSent = 0; - mReceived = 0; - bSent = 0; - bReceived = 0; -} - - -Conduit::~Conduit() { - NetworkDevice::instance()->closesocket(sock); -} - - -uint64 Conduit::bytesSent() const { - return bSent; -} - - -uint64 Conduit::bytesReceived() const { - return bReceived; -} - - -uint64 Conduit::messagesSent() const { - return mSent; -} - - -uint64 Conduit::messagesReceived() const { - return mReceived; -} - - -bool Conduit::ok() const { - return (sock != 0) && (sock != SOCKET_ERROR); -} - - -bool Conduit::messageWaiting() { - return readWaiting(sock); -} - - -/** - Increases the send and receive sizes of a socket to 2 MB from 8k - */ -static void increaseBufferSize(SOCKET sock) { - - // Increase the buffer size; the default (8192) is too easy to - // overflow when the network latency is high. - { - uint32 val = 1024 * 1024 * 2; - if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, - (char*)&val, sizeof(val)) == SOCKET_ERROR) { - Log::common()->printf("WARNING: Increasing socket " - "receive buffer to %d failed.\n", val); - Log::common()->println(socketErrorCode()); - } - - if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, - (char*)&val, sizeof(val)) == SOCKET_ERROR) { - Log::common()->printf("WARNING: Increasing socket " - "send buffer to %d failed.\n", val); - Log::common()->println(socketErrorCode()); - } - } -} - -////////////////////////////////////////////////////////////////////////////// - -ReliableConduitRef ReliableConduit::create(const NetAddress& address) { - return new ReliableConduit(address); -} - - -ReliableConduit::ReliableConduit( - const NetAddress& _addr) : state(NO_MESSAGE), receiveBuffer(NULL), - receiveBufferTotalSize(0), receiveBufferUsedSize(0) { - - NetworkDevice* nd = NetworkDevice::instance(); - - messageType = 0; - - addr = _addr; - Log::common()->print("Creating a TCP socket "); - sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); - - if (sock == SOCKET_ERROR) { - Log::common()->println("FAIL"); - Log::common()->println(socketErrorCode()); - nd->closesocket(sock); - return; - } - - Log::common()->println("Ok"); - - // Setup socket options (both constructors should set the same options) - - // Disable Nagle's algorithm (we send lots of small packets) - const int T = true; - if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, - (const char*)&T, sizeof(T)) == SOCKET_ERROR) { - - Log::common()->println("WARNING: Disabling Nagel's " - "algorithm failed."); - Log::common()->println(socketErrorCode()); - } else { - Log::common()->println("Disabled Nagel's algorithm."); - } - - // Set the NO LINGER option so the socket doesn't hang around if - // there is unsent data in the queue when it closes. - struct linger ling; - ling.l_onoff = 0; - ling.l_linger = 0; - if (setsockopt(sock, SOL_SOCKET, SO_LINGER, - (const char*)&ling, sizeof(ling)) == SOCKET_ERROR) { - - Log::common()->println("WARNING: Setting socket no linger failed."); - Log::common()->println(socketErrorCode()); - } else { - Log::common()->println("Set socket option no_linger."); - } - - // Set reuse address so that a new server can start up soon after - // an old one has closed. - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - (const char*)&T, sizeof(T)) == SOCKET_ERROR) { - - Log::common()->println("WARNING: Setting socket reuseaddr failed."); - Log::common()->println(socketErrorCode()); - } else { - Log::common()->println("Set socket option reuseaddr."); - } - - // Ideally, we'd like to specify IPTOS_LOWDELAY as well. - - logSocketInfo(sock); - - increaseBufferSize(sock); - - Log::common()->printf("Created TCP socket %d\n", sock); - - std::string x = addr.toString(); - Log::common()->printf("Connecting to %s on TCP socket %d ", x.c_str(), sock); - - int ret = connect(sock, (struct sockaddr *) &(addr.addr), sizeof(addr.addr)); - - if (ret == WSAEWOULDBLOCK) { - RealTime t = System::time() + 5.0; - // Non-blocking; we must wait until select returns non-zero - while ((selectOneWriteSocket(sock) == 0) && (System::time() < t)) { - System::sleep(0.02); - } - - // TODO: check for failure on the select call - - } else if (ret != 0) { - sock = (SOCKET)SOCKET_ERROR; - Log::common()->println("FAIL"); - Log::common()->println(socketErrorCode()); - return; - } - - Log::common()->println("Ok"); -} - - -ReliableConduit::ReliableConduit( - const SOCKET& _sock, - const NetAddress& _addr) : - state(NO_MESSAGE), - receiveBuffer(NULL), - receiveBufferTotalSize(0), - receiveBufferUsedSize(0) { - sock = _sock; - addr = _addr; - - messageType = 0; - - // Setup socket options (both constructors should set the same options) - - // Disable Nagle's algorithm (we send lots of small packets) - const int T = true; - if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, - (const char*)&T, sizeof(T)) == SOCKET_ERROR) { - - Log::common()->println("WARNING: Disabling Nagel's algorithm failed."); - Log::common()->println(socketErrorCode()); - } else { - Log::common()->println("Disabled Nagel's algorithm."); - } - - // Set the NO LINGER option so the socket doesn't hang around if - // there is unsent data in the queue when it closes. - struct linger ling; - ling.l_onoff = 0; - ling.l_linger = 0; - if (setsockopt(sock, SOL_SOCKET, SO_LINGER, - (const char*)&ling, sizeof(ling)) == SOCKET_ERROR) { - - Log::common()->println("WARNING: Setting socket no linger failed."); - Log::common()->println(socketErrorCode()); - } else { - Log::common()->println("Set socket option no_linger."); - } - - // Set reuse address so that a new server can start up soon after - // an old one has closed. - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - (const char*)&T, sizeof(T)) == SOCKET_ERROR) { - - Log::common()->println("WARNING: Setting socket reuseaddr failed."); - Log::common()->println(socketErrorCode()); - } else { - Log::common()->println("Set socket option reuseaddr."); - } - - // Ideally, we'd like to specify IPTOS_LOWDELAY as well. - - logSocketInfo(sock); -} - - -ReliableConduit::~ReliableConduit() { - free(receiveBuffer); - receiveBuffer = NULL; - receiveBufferTotalSize = 0; - receiveBufferUsedSize = 0; -} - - -bool ReliableConduit::messageWaiting() { - switch (state) { - case HOLDING: - // We've already read the message and are waiting - // for a receive call. - return true; - - case RECEIVING: - - if (! ok()) { - return false; - } - // We're currently receiving the message. Read a little more. - receiveIntoBuffer(); - - if (messageSize == receiveBufferUsedSize) { - // We've read the whole mesage. Switch to holding state - // and return true. - state = HOLDING; - return true; - } else { - // There are more bytes left to read. We'll read them on - // the next call. Because the *entire* message is not ready, - // return false. - return false; - } - break; - - case NO_MESSAGE: - if (Conduit::messageWaiting()) { - // Message incoming. Read the header. - - state = RECEIVING; - receiveHeader(); - - // Loop back around now that we're in the receive state; we - // may be able to read the whole message before returning - // to the caller. - return messageWaiting(); - } else { - // No message incoming. - return false; - } - } - - debugAssertM(false, "Should not reach this point"); - return false; -} - - -uint32 ReliableConduit::waitingMessageType() { - // The messageWaiting call is what actually receives the message. - if (messageWaiting()) { - return messageType; - } else { - return 0; - } -} - - -void ReliableConduit::sendBuffer(const BinaryOutput& b) { - NetworkDevice* nd = NetworkDevice::instance(); - int ret = ::send(sock, (const char*)b.getCArray(), b.size(), 0); - - if (ret == SOCKET_ERROR) { - Log::common()->println("Error occured while sending message."); - Log::common()->println(socketErrorCode()); - nd->closesocket(sock); - return; - } - - ++mSent; - bSent += b.size(); - - // Verify the packet was actually sent - // Conversion to unsigned is safe because -1 is caught earlier - debugAssert(ret == b.size()); -} - - -/** Null serializer. Used by reliable conduit::send(type) */ -class Dummy { -public: - void serialize(BinaryOutput& b) const { (void)b; } -}; - - -void ReliableConduit::send(uint32 type) { - static Dummy dummy; - send(type, dummy); -} - - - -NetAddress ReliableConduit::address() const { - return addr; -} - - -void ReliableConduit::receiveHeader() { - NetworkDevice* nd = NetworkDevice::instance(); - debugAssert(state == RECEIVING); - - // Read the type - uint32 tmp; - int ret = recv(sock, (char*)&tmp, sizeof(tmp), 0); - - // The type is the first four bytes. It is little endian. - if (System::machineEndian() == G3D_LITTLE_ENDIAN) { - messageType = tmp; - } else { - // Swap the byte order - for (int i = 0; i < 4; ++i) { - ((char*)&messageType)[i] = ((char*)&tmp)[3 - i]; - } - } - - if ((ret == SOCKET_ERROR) || (ret != sizeof(messageType))) { - Log::common()->printf("Call to recv failed. ret = %d," - " sizeof(messageType) = %d\n", - (int)ret, (int)sizeof(messageType)); - Log::common()->println(socketErrorCode()); - nd->closesocket(sock); - messageType = 0; - return; - } - - // Read the size - ret = recv(sock, (char*)&messageSize, sizeof(messageSize), 0); - - if ((ret == SOCKET_ERROR) || (ret != sizeof(messageSize))) { - Log::common()->printf("Call to recv failed. ret = %d," - " sizeof(len) = %d\n", (int)ret, - (int)sizeof(messageSize)); - Log::common()->println(socketErrorCode()); - nd->closesocket(sock); - messageType = 0; - return; - } - - messageSize = ntohl(messageSize); - debugAssert(messageSize < 6e7); - - debugAssert(receiveBufferUsedSize == 0); - - // Extend the size of the buffer. - if (messageSize > receiveBufferTotalSize) { - receiveBuffer = realloc(receiveBuffer, messageSize); - receiveBufferTotalSize = messageSize; - } - - if (receiveBuffer == NULL) { - Log::common()->println("Could not allocate a memory buffer " - "during receivePacket."); - nd->closesocket(sock); - } - - bReceived += 4; -} - - -void ReliableConduit::receiveIntoBuffer() { - NetworkDevice* nd = NetworkDevice::instance(); - - debugAssert(state == RECEIVING); - debugAssert(messageType != 0); - debugAssertM(receiveBufferUsedSize < messageSize, "Message already received."); - debugAssertM(messageSize >= receiveBufferUsedSize, "Message size overflow."); - - // Read the data itself - int ret = 0; - uint32 left = messageSize - receiveBufferUsedSize; - int count = 0; - while ((ret != SOCKET_ERROR) && (left > 0) && (count < 100)) { - - ret = recv(sock, ((char*)receiveBuffer) + receiveBufferUsedSize, left, 0); - - if (ret > 0) { - left -= ret; - receiveBufferUsedSize += ret; - bReceived += ret; - - if (left > 0) { - // There's still more. Give the machine a chance to read - // more data, but don't wait forever. - - ++count; - System::sleep(0.001); - } - } else { - // Something went wrong; our blocking read returned nothing. - break; - } - } - - if ((ret == 0) || (ret == SOCKET_ERROR)) { - - if (ret == SOCKET_ERROR) { - Log::common()->printf("Call to recv failed. ret = %d," - " sizeof(messageSize) = %d\n", ret, messageSize); - Log::common()->println(socketErrorCode()); - } else { - Log::common()->printf("recv returned 0\n"); - } - nd->closesocket(sock); - return; - } - - ++mReceived; -} - - -/////////////////////////////////////////////////////////////////////////////// -LightweightConduitRef LightweightConduit::create( - uint16 receivePort, - bool enableReceive, - bool enableBroadcast) { - - return new LightweightConduit(receivePort, enableReceive, enableBroadcast); -} - -LightweightConduit::LightweightConduit( - uint16 port, - bool enableReceive, - bool enableBroadcast) { - NetworkDevice* nd = NetworkDevice::instance(); - - Log::common()->print("Creating a UDP socket "); - sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - - if (sock == SOCKET_ERROR) { - sock = 0; - Log::common()->println("FAIL"); - Log::common()->println(socketErrorCode()); - return; - } - Log::common()->println("Ok"); - - if (enableReceive) { - debugAssert(port != 0); - if (! nd->bind(sock, NetAddress(0, port))) { - nd->closesocket(sock); - sock = (SOCKET)SOCKET_ERROR; - } - } - - // Figuring out the MTU seems very complicated, so we just set it to 1000, - // which is likely to be safe. See IP_MTU for more information. - MTU = 1000; - - increaseBufferSize(sock); - - if (enableBroadcast) { - int TR = true; - if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, - (const char*)&TR, sizeof(TR)) != 0) { - Log::common()->println("Call to setsockopt failed"); - Log::common()->println(socketErrorCode()); - nd->closesocket(sock); - sock = 0; - return; - } - } - - Log::common()->printf("Done creating UDP socket %d\n", sock); - - alreadyReadMessage = false; -} - - -LightweightConduit::~LightweightConduit() { -} - - -bool LightweightConduit::receive(NetAddress& sender) { - // This both checks to ensure that a message was waiting and - // actively consumes the message from the network stream if - // it has not been read yet. - uint32 t = waitingMessageType(); - if (t == 0) { - return false; - } - - sender = messageSender; - alreadyReadMessage = false; - - if (messageBuffer.size() < 4) { - // Something went wrong - return false; - } - - return true; -} - - -void LightweightConduit::sendBuffer(const NetAddress& a, BinaryOutput& b) { - NetworkDevice* nd = NetworkDevice::instance(); - if (sendto(sock, (const char*)b.getCArray(), b.size(), 0, - (struct sockaddr *) &(a.addr), sizeof(a.addr)) == SOCKET_ERROR) { - Log::common()->printf("Error occured while sending packet " - "to %s\n", inet_ntoa(a.addr.sin_addr)); - Log::common()->println(socketErrorCode()); - nd->closesocket(sock); - } else { - ++mSent; - bSent += b.size(); - } -} - - -bool LightweightConduit::messageWaiting() { - // We may have already pulled the message off the network stream - return alreadyReadMessage || Conduit::messageWaiting(); -} - - -uint32 LightweightConduit::waitingMessageType() { - NetworkDevice* nd = NetworkDevice::instance(); - if (! messageWaiting()) { - return 0; - } - - if (! alreadyReadMessage) { - messageBuffer.resize(8192); - - SOCKADDR_IN remote_addr; - int iRemoteAddrLen = sizeof(sockaddr); - - int ret = recvfrom(sock, (char*)messageBuffer.getCArray(), - messageBuffer.size(), 0, (struct sockaddr *) &remote_addr, - (socklen_t*)&iRemoteAddrLen); - - if (ret == SOCKET_ERROR) { - Log::common()->println("Error: recvfrom failed in " - "LightweightConduit::waitingMessageType()."); - Log::common()->println(socketErrorCode()); - nd->closesocket(sock); - messageBuffer.resize(0); - messageSender = NetAddress(); - messageType = 0; - return 0; - } - - messageSender = NetAddress(remote_addr); - - ++mReceived; - bReceived += ret; - - messageBuffer.resize(ret, DONT_SHRINK_UNDERLYING_ARRAY); - - // The type is the first four bytes. It is little endian. - if (System::machineEndian() == G3D_LITTLE_ENDIAN) { - messageType = *((uint32*)messageBuffer.getCArray()); - } else { - // Swap the byte order - for (int i = 0; i < 4; ++i) { - ((char*)&messageType)[i] = messageBuffer[3 - i]; - } - } - - alreadyReadMessage = true; - } - - return messageType; -} - - -/////////////////////////////////////////////////////////////////////////////// - -NetListenerRef NetListener::create(const uint16 port) { - return new NetListener(port); -} - - -NetListener::NetListener(uint16 port) { - NetworkDevice* nd = NetworkDevice::instance(); - - // Start the listener socket - Log::common()->print("Creating a listener "); - sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); - - if (sock == SOCKET_ERROR) { - Log::common()->printf("FAIL"); - Log::common()->println(socketErrorCode()); - return; - } - Log::common()->println("Ok"); - - const int T = true; - - // Set reuse address so that a new server can start up soon after - // an old one has closed. - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - (const char*)&T, sizeof(T)) == SOCKET_ERROR) { - - Log::common()->println("WARNING: Setting socket reuseaddr failed."); - Log::common()->println(socketErrorCode()); - } else { - Log::common()->println("Set socket option reuseaddr."); - } - - - if (! nd->bind(sock, NetAddress(0, port))) { - Log::common()->printf("Unable to bind!\n"); - nd->closesocket(sock); - sock = (SOCKET)SOCKET_ERROR; - return; - } - - Log::common()->printf("Listening on port %5d ", port); - - // listen is supposed to return 0 when there is no error. - // The 2nd argument is the number of connections to allow pending - // at any time. - int L = listen(sock, 100); - if (L == SOCKET_ERROR) { - Log::common()->println("FAIL"); - Log::common()->println(socketErrorCode()); - nd->closesocket(sock); - sock = (SOCKET)SOCKET_ERROR; - return; - } - Log::common()->println("Ok"); - Log::common()->printf("Now listening on socket %d.\n\n", sock); -} - - -NetListener::~NetListener() { - NetworkDevice* nd = NetworkDevice::instance(); - nd->closesocket(sock); -} - - -ReliableConduitRef NetListener::waitForConnection() { - NetworkDevice* nd = NetworkDevice::instance(); - // The address of the connecting host - SOCKADDR_IN remote_addr; - int iAddrLen = sizeof(remote_addr); - - Log::common()->println("Blocking in NetListener::waitForConnection()."); - - SOCKET sClient = accept(sock, (struct sockaddr*) &remote_addr, - (socklen_t*)&iAddrLen); - - if (sClient == SOCKET_ERROR) { - Log::common()->println("Error in NetListener::acceptConnection."); - Log::common()->println(socketErrorCode()); - nd->closesocket(sock); - return NULL; - } - - Log::common()->printf("%s connected, transferred to socket %d.\n", - inet_ntoa(remote_addr.sin_addr), sClient); - - #ifndef G3D_WIN32 - return new ReliableConduit(sClient, - NetAddress(htonl(remote_addr.sin_addr.s_addr), - ntohs(remote_addr.sin_port))); - #else - return new ReliableConduit(sClient, - NetAddress(ntohl(remote_addr.sin_addr.S_un.S_addr), - ntohs(remote_addr.sin_port))); - #endif -} - - -bool NetListener::ok() const { - return (sock != 0) && (sock != SOCKET_ERROR); -} - - -bool NetListener::clientWaiting() const { - return readWaiting(sock); -} - -//////////////////////////////////////////////////////////////////////////////////////////////// - -void NetworkDevice::describeSystem( - TextOutput& t) { - - t.writeSymbols("Network", "{"); - t.writeNewline(); - t.pushIndent(); - - for (int i = 0; i < m_adapterArray.size(); ++i) { - m_adapterArray[i].describe(t); - } - - - t.popIndent(); - t.writeSymbols("}"); - t.writeNewline(); - t.writeNewline(); -} - - -void NetworkDevice::describeSystem( - std::string& s) { - - TextOutput t; - describeSystem(t); - t.commitString(s); -} - -} // namespace diff --git a/externals/g3dlite/G3D.lib/source/PhysicsFrame.cpp b/externals/g3dlite/G3D.lib/source/PhysicsFrame.cpp deleted file mode 100644 index 034e585d01f..00000000000 --- a/externals/g3dlite/G3D.lib/source/PhysicsFrame.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/** - @file PhysicsFrame.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2002-07-09 - @edited 2006-01-25 -*/ - -#include "G3D/platform.h" -#include "G3D/PhysicsFrame.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - -namespace G3D { - -PhysicsFrame::PhysicsFrame() { - translation = Vector3::zero(); - rotation = Quat(); -} - - -PhysicsFrame::PhysicsFrame( - const CoordinateFrame& coordinateFrame) { - - translation = coordinateFrame.translation; - rotation = Quat(coordinateFrame.rotation); -} - - -PhysicsFrame PhysicsFrame::operator*(const PhysicsFrame& other) const { - PhysicsFrame result; - - result.rotation = rotation * other.rotation; - result.translation = translation + rotation.toRotationMatrix() * other.translation; - - return result; -} - - -CoordinateFrame PhysicsFrame::toCoordinateFrame() const { - CoordinateFrame f; - - f.translation = translation; - f.rotation = rotation.toRotationMatrix(); - - return f; -} - - -PhysicsFrame PhysicsFrame::lerp( - const PhysicsFrame& other, - float alpha) const { - - PhysicsFrame result; - - result.translation = translation.lerp(other.translation, alpha); - result.rotation = rotation.slerp(other.rotation, alpha); - - return result; -} - - -void PhysicsFrame::deserialize(class BinaryInput& b) { - translation.deserialize(b); - rotation.deserialize(b); -} - - -void PhysicsFrame::serialize(class BinaryOutput& b) const { - translation.serialize(b); - rotation.serialize(b); -} - - -}; // namespace - diff --git a/externals/g3dlite/G3D.lib/source/Plane.cpp b/externals/g3dlite/G3D.lib/source/Plane.cpp deleted file mode 100644 index bb8ed5c6033..00000000000 --- a/externals/g3dlite/G3D.lib/source/Plane.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/** - @file Plane.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2003-02-06 - @edited 2006-01-29 - */ - -#include "G3D/platform.h" -#include "G3D/Plane.h" -#include "G3D/BinaryOutput.h" -#include "G3D/BinaryInput.h" -#include "G3D/stringutils.h" - -namespace G3D { - -Plane::Plane(class BinaryInput& b) { - deserialize(b); -} - - -void Plane::serialize(class BinaryOutput& b) const { - _normal.serialize(b); - b.writeFloat64(_distance); -} - - -void Plane::deserialize(class BinaryInput& b) { - _normal.deserialize(b); - _distance = (float)b.readFloat64(); -} - - -Plane::Plane( - Vector4 point0, - Vector4 point1, - Vector4 point2) { - - debugAssertM( - point0.w != 0 || - point1.w != 0 || - point2.w != 0, - "At least one point must be finite."); - - // Rotate the points around so that the finite points come first. - - while ((point0.w == 0) && - ((point1.w == 0) || (point2.w != 0))) { - Vector4 temp = point0; - point0 = point1; - point1 = point2; - point2 = temp; - } - - Vector3 dir1; - Vector3 dir2; - - if (point1.w == 0) { - // 1 finite, 2 infinite points; the plane must contain - // the direction of the two direcitons - dir1 = point1.xyz(); - dir2 = point2.xyz(); - } else if (point2.w != 0) { - // 3 finite points, the plane must contain the directions - // betwseen the points. - dir1 = point1.xyz() - point0.xyz(); - dir2 = point2.xyz() - point0.xyz(); - } else { - // 2 finite, 1 infinite point; the plane must contain - // the direction between the first two points and the - // direction of the third point. - dir1 = point1.xyz() - point0.xyz(); - dir2 = point2.xyz(); - } - - _normal = dir1.cross(dir2).direction(); - _distance = _normal.dot(point0.xyz()); -} - - -Plane::Plane( - const Vector3& point0, - const Vector3& point1, - const Vector3& point2) { - - _normal = (point1 - point0).cross(point2 - point0).direction(); - _distance = _normal.dot(point0); -} - - -Plane::Plane( - const Vector3& __normal, - const Vector3& point) { - - _normal = __normal.direction(); - _distance = _normal.dot(point); -} - - -Plane Plane::fromEquation(float a, float b, float c, float d) { - Vector3 n(a, b, c); - float magnitude = n.magnitude(); - d /= magnitude; - n /= magnitude; - return Plane(n, -d); -} - - -void Plane::flip() { - _normal = -_normal; - _distance = -_distance; -} - - -void Plane::getEquation(Vector3& n, float& d) const { - double _d; - getEquation(n, _d); - d = (float)_d; -} - -void Plane::getEquation(Vector3& n, double& d) const { - n = _normal; - d = -_distance; -} - - -void Plane::getEquation(float& a, float& b, float& c, float& d) const { - double _a, _b, _c, _d; - getEquation(_a, _b, _c, _d); - a = (float)_a; - b = (float)_b; - c = (float)_c; - d = (float)_d; -} - -void Plane::getEquation(double& a, double& b, double& c, double& d) const { - a = _normal.x; - b = _normal.y; - c = _normal.z; - d = -_distance; -} - - -std::string Plane::toString() const { - return format("Plane(%g, %g, %g, %g)", _normal.x, _normal.y, _normal.z, _distance); -} - -} diff --git a/externals/g3dlite/G3D.lib/source/Quat.cpp b/externals/g3dlite/G3D.lib/source/Quat.cpp deleted file mode 100644 index 225c5b51acc..00000000000 --- a/externals/g3dlite/G3D.lib/source/Quat.cpp +++ /dev/null @@ -1,583 +0,0 @@ -/** - @file Quat.cpp - - Quaternion implementation based on Watt & Watt page 363 - - @author Morgan McGuire, graphics3d.com - - @created 2002-01-23 - @edited 2006-01-31 - */ - -#include "G3D/Quat.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - -namespace G3D { - -Quat Quat::fromAxisAngleRotation( - const Vector3& axis, - float angle) { - - Quat q; - - q.w = cos(angle / 2.0f); - q.imag() = axis.direction() * sin(angle / 2.0f); - - return q; -} - - -Quat::Quat( - const Matrix3& rot) { - - static const int plus1mod3[] = {1, 2, 0}; - - // Find the index of the largest diagonal component - // These ? operations hopefully compile to conditional - // move instructions instead of branches. - int i = (rot[1][1] > rot[0][0]) ? 1 : 0; - i = (rot[2][2] > rot[i][i]) ? 2 : i; - - // Find the indices of the other elements - int j = plus1mod3[i]; - int k = plus1mod3[j]; - - // Index the elements of the vector part of the quaternion as a float* - float* v = (float*)(this); - - // If we attempted to pre-normalize and trusted the matrix to be - // perfectly orthonormal, the result would be: - // - // double c = sqrt((rot[i][i] - (rot[j][j] + rot[k][k])) + 1.0) - // v[i] = -c * 0.5 - // v[j] = -(rot[i][j] + rot[j][i]) * 0.5 / c - // v[k] = -(rot[i][k] + rot[k][i]) * 0.5 / c - // w = (rot[j][k] - rot[k][j]) * 0.5 / c - // - // Since we're going to pay the sqrt anyway, we perform a post normalization, which also - // fixes any poorly normalized input. Multiply all elements by 2*c in the above, giving: - - // nc2 = -c^2 - double nc2 = ((rot[j][j] + rot[k][k]) - rot[i][i]) - 1.0; - v[i] = nc2; - w = (rot[j][k] - rot[k][j]); - v[j] = -(rot[i][j] + rot[j][i]); - v[k] = -(rot[i][k] + rot[k][i]); - - // We now have the correct result with the wrong magnitude, so normalize it: - float s = sqrt(x*x + y*y + z*z + w*w); - if (s > 0.00001f) { - s = 1.0f / s; - x *= s; - y *= s; - z *= s; - w *= s; - } else { - // The quaternion is nearly zero. Make it 0 0 0 1 - x = 0.0f; - y = 0.0f; - z = 0.0f; - w = 1.0f; - } -} - - -void Quat::toAxisAngleRotation( - Vector3& axis, - double& angle) const { - - // Decompose the quaternion into an angle and an axis. - - axis = Vector3(x, y, z); - angle = 2 * acos(w); - - float len = sqrt(1.0f - w * w); - - if (fuzzyGt(abs(len), 0.0f)) { - axis /= len; - } - - // Reduce the range of the angle. - - if (angle < 0) { - angle = -angle; - axis = -axis; - } - - while (angle > twoPi()) { - angle -= twoPi(); - } - - if (abs(angle) > pi()) { - angle -= twoPi(); - } - - // Make the angle positive. - - if (angle < 0.0f) { - angle = -angle; - axis = -axis; - } -} - - -Matrix3 Quat::toRotationMatrix() const { - Matrix3 out = Matrix3::zero(); - - toRotationMatrix(out); - - return out; -} - - -void Quat::toRotationMatrix( - Matrix3& rot) const { - - rot = Matrix3(*this); -} - - -Quat Quat::slerp( - const Quat& _quat1, - float alpha, - float threshold) const { - - // From: Game Physics -- David Eberly pg 538-540 - // Modified to include lerp for small angles, which - // is a common practice. - - // See also: - // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/index.html - - const Quat& quat0 = *this; - Quat quat1 = _quat1; - - // angle between quaternion rotations - float phi; - float cosphi = quat0.dot(quat1); - - - if (cosphi < 0) { - // Change the sign and fix the dot product; we need to - // loop the other way to get the shortest path - quat1 = -quat1; - cosphi = -cosphi; - } - - // Using G3D::aCos will clamp the angle to 0 and pi - phi = static_cast(G3D::aCos(cosphi)); - - if (phi >= threshold) { - // For large angles, slerp - float scale0, scale1; - - scale0 = sin((1.0f - alpha) * phi); - scale1 = sin(alpha * phi); - - return ( (quat0 * scale0) + (quat1 * scale1) ) / sin(phi); - } else { - // For small angles, linear interpolate - return quat0.nlerp(quat1, alpha); - } -} - - -Quat Quat::nlerp( - const Quat& quat1, - float alpha) const { - - Quat result = (*this) * (1.0f - alpha) + quat1 * alpha; - return result / result.magnitude(); -} - - -Quat Quat::operator*(const Quat& other) const { - - // Following Watt & Watt, page 360 - const Vector3& v1 = imag(); - const Vector3& v2 = other.imag(); - float s1 = w; - float s2 = other.w; - - return Quat(s1*v2 + s2*v1 + v1.cross(v2), s1*s2 - v1.dot(v2)); -} - - -// From "Uniform Random Rotations", Ken Shoemake, Graphics Gems III. -Quat Quat::unitRandom() { - float x0 = uniformRandom(); - float r1 = sqrtf(1 - x0), - r2 = sqrtf(x0); - float t1 = (float)G3D::twoPi() * uniformRandom(); - float t2 = (float)G3D::twoPi() * uniformRandom(); - float c1 = cosf(t1), - s1 = sinf(t1); - float c2 = cosf(t2), - s2 = sinf(t2); - return Quat(s1 * r1, c1 * r1, s2 * r2, c2 * r2); -} - - -void Quat::deserialize(class BinaryInput& b) { - x = b.readFloat32(); - y = b.readFloat32(); - z = b.readFloat32(); - w = b.readFloat32(); -} - - -void Quat::serialize(class BinaryOutput& b) const { - b.writeFloat32(x); - b.writeFloat32(y); - b.writeFloat32(z); - b.writeFloat32(w); -} - - -// 2-char swizzles - -Vector2 Quat::xx() const { return Vector2 (x, x); } -Vector2 Quat::yx() const { return Vector2 (y, x); } -Vector2 Quat::zx() const { return Vector2 (z, x); } -Vector2 Quat::wx() const { return Vector2 (w, x); } -Vector2 Quat::xy() const { return Vector2 (x, y); } -Vector2 Quat::yy() const { return Vector2 (y, y); } -Vector2 Quat::zy() const { return Vector2 (z, y); } -Vector2 Quat::wy() const { return Vector2 (w, y); } -Vector2 Quat::xz() const { return Vector2 (x, z); } -Vector2 Quat::yz() const { return Vector2 (y, z); } -Vector2 Quat::zz() const { return Vector2 (z, z); } -Vector2 Quat::wz() const { return Vector2 (w, z); } -Vector2 Quat::xw() const { return Vector2 (x, w); } -Vector2 Quat::yw() const { return Vector2 (y, w); } -Vector2 Quat::zw() const { return Vector2 (z, w); } -Vector2 Quat::ww() const { return Vector2 (w, w); } - -// 3-char swizzles - -Vector3 Quat::xxx() const { return Vector3 (x, x, x); } -Vector3 Quat::yxx() const { return Vector3 (y, x, x); } -Vector3 Quat::zxx() const { return Vector3 (z, x, x); } -Vector3 Quat::wxx() const { return Vector3 (w, x, x); } -Vector3 Quat::xyx() const { return Vector3 (x, y, x); } -Vector3 Quat::yyx() const { return Vector3 (y, y, x); } -Vector3 Quat::zyx() const { return Vector3 (z, y, x); } -Vector3 Quat::wyx() const { return Vector3 (w, y, x); } -Vector3 Quat::xzx() const { return Vector3 (x, z, x); } -Vector3 Quat::yzx() const { return Vector3 (y, z, x); } -Vector3 Quat::zzx() const { return Vector3 (z, z, x); } -Vector3 Quat::wzx() const { return Vector3 (w, z, x); } -Vector3 Quat::xwx() const { return Vector3 (x, w, x); } -Vector3 Quat::ywx() const { return Vector3 (y, w, x); } -Vector3 Quat::zwx() const { return Vector3 (z, w, x); } -Vector3 Quat::wwx() const { return Vector3 (w, w, x); } -Vector3 Quat::xxy() const { return Vector3 (x, x, y); } -Vector3 Quat::yxy() const { return Vector3 (y, x, y); } -Vector3 Quat::zxy() const { return Vector3 (z, x, y); } -Vector3 Quat::wxy() const { return Vector3 (w, x, y); } -Vector3 Quat::xyy() const { return Vector3 (x, y, y); } -Vector3 Quat::yyy() const { return Vector3 (y, y, y); } -Vector3 Quat::zyy() const { return Vector3 (z, y, y); } -Vector3 Quat::wyy() const { return Vector3 (w, y, y); } -Vector3 Quat::xzy() const { return Vector3 (x, z, y); } -Vector3 Quat::yzy() const { return Vector3 (y, z, y); } -Vector3 Quat::zzy() const { return Vector3 (z, z, y); } -Vector3 Quat::wzy() const { return Vector3 (w, z, y); } -Vector3 Quat::xwy() const { return Vector3 (x, w, y); } -Vector3 Quat::ywy() const { return Vector3 (y, w, y); } -Vector3 Quat::zwy() const { return Vector3 (z, w, y); } -Vector3 Quat::wwy() const { return Vector3 (w, w, y); } -Vector3 Quat::xxz() const { return Vector3 (x, x, z); } -Vector3 Quat::yxz() const { return Vector3 (y, x, z); } -Vector3 Quat::zxz() const { return Vector3 (z, x, z); } -Vector3 Quat::wxz() const { return Vector3 (w, x, z); } -Vector3 Quat::xyz() const { return Vector3 (x, y, z); } -Vector3 Quat::yyz() const { return Vector3 (y, y, z); } -Vector3 Quat::zyz() const { return Vector3 (z, y, z); } -Vector3 Quat::wyz() const { return Vector3 (w, y, z); } -Vector3 Quat::xzz() const { return Vector3 (x, z, z); } -Vector3 Quat::yzz() const { return Vector3 (y, z, z); } -Vector3 Quat::zzz() const { return Vector3 (z, z, z); } -Vector3 Quat::wzz() const { return Vector3 (w, z, z); } -Vector3 Quat::xwz() const { return Vector3 (x, w, z); } -Vector3 Quat::ywz() const { return Vector3 (y, w, z); } -Vector3 Quat::zwz() const { return Vector3 (z, w, z); } -Vector3 Quat::wwz() const { return Vector3 (w, w, z); } -Vector3 Quat::xxw() const { return Vector3 (x, x, w); } -Vector3 Quat::yxw() const { return Vector3 (y, x, w); } -Vector3 Quat::zxw() const { return Vector3 (z, x, w); } -Vector3 Quat::wxw() const { return Vector3 (w, x, w); } -Vector3 Quat::xyw() const { return Vector3 (x, y, w); } -Vector3 Quat::yyw() const { return Vector3 (y, y, w); } -Vector3 Quat::zyw() const { return Vector3 (z, y, w); } -Vector3 Quat::wyw() const { return Vector3 (w, y, w); } -Vector3 Quat::xzw() const { return Vector3 (x, z, w); } -Vector3 Quat::yzw() const { return Vector3 (y, z, w); } -Vector3 Quat::zzw() const { return Vector3 (z, z, w); } -Vector3 Quat::wzw() const { return Vector3 (w, z, w); } -Vector3 Quat::xww() const { return Vector3 (x, w, w); } -Vector3 Quat::yww() const { return Vector3 (y, w, w); } -Vector3 Quat::zww() const { return Vector3 (z, w, w); } -Vector3 Quat::www() const { return Vector3 (w, w, w); } - -// 4-char swizzles - -Vector4 Quat::xxxx() const { return Vector4 (x, x, x, x); } -Vector4 Quat::yxxx() const { return Vector4 (y, x, x, x); } -Vector4 Quat::zxxx() const { return Vector4 (z, x, x, x); } -Vector4 Quat::wxxx() const { return Vector4 (w, x, x, x); } -Vector4 Quat::xyxx() const { return Vector4 (x, y, x, x); } -Vector4 Quat::yyxx() const { return Vector4 (y, y, x, x); } -Vector4 Quat::zyxx() const { return Vector4 (z, y, x, x); } -Vector4 Quat::wyxx() const { return Vector4 (w, y, x, x); } -Vector4 Quat::xzxx() const { return Vector4 (x, z, x, x); } -Vector4 Quat::yzxx() const { return Vector4 (y, z, x, x); } -Vector4 Quat::zzxx() const { return Vector4 (z, z, x, x); } -Vector4 Quat::wzxx() const { return Vector4 (w, z, x, x); } -Vector4 Quat::xwxx() const { return Vector4 (x, w, x, x); } -Vector4 Quat::ywxx() const { return Vector4 (y, w, x, x); } -Vector4 Quat::zwxx() const { return Vector4 (z, w, x, x); } -Vector4 Quat::wwxx() const { return Vector4 (w, w, x, x); } -Vector4 Quat::xxyx() const { return Vector4 (x, x, y, x); } -Vector4 Quat::yxyx() const { return Vector4 (y, x, y, x); } -Vector4 Quat::zxyx() const { return Vector4 (z, x, y, x); } -Vector4 Quat::wxyx() const { return Vector4 (w, x, y, x); } -Vector4 Quat::xyyx() const { return Vector4 (x, y, y, x); } -Vector4 Quat::yyyx() const { return Vector4 (y, y, y, x); } -Vector4 Quat::zyyx() const { return Vector4 (z, y, y, x); } -Vector4 Quat::wyyx() const { return Vector4 (w, y, y, x); } -Vector4 Quat::xzyx() const { return Vector4 (x, z, y, x); } -Vector4 Quat::yzyx() const { return Vector4 (y, z, y, x); } -Vector4 Quat::zzyx() const { return Vector4 (z, z, y, x); } -Vector4 Quat::wzyx() const { return Vector4 (w, z, y, x); } -Vector4 Quat::xwyx() const { return Vector4 (x, w, y, x); } -Vector4 Quat::ywyx() const { return Vector4 (y, w, y, x); } -Vector4 Quat::zwyx() const { return Vector4 (z, w, y, x); } -Vector4 Quat::wwyx() const { return Vector4 (w, w, y, x); } -Vector4 Quat::xxzx() const { return Vector4 (x, x, z, x); } -Vector4 Quat::yxzx() const { return Vector4 (y, x, z, x); } -Vector4 Quat::zxzx() const { return Vector4 (z, x, z, x); } -Vector4 Quat::wxzx() const { return Vector4 (w, x, z, x); } -Vector4 Quat::xyzx() const { return Vector4 (x, y, z, x); } -Vector4 Quat::yyzx() const { return Vector4 (y, y, z, x); } -Vector4 Quat::zyzx() const { return Vector4 (z, y, z, x); } -Vector4 Quat::wyzx() const { return Vector4 (w, y, z, x); } -Vector4 Quat::xzzx() const { return Vector4 (x, z, z, x); } -Vector4 Quat::yzzx() const { return Vector4 (y, z, z, x); } -Vector4 Quat::zzzx() const { return Vector4 (z, z, z, x); } -Vector4 Quat::wzzx() const { return Vector4 (w, z, z, x); } -Vector4 Quat::xwzx() const { return Vector4 (x, w, z, x); } -Vector4 Quat::ywzx() const { return Vector4 (y, w, z, x); } -Vector4 Quat::zwzx() const { return Vector4 (z, w, z, x); } -Vector4 Quat::wwzx() const { return Vector4 (w, w, z, x); } -Vector4 Quat::xxwx() const { return Vector4 (x, x, w, x); } -Vector4 Quat::yxwx() const { return Vector4 (y, x, w, x); } -Vector4 Quat::zxwx() const { return Vector4 (z, x, w, x); } -Vector4 Quat::wxwx() const { return Vector4 (w, x, w, x); } -Vector4 Quat::xywx() const { return Vector4 (x, y, w, x); } -Vector4 Quat::yywx() const { return Vector4 (y, y, w, x); } -Vector4 Quat::zywx() const { return Vector4 (z, y, w, x); } -Vector4 Quat::wywx() const { return Vector4 (w, y, w, x); } -Vector4 Quat::xzwx() const { return Vector4 (x, z, w, x); } -Vector4 Quat::yzwx() const { return Vector4 (y, z, w, x); } -Vector4 Quat::zzwx() const { return Vector4 (z, z, w, x); } -Vector4 Quat::wzwx() const { return Vector4 (w, z, w, x); } -Vector4 Quat::xwwx() const { return Vector4 (x, w, w, x); } -Vector4 Quat::ywwx() const { return Vector4 (y, w, w, x); } -Vector4 Quat::zwwx() const { return Vector4 (z, w, w, x); } -Vector4 Quat::wwwx() const { return Vector4 (w, w, w, x); } -Vector4 Quat::xxxy() const { return Vector4 (x, x, x, y); } -Vector4 Quat::yxxy() const { return Vector4 (y, x, x, y); } -Vector4 Quat::zxxy() const { return Vector4 (z, x, x, y); } -Vector4 Quat::wxxy() const { return Vector4 (w, x, x, y); } -Vector4 Quat::xyxy() const { return Vector4 (x, y, x, y); } -Vector4 Quat::yyxy() const { return Vector4 (y, y, x, y); } -Vector4 Quat::zyxy() const { return Vector4 (z, y, x, y); } -Vector4 Quat::wyxy() const { return Vector4 (w, y, x, y); } -Vector4 Quat::xzxy() const { return Vector4 (x, z, x, y); } -Vector4 Quat::yzxy() const { return Vector4 (y, z, x, y); } -Vector4 Quat::zzxy() const { return Vector4 (z, z, x, y); } -Vector4 Quat::wzxy() const { return Vector4 (w, z, x, y); } -Vector4 Quat::xwxy() const { return Vector4 (x, w, x, y); } -Vector4 Quat::ywxy() const { return Vector4 (y, w, x, y); } -Vector4 Quat::zwxy() const { return Vector4 (z, w, x, y); } -Vector4 Quat::wwxy() const { return Vector4 (w, w, x, y); } -Vector4 Quat::xxyy() const { return Vector4 (x, x, y, y); } -Vector4 Quat::yxyy() const { return Vector4 (y, x, y, y); } -Vector4 Quat::zxyy() const { return Vector4 (z, x, y, y); } -Vector4 Quat::wxyy() const { return Vector4 (w, x, y, y); } -Vector4 Quat::xyyy() const { return Vector4 (x, y, y, y); } -Vector4 Quat::yyyy() const { return Vector4 (y, y, y, y); } -Vector4 Quat::zyyy() const { return Vector4 (z, y, y, y); } -Vector4 Quat::wyyy() const { return Vector4 (w, y, y, y); } -Vector4 Quat::xzyy() const { return Vector4 (x, z, y, y); } -Vector4 Quat::yzyy() const { return Vector4 (y, z, y, y); } -Vector4 Quat::zzyy() const { return Vector4 (z, z, y, y); } -Vector4 Quat::wzyy() const { return Vector4 (w, z, y, y); } -Vector4 Quat::xwyy() const { return Vector4 (x, w, y, y); } -Vector4 Quat::ywyy() const { return Vector4 (y, w, y, y); } -Vector4 Quat::zwyy() const { return Vector4 (z, w, y, y); } -Vector4 Quat::wwyy() const { return Vector4 (w, w, y, y); } -Vector4 Quat::xxzy() const { return Vector4 (x, x, z, y); } -Vector4 Quat::yxzy() const { return Vector4 (y, x, z, y); } -Vector4 Quat::zxzy() const { return Vector4 (z, x, z, y); } -Vector4 Quat::wxzy() const { return Vector4 (w, x, z, y); } -Vector4 Quat::xyzy() const { return Vector4 (x, y, z, y); } -Vector4 Quat::yyzy() const { return Vector4 (y, y, z, y); } -Vector4 Quat::zyzy() const { return Vector4 (z, y, z, y); } -Vector4 Quat::wyzy() const { return Vector4 (w, y, z, y); } -Vector4 Quat::xzzy() const { return Vector4 (x, z, z, y); } -Vector4 Quat::yzzy() const { return Vector4 (y, z, z, y); } -Vector4 Quat::zzzy() const { return Vector4 (z, z, z, y); } -Vector4 Quat::wzzy() const { return Vector4 (w, z, z, y); } -Vector4 Quat::xwzy() const { return Vector4 (x, w, z, y); } -Vector4 Quat::ywzy() const { return Vector4 (y, w, z, y); } -Vector4 Quat::zwzy() const { return Vector4 (z, w, z, y); } -Vector4 Quat::wwzy() const { return Vector4 (w, w, z, y); } -Vector4 Quat::xxwy() const { return Vector4 (x, x, w, y); } -Vector4 Quat::yxwy() const { return Vector4 (y, x, w, y); } -Vector4 Quat::zxwy() const { return Vector4 (z, x, w, y); } -Vector4 Quat::wxwy() const { return Vector4 (w, x, w, y); } -Vector4 Quat::xywy() const { return Vector4 (x, y, w, y); } -Vector4 Quat::yywy() const { return Vector4 (y, y, w, y); } -Vector4 Quat::zywy() const { return Vector4 (z, y, w, y); } -Vector4 Quat::wywy() const { return Vector4 (w, y, w, y); } -Vector4 Quat::xzwy() const { return Vector4 (x, z, w, y); } -Vector4 Quat::yzwy() const { return Vector4 (y, z, w, y); } -Vector4 Quat::zzwy() const { return Vector4 (z, z, w, y); } -Vector4 Quat::wzwy() const { return Vector4 (w, z, w, y); } -Vector4 Quat::xwwy() const { return Vector4 (x, w, w, y); } -Vector4 Quat::ywwy() const { return Vector4 (y, w, w, y); } -Vector4 Quat::zwwy() const { return Vector4 (z, w, w, y); } -Vector4 Quat::wwwy() const { return Vector4 (w, w, w, y); } -Vector4 Quat::xxxz() const { return Vector4 (x, x, x, z); } -Vector4 Quat::yxxz() const { return Vector4 (y, x, x, z); } -Vector4 Quat::zxxz() const { return Vector4 (z, x, x, z); } -Vector4 Quat::wxxz() const { return Vector4 (w, x, x, z); } -Vector4 Quat::xyxz() const { return Vector4 (x, y, x, z); } -Vector4 Quat::yyxz() const { return Vector4 (y, y, x, z); } -Vector4 Quat::zyxz() const { return Vector4 (z, y, x, z); } -Vector4 Quat::wyxz() const { return Vector4 (w, y, x, z); } -Vector4 Quat::xzxz() const { return Vector4 (x, z, x, z); } -Vector4 Quat::yzxz() const { return Vector4 (y, z, x, z); } -Vector4 Quat::zzxz() const { return Vector4 (z, z, x, z); } -Vector4 Quat::wzxz() const { return Vector4 (w, z, x, z); } -Vector4 Quat::xwxz() const { return Vector4 (x, w, x, z); } -Vector4 Quat::ywxz() const { return Vector4 (y, w, x, z); } -Vector4 Quat::zwxz() const { return Vector4 (z, w, x, z); } -Vector4 Quat::wwxz() const { return Vector4 (w, w, x, z); } -Vector4 Quat::xxyz() const { return Vector4 (x, x, y, z); } -Vector4 Quat::yxyz() const { return Vector4 (y, x, y, z); } -Vector4 Quat::zxyz() const { return Vector4 (z, x, y, z); } -Vector4 Quat::wxyz() const { return Vector4 (w, x, y, z); } -Vector4 Quat::xyyz() const { return Vector4 (x, y, y, z); } -Vector4 Quat::yyyz() const { return Vector4 (y, y, y, z); } -Vector4 Quat::zyyz() const { return Vector4 (z, y, y, z); } -Vector4 Quat::wyyz() const { return Vector4 (w, y, y, z); } -Vector4 Quat::xzyz() const { return Vector4 (x, z, y, z); } -Vector4 Quat::yzyz() const { return Vector4 (y, z, y, z); } -Vector4 Quat::zzyz() const { return Vector4 (z, z, y, z); } -Vector4 Quat::wzyz() const { return Vector4 (w, z, y, z); } -Vector4 Quat::xwyz() const { return Vector4 (x, w, y, z); } -Vector4 Quat::ywyz() const { return Vector4 (y, w, y, z); } -Vector4 Quat::zwyz() const { return Vector4 (z, w, y, z); } -Vector4 Quat::wwyz() const { return Vector4 (w, w, y, z); } -Vector4 Quat::xxzz() const { return Vector4 (x, x, z, z); } -Vector4 Quat::yxzz() const { return Vector4 (y, x, z, z); } -Vector4 Quat::zxzz() const { return Vector4 (z, x, z, z); } -Vector4 Quat::wxzz() const { return Vector4 (w, x, z, z); } -Vector4 Quat::xyzz() const { return Vector4 (x, y, z, z); } -Vector4 Quat::yyzz() const { return Vector4 (y, y, z, z); } -Vector4 Quat::zyzz() const { return Vector4 (z, y, z, z); } -Vector4 Quat::wyzz() const { return Vector4 (w, y, z, z); } -Vector4 Quat::xzzz() const { return Vector4 (x, z, z, z); } -Vector4 Quat::yzzz() const { return Vector4 (y, z, z, z); } -Vector4 Quat::zzzz() const { return Vector4 (z, z, z, z); } -Vector4 Quat::wzzz() const { return Vector4 (w, z, z, z); } -Vector4 Quat::xwzz() const { return Vector4 (x, w, z, z); } -Vector4 Quat::ywzz() const { return Vector4 (y, w, z, z); } -Vector4 Quat::zwzz() const { return Vector4 (z, w, z, z); } -Vector4 Quat::wwzz() const { return Vector4 (w, w, z, z); } -Vector4 Quat::xxwz() const { return Vector4 (x, x, w, z); } -Vector4 Quat::yxwz() const { return Vector4 (y, x, w, z); } -Vector4 Quat::zxwz() const { return Vector4 (z, x, w, z); } -Vector4 Quat::wxwz() const { return Vector4 (w, x, w, z); } -Vector4 Quat::xywz() const { return Vector4 (x, y, w, z); } -Vector4 Quat::yywz() const { return Vector4 (y, y, w, z); } -Vector4 Quat::zywz() const { return Vector4 (z, y, w, z); } -Vector4 Quat::wywz() const { return Vector4 (w, y, w, z); } -Vector4 Quat::xzwz() const { return Vector4 (x, z, w, z); } -Vector4 Quat::yzwz() const { return Vector4 (y, z, w, z); } -Vector4 Quat::zzwz() const { return Vector4 (z, z, w, z); } -Vector4 Quat::wzwz() const { return Vector4 (w, z, w, z); } -Vector4 Quat::xwwz() const { return Vector4 (x, w, w, z); } -Vector4 Quat::ywwz() const { return Vector4 (y, w, w, z); } -Vector4 Quat::zwwz() const { return Vector4 (z, w, w, z); } -Vector4 Quat::wwwz() const { return Vector4 (w, w, w, z); } -Vector4 Quat::xxxw() const { return Vector4 (x, x, x, w); } -Vector4 Quat::yxxw() const { return Vector4 (y, x, x, w); } -Vector4 Quat::zxxw() const { return Vector4 (z, x, x, w); } -Vector4 Quat::wxxw() const { return Vector4 (w, x, x, w); } -Vector4 Quat::xyxw() const { return Vector4 (x, y, x, w); } -Vector4 Quat::yyxw() const { return Vector4 (y, y, x, w); } -Vector4 Quat::zyxw() const { return Vector4 (z, y, x, w); } -Vector4 Quat::wyxw() const { return Vector4 (w, y, x, w); } -Vector4 Quat::xzxw() const { return Vector4 (x, z, x, w); } -Vector4 Quat::yzxw() const { return Vector4 (y, z, x, w); } -Vector4 Quat::zzxw() const { return Vector4 (z, z, x, w); } -Vector4 Quat::wzxw() const { return Vector4 (w, z, x, w); } -Vector4 Quat::xwxw() const { return Vector4 (x, w, x, w); } -Vector4 Quat::ywxw() const { return Vector4 (y, w, x, w); } -Vector4 Quat::zwxw() const { return Vector4 (z, w, x, w); } -Vector4 Quat::wwxw() const { return Vector4 (w, w, x, w); } -Vector4 Quat::xxyw() const { return Vector4 (x, x, y, w); } -Vector4 Quat::yxyw() const { return Vector4 (y, x, y, w); } -Vector4 Quat::zxyw() const { return Vector4 (z, x, y, w); } -Vector4 Quat::wxyw() const { return Vector4 (w, x, y, w); } -Vector4 Quat::xyyw() const { return Vector4 (x, y, y, w); } -Vector4 Quat::yyyw() const { return Vector4 (y, y, y, w); } -Vector4 Quat::zyyw() const { return Vector4 (z, y, y, w); } -Vector4 Quat::wyyw() const { return Vector4 (w, y, y, w); } -Vector4 Quat::xzyw() const { return Vector4 (x, z, y, w); } -Vector4 Quat::yzyw() const { return Vector4 (y, z, y, w); } -Vector4 Quat::zzyw() const { return Vector4 (z, z, y, w); } -Vector4 Quat::wzyw() const { return Vector4 (w, z, y, w); } -Vector4 Quat::xwyw() const { return Vector4 (x, w, y, w); } -Vector4 Quat::ywyw() const { return Vector4 (y, w, y, w); } -Vector4 Quat::zwyw() const { return Vector4 (z, w, y, w); } -Vector4 Quat::wwyw() const { return Vector4 (w, w, y, w); } -Vector4 Quat::xxzw() const { return Vector4 (x, x, z, w); } -Vector4 Quat::yxzw() const { return Vector4 (y, x, z, w); } -Vector4 Quat::zxzw() const { return Vector4 (z, x, z, w); } -Vector4 Quat::wxzw() const { return Vector4 (w, x, z, w); } -Vector4 Quat::xyzw() const { return Vector4 (x, y, z, w); } -Vector4 Quat::yyzw() const { return Vector4 (y, y, z, w); } -Vector4 Quat::zyzw() const { return Vector4 (z, y, z, w); } -Vector4 Quat::wyzw() const { return Vector4 (w, y, z, w); } -Vector4 Quat::xzzw() const { return Vector4 (x, z, z, w); } -Vector4 Quat::yzzw() const { return Vector4 (y, z, z, w); } -Vector4 Quat::zzzw() const { return Vector4 (z, z, z, w); } -Vector4 Quat::wzzw() const { return Vector4 (w, z, z, w); } -Vector4 Quat::xwzw() const { return Vector4 (x, w, z, w); } -Vector4 Quat::ywzw() const { return Vector4 (y, w, z, w); } -Vector4 Quat::zwzw() const { return Vector4 (z, w, z, w); } -Vector4 Quat::wwzw() const { return Vector4 (w, w, z, w); } -Vector4 Quat::xxww() const { return Vector4 (x, x, w, w); } -Vector4 Quat::yxww() const { return Vector4 (y, x, w, w); } -Vector4 Quat::zxww() const { return Vector4 (z, x, w, w); } -Vector4 Quat::wxww() const { return Vector4 (w, x, w, w); } -Vector4 Quat::xyww() const { return Vector4 (x, y, w, w); } -Vector4 Quat::yyww() const { return Vector4 (y, y, w, w); } -Vector4 Quat::zyww() const { return Vector4 (z, y, w, w); } -Vector4 Quat::wyww() const { return Vector4 (w, y, w, w); } -Vector4 Quat::xzww() const { return Vector4 (x, z, w, w); } -Vector4 Quat::yzww() const { return Vector4 (y, z, w, w); } -Vector4 Quat::zzww() const { return Vector4 (z, z, w, w); } -Vector4 Quat::wzww() const { return Vector4 (w, z, w, w); } -Vector4 Quat::xwww() const { return Vector4 (x, w, w, w); } -Vector4 Quat::ywww() const { return Vector4 (y, w, w, w); } -Vector4 Quat::zwww() const { return Vector4 (z, w, w, w); } -Vector4 Quat::wwww() const { return Vector4 (w, w, w, w); } -} - diff --git a/externals/g3dlite/G3D.lib/source/Ray.cpp b/externals/g3dlite/G3D.lib/source/Ray.cpp deleted file mode 100644 index bf6aadc08d1..00000000000 --- a/externals/g3dlite/G3D.lib/source/Ray.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/** - @file Ray.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2002-07-12 - @edited 2004-03-19 - */ - -#include "G3D/platform.h" -#include "G3D/Ray.h" -#include "G3D/Plane.h" -#include "G3D/Sphere.h" -#include "G3D/CollisionDetection.h" - -namespace G3D { - -Ray::Ray(class BinaryInput& b) { - deserialize(b); -} - - -void Ray::serialize(class BinaryOutput& b) const { - origin.serialize(b); - direction.serialize(b); -} - - -void Ray::deserialize(class BinaryInput& b) { - origin.deserialize(b); - direction.deserialize(b); -} - - -Ray Ray::refract( - const Vector3& newOrigin, - const Vector3& normal, - float iInside, - float iOutside) const { - - Vector3 D = direction.refractionDirection(normal, iInside, iOutside); - return Ray::fromOriginAndDirection( - newOrigin + (direction + normal * (float)sign(direction.dot(normal))) * 0.001f, D); -} - - -Ray Ray::reflect( - const Vector3& newOrigin, - const Vector3& normal) const { - - Vector3 D = direction.reflectionDirection(normal); - return Ray::fromOriginAndDirection(newOrigin + (D + normal) * 0.001f, D); -} - - -Vector3 Ray::intersection(const Plane& plane) const { - float d; - Vector3 normal = plane.normal(); - plane.getEquation(normal, d); - float rate = direction.dot(normal); - - if (rate >= 0.0f) { - return Vector3::inf(); - } else { - float t = -(d + origin.dot(normal)) / rate; - - return origin + direction * t; - } -} - - -float Ray::intersectionTime(const class Sphere& sphere) const { - Vector3 dummy; - return CollisionDetection::collisionTimeForMovingPointFixedSphere( - origin, direction, sphere, dummy); -} - - -float Ray::intersectionTime(const class Plane& plane) const { - Vector3 dummy; - return CollisionDetection::collisionTimeForMovingPointFixedPlane( - origin, direction, plane, dummy); -} - - -float Ray::intersectionTime(const class Box& box) const { - Vector3 dummy; - float time = CollisionDetection::collisionTimeForMovingPointFixedBox( - origin, direction, box, dummy); - - if ((time == inf()) && (box.contains(origin))) { - return 0.0f; - } else { - return time; - } -} - - -float Ray::intersectionTime(const class AABox& box) const { - Vector3 dummy; - bool inside; - float time = CollisionDetection::collisionTimeForMovingPointFixedAABox( - origin, direction, box, dummy, inside); - - if ((time == inf()) && inside) { - return 0.0f; - } else { - return time; - } -} - -} diff --git a/externals/g3dlite/G3D.lib/source/RegistryUtil.cpp b/externals/g3dlite/G3D.lib/source/RegistryUtil.cpp deleted file mode 100644 index 28ff6955d9b..00000000000 --- a/externals/g3dlite/G3D.lib/source/RegistryUtil.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/** - @file RegistryUtil.cpp - - @created 2006-04-06 - @edited 2006-04-24 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. -*/ - -#include "G3D/platform.h" - -// This file is only used on Windows -#ifdef G3D_WIN32 - -#include "G3D/RegistryUtil.h" -#include "G3D/System.h" - -namespace G3D { - -// static helpers -static HKEY getRootKeyFromString(const char* str, size_t length); - - -bool RegistryUtil::keyExists(const std::string& key) { - size_t pos = key.find('\\', 0); - if (pos == std::string::npos) { - return false; - } - - HKEY hkey = getRootKeyFromString(key.c_str(), pos); - - if (hkey == NULL) { - return false; - } - - HKEY openKey; - int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_READ, &openKey); - - debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); - - if (result == ERROR_SUCCESS) { - RegCloseKey(openKey); - return true; - } else { - return false; - } -} - -bool RegistryUtil::valueExists(const std::string& key, const std::string& value) { - size_t pos = key.find('\\', 0); - if (pos == std::string::npos) { - return false; - } - - HKEY hkey = getRootKeyFromString(key.c_str(), pos); - - if ( hkey == NULL ) { - return false; - } - - HKEY openKey; - int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_READ, &openKey); - debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); - - if (result == ERROR_SUCCESS) { - uint32 dataSize = 0; - result = RegQueryValueExA(openKey, value.c_str(), NULL, NULL, NULL, reinterpret_cast(&dataSize)); - - debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); - RegCloseKey(openKey); - } - return (result == ERROR_SUCCESS); -} - - -bool RegistryUtil::readInt32(const std::string& key, const std::string& value, int32& data) { - size_t pos = key.find('\\', 0); - if (pos == std::string::npos) { - return false; - } - - HKEY hkey = getRootKeyFromString(key.c_str(), pos); - - if ( hkey == NULL ) { - return false; - } - - HKEY openKey; - int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_READ, &openKey); - debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); - - if (result == ERROR_SUCCESS) { - uint32 dataSize = sizeof(int32); - result = RegQueryValueExA(openKey, value.c_str(), NULL, NULL, reinterpret_cast(&data), reinterpret_cast(&dataSize)); - - debugAssertM(result == ERROR_SUCCESS, "Could not read registry key value."); - - RegCloseKey(openKey); - } - return (result == ERROR_SUCCESS); -} - -bool RegistryUtil::readBytes(const std::string& key, const std::string& value, uint8* data, uint32& dataSize) { - size_t pos = key.find('\\', 0); - if (pos == std::string::npos) { - return false; - } - - HKEY hkey = getRootKeyFromString(key.c_str(), pos); - - if (hkey == NULL) { - return false; - } - - HKEY openKey; - int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_READ, &openKey); - debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); - - if (result == ERROR_SUCCESS) { - if (data == NULL) { - result = RegQueryValueExA(openKey, value.c_str(), NULL, NULL, NULL, reinterpret_cast(&dataSize)); - } else { - result = RegQueryValueExA(openKey, value.c_str(), NULL, NULL, reinterpret_cast(&data), reinterpret_cast(&dataSize)); - } - - debugAssertM(result == ERROR_SUCCESS, "Could not read registry key value."); - - RegCloseKey(openKey); - } - return (result == ERROR_SUCCESS); -} - -bool RegistryUtil::readString(const std::string& key, const std::string& value, std::string& data) { - size_t pos = key.find('\\', 0); - if (pos == std::string::npos) { - return false; - } - - HKEY hkey = getRootKeyFromString(key.c_str(), pos); - - if (hkey == NULL) { - return false; - } - - HKEY openKey; - int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_READ, &openKey); - debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); - - if (result == ERROR_SUCCESS) { - uint32 dataSize = 0; - - result = RegQueryValueExA(openKey, value.c_str(), NULL, NULL, NULL, reinterpret_cast(&dataSize)); - debugAssertM(result == ERROR_SUCCESS, "Could not read registry key value."); - - // increment datasize to allow for non null-terminated strings in registry - dataSize += 1; - - if (result == ERROR_SUCCESS) { - char* tmpStr = static_cast(System::malloc(dataSize)); - System::memset(tmpStr, 0, dataSize); - - result = RegQueryValueExA(openKey, value.c_str(), NULL, NULL, reinterpret_cast(tmpStr), reinterpret_cast(&dataSize)); - debugAssertM(result == ERROR_SUCCESS, "Could not read registry key value."); - - if (result == ERROR_SUCCESS) { - data = tmpStr; - } - - RegCloseKey(openKey); - System::free(tmpStr); - } - } - return (result == ERROR_SUCCESS); -} - -bool RegistryUtil::writeInt32(const std::string& key, const std::string& value, int32 data) { - size_t pos = key.find('\\', 0); - if (pos == std::string::npos) { - return false; - } - - HKEY hkey = getRootKeyFromString(key.c_str(), pos); - - if (hkey == NULL) { - return false; - } - - HKEY openKey; - int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_WRITE, &openKey); - debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); - - if (result == ERROR_SUCCESS) { - result = RegSetValueExA(openKey, value.c_str(), 0, REG_DWORD, reinterpret_cast(&data), sizeof(int32)); - - debugAssertM(result == ERROR_SUCCESS, "Could not write registry key value."); - - RegCloseKey(openKey); - } - return (result == ERROR_SUCCESS); -} - -bool RegistryUtil::writeBytes(const std::string& key, const std::string& value, const uint8* data, uint32 dataSize) { - debugAssert(data); - - size_t pos = key.find('\\', 0); - if (pos == std::string::npos) { - return false; - } - - HKEY hkey = getRootKeyFromString(key.c_str(), pos); - - if (hkey == NULL) { - return false; - } - - HKEY openKey; - int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_WRITE, &openKey); - debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); - - if (result == ERROR_SUCCESS) { - if (data) { - result = RegSetValueExA(openKey, value.c_str(), 0, REG_BINARY, reinterpret_cast(data), dataSize); - } - - debugAssertM(result == ERROR_SUCCESS, "Could not write registry key value."); - - RegCloseKey(openKey); - } - return (result == ERROR_SUCCESS); -} - -bool RegistryUtil::writeString(const std::string& key, const std::string& value, const std::string& data) { - size_t pos = key.find('\\', 0); - if (pos == std::string::npos) { - return false; - } - - HKEY hkey = getRootKeyFromString(key.c_str(), pos); - - if (hkey == NULL) { - return false; - } - - HKEY openKey; - int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_WRITE, &openKey); - debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); - - if (result == ERROR_SUCCESS) { - result = RegSetValueExA(openKey, value.c_str(), 0, REG_SZ, reinterpret_cast(data.c_str()), (data.size() + 1)); - debugAssertM(result == ERROR_SUCCESS, "Could not write registry key value."); - - RegCloseKey(openKey); - } - return (result == ERROR_SUCCESS); -} - - -// static helpers -static HKEY getRootKeyFromString(const char* str, uint32 length) { - debugAssert(str); - - if (str) { - if ( strncmp(str, "HKEY_CLASSES_ROOT", length) == 0 ) { - return HKEY_CLASSES_ROOT; - } else if ( strncmp(str, "HKEY_CURRENT_CONFIG", length) == 0 ) { - return HKEY_CURRENT_CONFIG; - } else if ( strncmp(str, "HKEY_CURRENT_USER", length) == 0 ) { - return HKEY_CURRENT_USER; - } else if ( strncmp(str, "HKEY_LOCAL_MACHINE", length) == 0 ) { - return HKEY_LOCAL_MACHINE; - } else if ( strncmp(str, "HKEY_PERFORMANCE_DATA", length) == 0 ) { - return HKEY_PERFORMANCE_DATA; - } else if ( strncmp(str, "HKEY_PERFORMANCE_NLSTEXT", length) == 0 ) { - return HKEY_PERFORMANCE_NLSTEXT; - } else if ( strncmp(str, "HKEY_PERFORMANCE_TEXT", length) == 0 ) { - return HKEY_PERFORMANCE_TEXT; - } else if ( strncmp(str, "HKEY_CLASSES_ROOT", length) == 0 ) { - return HKEY_CLASSES_ROOT; - } else { - return NULL; - } - } else { - return NULL; - } -} - -} // namespace G3D - -#endif // G3D_WIN32 diff --git a/externals/g3dlite/G3D.lib/source/Sphere.cpp b/externals/g3dlite/G3D.lib/source/Sphere.cpp deleted file mode 100644 index 935598d52dd..00000000000 --- a/externals/g3dlite/G3D.lib/source/Sphere.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/** - @file Sphere.cpp - - Sphere class - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2001-04-17 - @edited 2006-02-05 - */ - -#include "G3D/platform.h" -#include "G3D/Sphere.h" -#include "G3D/stringutils.h" -#include "G3D/BinaryOutput.h" -#include "G3D/BinaryInput.h" -#include "G3D/AABox.h" -#include "G3D/Plane.h" - -namespace G3D { - -int32 Sphere::dummy; - -Sphere::Sphere(class BinaryInput& b) { - deserialize(b); -} - - -void Sphere::serialize(class BinaryOutput& b) const { - center.serialize(b); - b.writeFloat64(radius); -} - - -void Sphere::deserialize(class BinaryInput& b) { - center.deserialize(b); - radius = (float)b.readFloat64(); -} - - -std::string Sphere::toString() const { - return format("Sphere(<%g, %g, %g>, %g)", - center.x, center.y, center.z, radius); -} - - -bool Sphere::contains(const Vector3& point) const { - double distance = (center - point).squaredMagnitude(); - return distance <= (radius * radius); -} - - -bool Sphere::intersects(const Sphere& other) const { - return (other.center - center).length() <= (radius + other.radius); -} - -bool Sphere::culledBy( - const Array& plane, - int& cullingPlaneIndex, - const uint32 inMask, - uint32& outMask) const { - - return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask, outMask); -} - - -bool Sphere::culledBy( - const Array& plane, - int& cullingPlaneIndex, - const uint32 inMask) const { - - return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask); -} - - -bool Sphere::culledBy( - const class Plane* plane, - int numPlanes, - int& cullingPlane, - const uint32 _inMask, - uint32& childMask) const { - - if (radius == inf()) { - // No plane can cull the infinite box - return false; - } - - uint32 inMask = _inMask; - assert(numPlanes < 31); - - childMask = 0; - - // See if there is one plane for which all of the - // vertices are in the negative half space. - for (int p = 0; p < numPlanes; p++) { - - // Only test planes that are not masked - if ((inMask & 1) != 0) { - - bool culledLow = ! plane[p].halfSpaceContainsFinite(center + plane[p].normal() * radius); - bool culledHigh = ! plane[p].halfSpaceContainsFinite(center - plane[p].normal() * radius); - - if (culledLow) { - // Plane p culled the sphere - cullingPlane = p; - - // The caller should not recurse into the children, - // since the parent is culled. If they do recurse, - // make them only test against this one plane, which - // will immediately cull the volume. - childMask = 1 << p; - return true; - - } else if (culledHigh) { - // The bounding volume straddled the plane; we have - // to keep testing against this plane - childMask |= (1 << p); - } - } - - // Move on to the next bit. - inMask = inMask >> 1; - } - - // None of the planes could cull this box - cullingPlane = -1; - return false; -} - - -bool Sphere::culledBy( - const class Plane* plane, - int numPlanes, - int& cullingPlane, - const uint32 _inMask) const { - - uint32 inMask = _inMask; - assert(numPlanes < 31); - - // See if there is one plane for which all of the - // vertices are in the negative half space. - for (int p = 0; p < numPlanes; p++) { - - // Only test planes that are not masked - if ((inMask & 1) != 0) { - bool culled = ! plane[p].halfSpaceContains(center + plane[p].normal() * radius); - if (culled) { - // Plane p culled the sphere - cullingPlane = p; - return true; - } - } - - // Move on to the next bit. - inMask = inMask >> 1; - } - - // None of the planes could cull this box - cullingPlane = -1; - return false; -} - - -Vector3 Sphere::randomSurfacePoint() const { - return Vector3::random() * radius + center; -} - - -Vector3 Sphere::randomInteriorPoint() const { - Vector3 result; - do { - result = Vector3(uniformRandom(-1, 1), - uniformRandom(-1, 1), - uniformRandom(-1, 1)); - } while (result.squaredMagnitude() >= 1.0f); - - return result * radius + center; -} - - -float Sphere::volume() const { - return (float)pi() * (4.0f / 3.0f) * powf((float)radius, 3.0f); -} - - -float Sphere::area() const { - return (float)pi() * 4.0f * powf((float)radius, 2.0f); -} - - -void Sphere::getBounds(AABox& out) const { - Vector3 extent(radius, radius, radius); - out = AABox(center - extent, center + extent); -} - -} // namespace diff --git a/externals/g3dlite/G3D.lib/source/SplineBase.cpp b/externals/g3dlite/G3D.lib/source/SplineBase.cpp deleted file mode 100644 index 41221624b06..00000000000 --- a/externals/g3dlite/G3D.lib/source/SplineBase.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include "G3D/platform.h" -#include "G3D/Spline.h" - -namespace G3D { - -float SplineBase::getFinalInterval() const { - if (! cyclic) { - return 0; - } else if (finalInterval <= 0) { - int N = time.size(); - if (N >= 2) { - return (time[1] - time[0] + time[N - 1] - time[N - 2]) * 0.5f; - } else { - return 1.0f; - } - } else { - return finalInterval; - } -} - - -Matrix4 SplineBase::computeBasis() { - // The standard Catmull-Rom spline basis (e.g., Watt & Watt p108) - // is for [u^3 u^2 u^1 u^0] * B * [p[0] p[1] p[2] p[3]]^T. - // We need a basis formed for: - // - // U * C * [2*p'[1] p[1] p[2] 2*p'[2]]^T - // - // U * C * [p2-p0 p1 p2 p3-p1]^T - // - // To make this transformation, compute the differences of columns in C: - // For [p0 p1 p2 p3] - Matrix4 basis = - Matrix4( -1, 3, -3, 1, - 2, -5, 4, -1, - -1, 0, 1, 0, - 0, 2, 0, 0) * 0.5f; - - // For [-p0 p1 p2 p3]^T - basis.setColumn(0, -basis.column(0)); - - // For [-p0 p1 p2 p3-p1]^T - basis.setColumn(1, basis.column(1) + basis.column(3)); - - // For [p2-p0 p1 p2 p3-p1]^T - basis.setColumn(2, basis.column(2) - basis.column(0)); - - return basis; -} - - -float SplineBase::duration() const { - if (time.size() == 0) { - return 0; - } else { - return time.last() - time[0] + getFinalInterval(); - } -} - - -void SplineBase::computeIndexInBounds(float s, int& i, float& u) const { - int N = time.size(); - float t0 = time[0]; - float tn = time[N - 1]; - - i = iFloor((N - 1) * (s - t0) / (tn - t0)); - - // Inclusive bounds for binary search - int hi = N - 1; - int lo = 0; - - while ((time[i] > s) || (time[i + 1] <= s)) { - - if (time[i] > s) { - // too big - hi = i - 1; - } else if (time[i + 1] <= s) { - // too small - lo = i + 1; - } - - i = (hi + lo) / 2; - } - - // Having exited the above loop, i must be correct, so compute u. - u = (s - time[i]) / (time[i + 1] - time[i]); -} - - -void SplineBase::computeIndex(float s, int& i, float& u) const { - int N = time.size(); - debugAssertM(N > 0, "No control points"); - float t0 = time[0]; - float tn = time[N - 1]; - - if (N < 2) { - // No control points to work with - i = 0; - u = 0.0; - } else if (cyclic) { - float fi = getFinalInterval(); - - // Cyclic spline - if ((s < t0) || (s >= tn + fi)) { - // Cyclic, off the bottom or top - - // Compute offset and reduce to the in-bounds case - - float d = duration(); - // Number of times we wrapped around the cyclic array - int wraps = iFloor((s - t0) / d); - - debugAssert(s - d * wraps >= t0); - debugAssert(s - d * wraps < tn + getFinalInterval()); - - computeIndex(s - d * wraps, i, u); - i += wraps * N; - - } else if (s >= tn) { - debugAssert(s < tn + fi); - // Cyclic, off the top but before the end of the last interval - i = N - 1; - u = (s - tn) / fi; - - } else { - // Cyclic, in bounds - computeIndexInBounds(s, i, u); - } - - } else { - // Non-cyclic - - if (s < t0) { - // Non-cyclic, off the bottom. Assume points are spaced - // following the first time interval. - - float dt = time[1] - t0; - float x = (s - t0) / dt; - i = iFloor(x); - u = x - i; - - } else if (s >= tn) { - // Non-cyclic, off the top. Assume points are spaced following - // the last time interval. - - float dt = tn - time[N - 2]; - float x = N - 1 + (s - tn) / dt; - i = iFloor(x); - u = x - i; - - } else { - // In bounds, non-cyclic. Assume a regular - // distribution (which gives O(1) for uniform spacing) - // and then binary search to handle the general case - // efficiently. - computeIndexInBounds(s, i, u); - - } // if in bounds - } // if cyclic -} - -} diff --git a/externals/g3dlite/G3D.lib/source/Stopwatch.cpp b/externals/g3dlite/G3D.lib/source/Stopwatch.cpp deleted file mode 100644 index e55f689a9e2..00000000000 --- a/externals/g3dlite/G3D.lib/source/Stopwatch.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/** - @file Stopwatch.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2005-10-05 - @edited 2005-10-05 - - Copyright 2000-2003, Morgan McGuire. - All rights reserved. - */ - -#include "G3D/Stopwatch.h" -#include "G3D/System.h" - -namespace G3D { - -Stopwatch::Stopwatch() : inBetween(false), lastTockTime(-1), - lastDuration(0), lastCycleCount(0), m_fps(0), emwaFPS(0), - m_smoothFPS(0), emwaDuration(0) { - computeOverhead(); -} - - -void Stopwatch::computeOverhead() { - cycleOverhead = 0; - tick(); - tock(); - cycleOverhead = elapsedCycles(); -} - - -void Stopwatch::tick() { - // This is 'alwaysAssert' instead of 'debugAssert' - // since people rarely profile in debug mode. - alwaysAssertM(! inBetween, "Stopwatch::tick() called twice in a row."); - inBetween = true; - - // We read RDTSC twice here, but it is more abstract to implement this - // way and at least we're reading the cycle count last. - timeStart = System::time(); - System::beginCycleCount(cycleStart); -} - - -void Stopwatch::tock() { - System::endCycleCount(cycleStart); - RealTime now = System::time(); - lastDuration = now - timeStart; - if (abs(emwaDuration - lastDuration) > max(emwaDuration, lastDuration) * 0.50) { - // Off by more than 50% - emwaDuration = lastDuration; - } else { - emwaDuration = lastDuration * 0.05 + emwaDuration * 0.95; - } - - lastCycleCount = cycleStart - cycleOverhead; - if (lastCycleCount < 0) { - lastCycleCount = 0; - } - - if (lastTockTime != -1.0) { - m_fps = 1.0 / (now - lastTockTime); - - // Time smooth the average - emwaFPS = m_fps * 0.01 + emwaFPS * 0.99; - - if (abs(emwaFPS - m_fps) > max(emwaFPS, m_fps) * 0.08) { - // The difference between emwa and m_fps is way off - // update emwa directly. - emwaFPS = m_fps; - } - - // Update m_smoothFPS only when the value varies significantly - // We round so as to not mislead the user as to the accuracy of - // the number. - if (m_smoothFPS == 0) { - m_smoothFPS = m_fps; - } else if (emwaFPS <= 10) { - if (::fabs(m_smoothFPS - emwaFPS) > .75) { - m_smoothFPS = floor(emwaFPS * 10.0 + 0.5) / 10.0; - } - } else { - if (::fabs(m_smoothFPS - emwaFPS) > 1.25) { - m_smoothFPS = floor(emwaFPS + 0.5); - } - } - } - lastTockTime = now; - - alwaysAssertM(inBetween, "Stopwatch::tock() called without matching tick."); - inBetween = false; -} - -} - diff --git a/externals/g3dlite/G3D.lib/source/System.cpp b/externals/g3dlite/G3D.lib/source/System.cpp deleted file mode 100644 index 748e13257f1..00000000000 --- a/externals/g3dlite/G3D.lib/source/System.cpp +++ /dev/null @@ -1,1864 +0,0 @@ -/** - @file System.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - Note: every routine must call init() first. - - There are two kinds of detection used in this file. At compile - time, the _MSC_VER #define is used to determine whether x86 assembly - can be used at all. At runtime, processor detection is used to - determine if we can safely call the routines that use that assembly. - - @cite Rob Wyatt http://www.gamasutra.com/features/wyatts_world/19990709/processor_detection_01.htm - @cite Benjamin Jurke http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-ProcessorDetectionClass&forum=cotd&id=-1 - @cite Michael Herf http://www.stereopsis.com/memcpy.html - - @created 2003-01-25 - @edited 2008-09-02 - */ - -#include "G3D/platform.h" -#include "G3D/System.h" -#include "G3D/debug.h" -#include "G3D/fileutils.h" -#include "G3D/TextOutput.h" -#include "G3D/G3DGameUnits.h" -#include "G3D/Crypto.h" -#include "G3D/prompt.h" -#include "G3D/Log.h" -#include - -#include -#include - -// Uncomment the following line to turn off G3D::System memory -// allocation and use the operating system's malloc. -//#define NO_BUFFERPOOL - -#if defined(__i386__) || defined(__x86_64__) || defined(G3D_WIN32) -# define G3D_NOT_OSX_PPC -#endif - -#ifdef G3D_WIN32 - -# include -# include -# include "G3D/RegistryUtil.h" - -#elif defined(G3D_LINUX) - - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - -#elif defined(G3D_OSX) - - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #include - #include -#endif - -#if defined(SSE) - #include -#endif - -namespace G3D { - -struct CpuInfo -{ -public: - int m_cpuSpeed; - bool m_hasCPUID; - bool m_hasRDTSC; - bool m_hasMMX; - bool m_hasSSE; - bool m_hasSSE2; - bool m_hasSSE3; - bool m_has3DNOW; - char m_cpuVendorStr[1024]; -}; - -// helper macro to call cpuid functions and return all values -#ifdef _MSC_VER - - // VC on Intel -# define CALL_CPUID(func, areg, breg, creg, dreg) \ - __asm mov eax, func \ - __asm cpuid \ - __asm mov areg, eax \ - __asm mov breg, ebx \ - __asm mov creg, ecx \ - __asm mov dreg, edx - -#elif defined(__GNUC__) && defined(G3D_OSX_INTEL) - // GCC on OS X intel -# define CALL_CPUID(func, areg, breg, creg, dreg) \ - areg = 0; \ - breg = 0; \ - creg = 0; \ - dreg = 0; -#else - // Any other compiler/platform, likely GCC -# define CALL_CPUID(func, areg, breg, creg, dreg) \ - __asm__ ( \ - "cpuid \n": \ - "=a" (areg), \ - "=b" (breg), \ - "=c" (creg), \ - "=d" (dreg): \ - "a" (func) \ - ); -#endif - -// this holds the data directory set by the application (currently GApp) for use by findDataFile -static char g_appDataDir[FILENAME_MAX] = ""; - -static CpuInfo g_cpuInfo = { - 0, false, false, false, false, false, false, false, {'U', 'n', 'k', 'n', 'o', 'w', 'n', '\0'}}; - -static G3DEndian _machineEndian = G3D_LITTLE_ENDIAN; -static char _cpuArchCstr[1024]; -static char _operatingSystemCstr[1024]; - -#ifdef G3D_WIN32 -/** Used by getTick() for timing */ -static LARGE_INTEGER _start; -static LARGE_INTEGER _counterFrequency; -#else -static struct timeval _start; -#endif - -static char versionCstr[1024]; -System::OutOfMemoryCallback System::outOfMemoryCallback = NULL; - -#ifdef G3D_OSX -long System::m_OSXCPUSpeed; -double System::m_secondsPerNS; -#endif - -/** The Real-World time of System::getTick() time 0. Set by initTime */ -static RealTime realWorldGetTickTime0; - - -static unsigned int maxSupportedCPUIDLevel = 0; -static unsigned int maxSupportedExtendedLevel = 0; - -/** Checks if the CPUID command is available on the processor (called from init) */ -static void checkForCPUID(); - -/** ReadRead the standard processor extensions. Called from init(). */ -static void getStandardProcessorExtensions(); - -/** Called from init */ -static void initTime(); - - -std::string System::findDataFile -(const std::string& full, - bool errorIfNotFound) { - - if (fileExists(full)) { - return full; - } - - std::string initialAppDataDir(g_appDataDir); - - std::string name = filenameBaseExt(full); - std::string originalPath = filenamePath(full); - - // Search several paths - Array pathBase; - - int backlen = 4; - - // add what should be the current working directory - pathBase.append(""); - - // add application specified data directory to be searched first - pathBase.append(initialAppDataDir); - - // try walking back along the directory tree - std::string prev = ""; - for (int i = 0; i < backlen; ++i) { - pathBase.append(originalPath + prev); - prev = prev + "../"; - } - - prev = "../"; - for (int i = 0; i < backlen; ++i) { - pathBase.append(prev); - prev = prev + "../"; - } - - // Hard-code in likely install directories - int ver = G3D_VER; - std::string lname = format("G3D-%d.%02d", ver / 10000, (ver / 100) % 100); - - if (G3D_VER % 100 != 0) { - lname = lname + format("-b%02d/", ver % 100); - } else { - lname = lname + "/"; - } - - // Look in some other likely places -# ifdef G3D_WIN32 - std::string lpath = "libraries/G3D/"; - pathBase.append(std::string("c:/") + lpath); - pathBase.append(std::string("d:/") + lpath); - pathBase.append(std::string("e:/") + lpath); - pathBase.append(std::string("f:/") + lpath); - pathBase.append(std::string("g:/") + lpath); - pathBase.append(std::string("x:/") + lpath); -# endif -# if defined(G3D_LINUX) - pathBase.append("/usr/local/"); - pathBase.append("/course/cs224/"); - pathBase.append("/map/gfx0/common/games/"); -# endif -# if defined(G3D_FREEBSD) - pathBase.append("/usr/local/"); - pathBase.append("/usr/local/371/"); - pathBase.append("/usr/cs-local/371/"); -# endif -# if defined(G3D_OSX) - pathBase.append("/usr/local/" + lname); - pathBase.append("/Volumes/McGuire/Projects/"); -# endif - - // Add the library name to all variations - int N = pathBase.size(); - for (int i = 0; i < N; ++i) { - pathBase.append(pathBase[i] + lname); - pathBase.append(pathBase[i] + "G3D/"); - } - - Array subDir; - subDir.append("", "font/", "sky/", "gui/"); - subDir.append("image/", "quake2/", "quake2/players/"); - subDir.append("quake3/", "SuperShader/", "ifs/", "3ds/"); - subDir.append("quake2/speedway/"); - - Array path; - for (int p = 0; p < pathBase.size(); ++p) { - for (int s = 0; s < subDir.size(); ++s) { - path.append(pathBase[p] + subDir[s]); - path.append(pathBase[p] + "data/" + subDir[s]); - path.append(pathBase[p] + "data-files/" + subDir[s]); - } - } - - for (int i = 0; i < path.length(); ++i) { - std::string filename = path[i] + name; - if (fileExists(filename)) { - logPrintf("\nWARNING: Could not find '%s' so '%s' " - "was substituted.\n", full.c_str(), - filename.c_str()); - return filename; - } - } - - if (errorIfNotFound) { - // Generate an error message - std::string locations; - for (int i = 0; i < path.size(); ++i) { - locations += path[i] + name + "\n"; - } - alwaysAssertM(false, "Could not find '" + full + "' in:\n" + locations); - } - // Not found - return ""; -} - - -void System::setAppDataDir(const std::string& path) { - // just copy the path, it needs to be valid - strncpy(g_appDataDir, path.c_str(), sizeof(g_appDataDir)); -} - - -std::string demoFindData(bool errorIfNotFound) { - // Directories that might contain the data - Array potential; - - // Look back up the directory tree - std::string x = "../"; - std::string f = ""; - for (int i = 0; i < 6; ++i) { - potential.append(f); - f = f + x; - } - - // Hard-code in likely install directories - int ver = G3D_VER; - std::string lname = format("G3D-%d.%02d", ver / 10000, (ver / 100) % 100); - - if (G3D_VER % 100 != 0) { - lname = lname + format("-b%02d/", ver % 100); - } else { - lname = lname + "/"; - } - - std::string lpath = "libraries/" + lname; - #ifdef G3D_WIN32 - potential.append(std::string("c:/") + lpath); - potential.append(std::string("d:/") + lpath); - potential.append(std::string("e:/") + lpath); - potential.append(std::string("f:/") + lpath); - potential.append(std::string("g:/") + lpath); - potential.append(std::string("x:/") + lpath); - #elif defined(G3D_LINUX) - potential.append("/usr/local/" + lname); - potential.append("/course/cs224/"); - potential.append("/map/gfx0/common/games/"); - #elif defined(G3D_FREEBSD) - potential.append("/usr/local/" + lname); - potential.append("/usr/local/371/") - potential.append("/usr/cs-local/371/") - #elif defined(G3D_OSX) - potential.append("/usr/local/" + lname); - potential.append("/Volumes/McGuire/Projects/"); - potential.append("/Volumes/McGuire/Projects/G3D/"); - #endif - - // Scan all potentials for the font directory - for (int p = 0; p < potential.size(); ++p) { - std::string path = potential[p]; - //debugPrintf("Looking at: %sdata\n", path.c_str()); - if (fileExists(path + "data") && fileExists(path + "data/font")) { - return path + "data/"; - } - if (fileExists(path + "data-files") && fileExists(path + "data-files/font")) { - return path + "data-files/"; - } - } - - if (errorIfNotFound) { - const char* choice[] = {"Exit"}; - - prompt("Demo Error", "The demo could not locate the data directory. " - "The data is required to run this demo. If you have not downloaded " - "the data zipfile, get it from http://g3d-cpp.sf.net. If you have " - "downloaded it, it needs to be no more than 4 directories above the " - "demo directory.", choice, 1, true); - } - - return ""; -} - -bool System::hasCPUID() { - init(); - return g_cpuInfo.m_hasCPUID; -} - -bool System::hasRDTSC() { - init(); - return g_cpuInfo.m_hasRDTSC; -} - - -bool System::hasSSE() { - init(); - return g_cpuInfo.m_hasSSE; -} - - -bool System::hasSSE2() { - init(); - return g_cpuInfo.m_hasSSE2; -} - -bool System::hasSSE3() { - init(); - return g_cpuInfo.m_hasSSE3; -} - -bool System::hasMMX() { - init(); - return g_cpuInfo.m_hasMMX; -} - - -bool System::has3DNow() { - init(); - return g_cpuInfo.m_has3DNOW; -} - - -const std::string& System::cpuVendor() { - init(); - static const std::string _cpuVendor = g_cpuInfo.m_cpuVendorStr; - return _cpuVendor; -} - - -G3DEndian System::machineEndian() { - init(); - return _machineEndian; -} - -const std::string& System::operatingSystem() { - init(); - static const std::string _operatingSystem =_operatingSystemCstr; - return _operatingSystem; -} - - -const std::string& System::cpuArchitecture() { - init(); - static const std::string _cpuArch = _cpuArchCstr; - return _cpuArch; -} - -const std::string& System::build() { - const static std::string b = -# ifdef _DEBUG - "Debug"; -# else - "Release"; -# endif - - return b; -} - -const std::string& System::version() { - init(); - - static const std::string _version = versionCstr; - return _version; -} - - -void System::init() { - // Cannot use most G3D data structures or utility functions in here because - // they are not initialized. - - static bool initialized = false; - - if (initialized) { - return; - } - - initialized = true; - - if ((G3D_VER % 100) != 0) { - sprintf(versionCstr, "G3D %d.%02d beta %d", - G3D_VER / 10000, - (G3D_VER / 100) % 100, - G3D_VER % 100); - } else { - sprintf(versionCstr, "G3D %d.%02d", - G3D_VER / 10000, - (G3D_VER / 100) % 100); - } - - // First of all we check if the CPUID command is available - checkForCPUID(); - - // Figure out if this machine is little or big endian. - { - int32 a = 1; - if (*(uint8*)&a == 1) { - _machineEndian = G3D_LITTLE_ENDIAN; - } else { - _machineEndian = G3D_BIG_ENDIAN; - } - } - -# ifdef G3D_NOT_OSX_PPC - // Process the CPUID information - if (g_cpuInfo.m_hasCPUID) { - // We read the standard CPUID level 0x00000000 which should - // be available on every x86 processor. This fills out - // a string with the processor vendor tag. - unsigned int eaxreg = 0, ebxreg = 0, ecxreg = 0, edxreg = 0; - - CALL_CPUID(0x00, eaxreg, ebxreg, ecxreg, edxreg); - - // Then we connect the single register values to the vendor string - *((unsigned int*) g_cpuInfo.m_cpuVendorStr) = ebxreg; - *((unsigned int*) (g_cpuInfo.m_cpuVendorStr + 4)) = edxreg; - *((unsigned int*) (g_cpuInfo.m_cpuVendorStr + 8)) = ecxreg; - g_cpuInfo.m_cpuVendorStr[12] = '\0'; - - // We can also read the max. supported standard CPUID level - maxSupportedCPUIDLevel = eaxreg & 0xFFFF; - - // Then we read the ext. CPUID level 0x80000000 - CALL_CPUID(0x80000000, eaxreg, ebxreg, ecxreg, edxreg); - - // ...to check the max. supported extended CPUID level - maxSupportedExtendedLevel = eaxreg; - - // Then we switch to the specific processor vendors. - // Fill out _cpuArch based on this information. It will - // be overwritten by the next block of code on Windows, - // but on Linux will stand. - switch (ebxreg) { - case 0x756E6547: // GenuineIntel - strcpy(_cpuArchCstr, "Intel Processor"); - break; - - case 0x68747541: // AuthenticAMD - strcpy(_cpuArchCstr, "AMD Processor"); - break; - - case 0x69727943: // CyrixInstead - strcpy(_cpuArchCstr, "Cyrix Processor"); - break; - - default: - strcpy(_cpuArchCstr, "Unknown Processor Vendor"); - break; - } - } - #endif // G3D_NOT_OSX_PPC - - #ifdef G3D_WIN32 - bool success = RegistryUtil::readInt32 - ("HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", "~MHz", g_cpuInfo.m_cpuSpeed); - - SYSTEM_INFO systemInfo; - GetSystemInfo(&systemInfo); - char* arch; - switch (systemInfo.wProcessorArchitecture) { - case PROCESSOR_ARCHITECTURE_INTEL: - arch = "Intel"; - break; - - case PROCESSOR_ARCHITECTURE_MIPS: - arch = "MIPS"; - break; - - case PROCESSOR_ARCHITECTURE_ALPHA: - arch = "Alpha"; - break; - - case PROCESSOR_ARCHITECTURE_PPC: - arch = "Power PC"; - break; - - default: - arch = "Unknown"; - } - - uint32 maxAddr = (uint32)systemInfo.lpMaximumApplicationAddress; - sprintf(_cpuArchCstr, "%d x %d-bit %s processor", - systemInfo.dwNumberOfProcessors, - (int)(::log((double)maxAddr) / ::log(2.0) + 2.0), - arch); - // _CPUSpeed / (1024.0 * 1024)); - - OSVERSIONINFO osVersionInfo; - osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - success = GetVersionEx(&osVersionInfo) != 0; - - if (success) { - sprintf(_operatingSystemCstr, "Windows %d.%d build %d Platform %d %s", - osVersionInfo.dwMajorVersion, - osVersionInfo.dwMinorVersion, - osVersionInfo.dwBuildNumber, - osVersionInfo.dwPlatformId, - osVersionInfo.szCSDVersion); - } else { - strcpy(_operatingSystemCstr, "Windows"); - } - - #elif defined(G3D_LINUX) - - { - // Shell out to the 'uname' command - FILE* f = popen("uname -a", "r"); - - int len = 100; - char* r = (char*)::malloc(len * sizeof(char)); - fgets(r, len, f); - // Remove trailing newline - if (r[strlen(r) - 1] == '\n') { - r[strlen(r) - 1] = '\0'; - } - fclose(f); - - strcpy(_operatingSystemCstr, r); - ::free(r); - } - - #elif defined(G3D_OSX) - - // Operating System: - SInt32 macVersion; - Gestalt(gestaltSystemVersion, &macVersion); - - int major = (macVersion >> 8) & 0xFF; - int minor = (macVersion >> 4) & 0xF; - int revision = macVersion & 0xF; - - sprintf(_operatingSystemCstr, "OS X %x.%x.%x", major, minor, revision); - - // Clock Cycle Timing Information: - Gestalt('pclk', &System::m_OSXCPUSpeed); - g_cpuInfo.m_cpuSpeed = iRound((double)m_OSXCPUSpeed / (1024 * 1024)); - m_secondsPerNS = 1.0 / 1.0e9; - - // System Architecture: - const NXArchInfo* pInfo = NXGetLocalArchInfo(); - - if (pInfo) { - strcpy(_cpuArchCstr, pInfo->description); - - switch (pInfo->cputype) { - case CPU_TYPE_POWERPC: - switch(pInfo->cpusubtype){ - case CPU_SUBTYPE_POWERPC_750: - case CPU_SUBTYPE_POWERPC_7400: - case CPU_SUBTYPE_POWERPC_7450: - strcpy(g_cpuInfo.m_cpuVendorStr, "Motorola"); - break; - case CPU_SUBTYPE_POWERPC_970: - strcpy(g_cpuInfo.m_cpuVendorStr, "IBM"); - break; - } - break; - - case CPU_TYPE_I386: - strcpy(g_cpuInfo.m_cpuVendorStr, "Intel"); - break; - } - } - #endif - - initTime(); - - getStandardProcessorExtensions(); -} - -static void checkForCPUID() { - unsigned int bitChanged = 0; - - // We've to check if we can toggle the flag register bit 21. - // If we can't the processor does not support the CPUID command. - -#if defined(_MSC_VER) - __asm { - push eax - push ebx - pushfd - pushfd - pop eax - mov ebx, eax - xor eax, 0x00200000 - push eax - popfd - pushfd - pop eax - popfd - xor eax, ebx - mov bitChanged, eax - pop ebx - pop eax - } -#elif defined(__GNUC__) && defined(i386) && !defined(G3D_OSX_INTEL) - // 32-bit g++ - __asm__ ( - "pushfl # Get original EFLAGS \n" - "pushfl \n" - "popl %%eax \n" - "movl %%eax, %%ecx \n" - "xorl $0x200000, %%eax # Flip ID bit in EFLAGS \n" - "pushl %%eax # Save new EFLAGS value on stack \n" - "popfl # Replace current EFLAGS value \n" - "pushfl # Get new EFLAGS \n" - "popl %%eax # Store new EFLAGS in EAX \n" - "popfl \n" - "xorl %%ecx, %%eax # Can not toggle ID bit, \n" - "movl %%eax, %0 # We have CPUID support \n" - : "=m" (bitChanged) - : // No inputs - : "%eax", "%ecx" - ); -#elif defined(__GNUC__) && defined(__x86_64__) && !defined(G3D_OSX_INTEL) - // x86_64 has SSE and CPUID - - bitChanged = 1; -#else - // Unknown architecture - bitChanged = 0; -#endif - - g_cpuInfo.m_hasCPUID = ((bitChanged == 0) ? false : true); -} - -void getStandardProcessorExtensions() { -#if !defined(G3D_OSX) || defined(G3D_OSX_INTEL) - if (! g_cpuInfo.m_hasCPUID) { - return; - } - - unsigned int eaxreg = 0, ebxreg = 0, ecxreg = 0; - unsigned int features = 0; - - // http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf - // call cpuid with function 0x01 in EAX - - // Invoking CPUID with '1' in EAX fills out edx with a bit string. - // The bits of this value indicate the presence or absence of - // useful processor features. - CALL_CPUID(0x01, eaxreg, ebxreg, ecxreg, features); - - #define checkBit(var, bit) ((var & (1 << bit)) ? true : false) - - g_cpuInfo.m_hasRDTSC = checkBit(features, 16); - g_cpuInfo.m_hasMMX = checkBit(features, 23); - g_cpuInfo.m_hasSSE = checkBit(features, 25); - g_cpuInfo.m_hasSSE2 = checkBit(features, 26); - g_cpuInfo.m_hasSSE3 = checkBit(ecxreg, 0); - - if (maxSupportedExtendedLevel >= 0x80000001) { - // function 0x80000001 changes bit 31 of edx to 3dnow support flag - CALL_CPUID(0x80000001, eaxreg, ebxreg, ecxreg, features); - g_cpuInfo.m_has3DNOW = checkBit(features, 31); - } else { - g_cpuInfo.m_has3DNOW = false; - } - - #undef checkBit -#endif -} - -#if defined(SSE) - -// Copy in 128 bytes chunks, where each chunk contains 8*float32x4 = 8 * 4 * 4 bytes = 128 bytes -// -// -void memcpySSE2(void* dst, const void* src, int nbytes) { - int remainingBytes = nbytes; - - if (nbytes > 128) { - - // Number of chunks - int N = nbytes / 128; - - float* restrict d = (float*)dst; - const float* restrict s = (const float*)src; - - // Finish when the destination pointer has moved 8N elements - float* stop = d + (N * 8 * 4); - - while (d < stop) { - // Inner loop unrolled 8 times - const __m128 r0 = _mm_loadu_ps(s); - const __m128 r1 = _mm_loadu_ps(s + 4); - const __m128 r2 = _mm_loadu_ps(s + 8); - const __m128 r3 = _mm_loadu_ps(s + 12); - const __m128 r4 = _mm_loadu_ps(s + 16); - const __m128 r5 = _mm_loadu_ps(s + 20); - const __m128 r6 = _mm_loadu_ps(s + 24); - const __m128 r7 = _mm_loadu_ps(s + 28); - - _mm_storeu_ps(d, r0); - _mm_storeu_ps(d + 4, r1); - _mm_storeu_ps(d + 8, r2); - _mm_storeu_ps(d + 12, r3); - _mm_storeu_ps(d + 16, r4); - _mm_storeu_ps(d + 20, r5); - _mm_storeu_ps(d + 24, r6); - _mm_storeu_ps(d + 28, r7); - - s += 32; - d += 32; - } - - remainingBytes -= N * 8 * 4 * 4; - } - - if (remainingBytes > 0) { - // Memcpy the rest - memcpy((uint8*)dst + (nbytes - remainingBytes), (const uint8*)src + (nbytes - remainingBytes), remainingBytes); - } -} -#else - - // Fall back to memcpy - void memcpySSE2(void *dst, const void *src, int nbytes) { - memcpy(dst, src, nbytes); - } - -#endif - -#if defined(G3D_WIN32) && defined(SSE) -/** Michael Herf's fast memcpy */ -void memcpyMMX(void* dst, const void* src, int nbytes) { - int remainingBytes = nbytes; - - if (nbytes > 64) { - _asm { - mov esi, src - mov edi, dst - mov ecx, nbytes - shr ecx, 6 // 64 bytes per iteration - - loop1: - movq mm1, 0[ESI] // Read in source data - movq mm2, 8[ESI] - movq mm3, 16[ESI] - movq mm4, 24[ESI] - movq mm5, 32[ESI] - movq mm6, 40[ESI] - movq mm7, 48[ESI] - movq mm0, 56[ESI] - - movntq 0[EDI], mm1 // Non-temporal stores - movntq 8[EDI], mm2 - movntq 16[EDI], mm3 - movntq 24[EDI], mm4 - movntq 32[EDI], mm5 - movntq 40[EDI], mm6 - movntq 48[EDI], mm7 - movntq 56[EDI], mm0 - - add esi, 64 - add edi, 64 - dec ecx - jnz loop1 - - emms - } - remainingBytes -= ((nbytes >> 6) << 6); - } - - if (remainingBytes > 0) { - // Memcpy the rest - memcpy((uint8*)dst + (nbytes - remainingBytes), (const uint8*)src + (nbytes - remainingBytes), remainingBytes); - } -} - -#else - // Fall back to memcpy - void memcpyMMX(void *dst, const void *src, int nbytes) { - memcpy(dst, src, nbytes); - } - -#endif - - -void System::memcpy(void* dst, const void* src, size_t numBytes) { - if (System::hasSSE2() && System::hasMMX()) { - G3D::memcpyMMX(dst, src, numBytes); - } else if (System::hasSSE() && System::hasMMX()) { - G3D::memcpyMMX(dst, src, numBytes); - } else { - ::memcpy(dst, src, numBytes); - } -} - - -/** Michael Herf's fastest memset. n32 must be filled with the same - character repeated. */ -#if defined(G3D_WIN32) && defined(SSE) - -// On x86 processors, use MMX -void memfill(void *dst, int n32, unsigned long i) { - - int originalSize = i; - int bytesRemaining = i; - - if (i > 16) { - - bytesRemaining = i % 16; - i -= bytesRemaining; - __asm { - movq mm0, n32 - punpckldq mm0, mm0 - mov edi, dst - - loopwrite: - - movntq 0[edi], mm0 - movntq 8[edi], mm0 - - add edi, 16 - sub i, 16 - jg loopwrite - - emms - } - } - - if (bytesRemaining > 0) { - ::memset((uint8*)dst + (originalSize - bytesRemaining), n32, bytesRemaining); - } -} - -#else - -// For non x86 processors, we fall back to the standard memset -void memfill(void *dst, int n32, unsigned long i) { - ::memset(dst, n32, i); -} - -#endif - - -void System::memset(void* dst, uint8 value, size_t numBytes) { - if (System::hasSSE() && System::hasMMX()) { - uint32 v = value; - v = v + (v << 8) + (v << 16) + (v << 24); - G3D::memfill(dst, v, numBytes); - } else { - ::memset(dst, value, numBytes); - } -} - - -std::string& System::appName() { - static std::string n = filenameBase(currentProgramFilename()); - return n; -} - - -std::string System::currentProgramFilename() { - char filename[2048]; - - #ifdef G3D_WIN32 - { - GetModuleFileNameA(NULL, filename, sizeof(filename)); - } - #else - { - int ret = readlink("/proc/self/exe", filename, sizeof(filename)); - - // In case of an error, leave the handling up to the caller - if (ret == -1) { - return ""; - } - - debugAssert((int)sizeof(filename) > ret); - - // Ensure proper NULL termination - filename[ret] = 0; - } - #endif - - return filename; -} - - -void System::sleep(RealTime t) { - - // Overhead of calling this function. - static const RealTime OVERHEAD = .000006; - - RealTime now = time(); - RealTime wakeupTime = now + t - OVERHEAD; - - RealTime remainingTime = wakeupTime - now; - RealTime sleepTime = 0; - - while (remainingTime > 0) { - - - if (remainingTime > 0.001) { - // Safe to use Sleep with a time... sleep for half the remaining time - sleepTime = max(remainingTime * .5, 0.0005); - } else if (remainingTime > 0.0001) { - // Safe to use Sleep with a zero time; - // causes the program to yield only - // the current time slice, and then return. - sleepTime = 0; - } else { - // Not safe to use Sleep; busy wait - sleepTime = -1; - } - - if (sleepTime >= 0) { - #ifdef G3D_WIN32 - // Translate to milliseconds - Sleep((int)(sleepTime * 1e3)); - #else - // Translate to microseconds - usleep((int)(sleepTime * 1e6)); - #endif - } - - now = time(); - remainingTime = wakeupTime - now; - } -} - - -void System::consoleClearScreen() { - #ifdef G3D_WIN32 - system("cls"); - #else - system("clear"); - #endif -} - - -bool System::consoleKeyPressed() { - #ifdef G3D_WIN32 - - return _kbhit() != 0; - - #else - - static const int STDIN = 0; - static bool initialized = false; - - if (! initialized) { - // Use termios to turn off line buffering - termios term; - tcgetattr(STDIN, &term); - term.c_lflag &= ~ICANON; - tcsetattr(STDIN, TCSANOW, &term); - setbuf(stdin, NULL); - initialized = true; - } - - #ifdef G3D_LINUX - - int bytesWaiting; - ioctl(STDIN, FIONREAD, &bytesWaiting); - return bytesWaiting; - - #else - - timeval timeout; - fd_set rdset; - - FD_ZERO(&rdset); - FD_SET(STDIN, &rdset); - timeout.tv_sec = 0; - timeout.tv_usec = 0; - - return select(STDIN + 1, &rdset, NULL, NULL, &timeout); - #endif - #endif -} - - -int System::consoleReadKey() { - #ifdef G3D_WIN32 - return _getch(); - #else - char c; - read(0, &c, 1); - return c; - #endif -} - - -void initTime() { - #ifdef G3D_WIN32 - if (QueryPerformanceFrequency(&_counterFrequency)) { - QueryPerformanceCounter(&_start); - } - - struct _timeb t; - _ftime(&t); - - realWorldGetTickTime0 = (RealTime)t.time - t.timezone * G3D::MINUTE + (t.dstflag ? G3D::HOUR : 0); - - #else - gettimeofday(&_start, NULL); - // "sse" = "seconds since epoch". The time - // function returns the seconds since the epoch - // GMT (perhaps more correctly called UTC). - time_t gmt = time(NULL); - - // No call to free or delete is needed, but subsequent - // calls to asctime, ctime, mktime, etc. might overwrite - // local_time_vals. - tm* localTimeVals = localtime(&gmt); - - time_t local = gmt; - - if (localTimeVals) { - // tm_gmtoff is already corrected for daylight savings. - local = local + localTimeVals->tm_gmtoff; - } - - realWorldGetTickTime0 = local; - #endif -} - - -RealTime System::time() { - init(); - #ifdef G3D_WIN32 - LARGE_INTEGER now; - QueryPerformanceCounter(&now); - - return ((RealTime)(now.QuadPart - _start.QuadPart) / - _counterFrequency.QuadPart) + realWorldGetTickTime0; - #else - // Linux resolution defaults to 100Hz. - // There is no need to do a separate RDTSC call as gettimeofday - // actually uses RDTSC when on systems that support it, otherwise - // it uses the system clock. - struct timeval now; - gettimeofday(&now, NULL); - - return (now.tv_sec - _start.tv_sec) + - (now.tv_usec - _start.tv_usec) / 1e6 - + realWorldGetTickTime0; - #endif -} - - -//////////////////////////////////////////////////////////////// - -#define REALPTR_TO_USERPTR(x) ((uint8*)(x) + sizeof (void *)) -#define USERPTR_TO_REALPTR(x) ((uint8*)(x) - sizeof (void *)) -#define REALBLOCK_SIZE(x) ((x) + sizeof (void *)) - -class BufferPool { -public: - - /** Only store buffers up to these sizes (in bytes) in each pool-> - Different pools have different management strategies. - - A large block is preallocated for tiny buffers; they are used with - tremendous frequency. Other buffers are allocated as demanded. - Tiny buffers are 128 bytes long because that seems to align well with - cache sizes on many machines. - */ - enum {tinyBufferSize = 128, smallBufferSize = 1024, medBufferSize = 4096}; - - /** - Most buffers we're allowed to store. - 128000 * 128 = 16 MB (preallocated) - 2048 * 1024 = 2 MB (allocated on demand) - 1024 * 4096 = 4 MB (allocated on demand) - */ - enum {maxTinyBuffers = 128000, maxSmallBuffers = 2048, maxMedBuffers = 1024}; - -private: - - class MemBlock { - public: - void* ptr; - size_t bytes; - - inline MemBlock() : ptr(NULL), bytes(0) {} - inline MemBlock(void* p, size_t b) : ptr(p), bytes(b) {} - }; - - MemBlock smallPool[maxSmallBuffers]; - int smallPoolSize; - - MemBlock medPool[maxMedBuffers]; - int medPoolSize; - - /** The tiny pool is a single block of storage into which all tiny - objects are allocated. This provides better locality for - small objects and avoids the search time, since all tiny - blocks are exactly the same size. */ - void* tinyPool[maxTinyBuffers]; - int tinyPoolSize; - - /** Pointer to the data in the tiny pool */ - void* tinyHeap; - -# ifdef G3D_WIN32 - CRITICAL_SECTION mutex; -# else - pthread_mutex_t mutex; -# endif - - /** Provide synchronization between threads */ - void lock() { -# ifdef G3D_WIN32 - EnterCriticalSection(&mutex); -# else - pthread_mutex_lock(&mutex); -# endif - } - - void unlock() { -# ifdef G3D_WIN32 - LeaveCriticalSection(&mutex); -# else - pthread_mutex_unlock(&mutex); -# endif - } - - /** - Malloc out of the tiny heap. Returns NULL if allocation failed. - */ - inline void* tinyMalloc(size_t bytes) { - // Note that we ignore the actual byte size - // and create a constant size block. - (void)bytes; - assert(tinyBufferSize >= bytes); - - void* ptr = NULL; - - if (tinyPoolSize > 0) { - --tinyPoolSize; - - // Return the old last pointer from the freelist - ptr = tinyPool[tinyPoolSize]; - -# ifdef G3D_DEBUG - if (tinyPoolSize > 0) { - assert(tinyPool[tinyPoolSize - 1] != ptr); - // "System::malloc heap corruption detected: " - // "the last two pointers on the freelist are identical (during tinyMalloc)."); - } -# endif - - // NULL out the entry to help detect corruption - tinyPool[tinyPoolSize] = NULL; - } - - return ptr; - } - - /** Returns true if this is a pointer into the tiny heap. */ - bool inTinyHeap(void* ptr) { - return - (ptr >= tinyHeap) && - (ptr < (uint8*)tinyHeap + maxTinyBuffers * tinyBufferSize); - } - - void tinyFree(void* ptr) { - assert(ptr); - assert(tinyPoolSize < maxTinyBuffers); - // "Tried to free a tiny pool buffer when the tiny pool freelist is full."); - -# ifdef G3D_DEBUG - if (tinyPoolSize > 0) { - void* prevOnHeap = tinyPool[tinyPoolSize - 1]; - assert(prevOnHeap != ptr); -// "System::malloc heap corruption detected: " -// "the last two pointers on the freelist are identical (during tinyFree)."); - } -# endif - - assert(tinyPool[tinyPoolSize] == NULL); - - // Put the pointer back into the free list - tinyPool[tinyPoolSize] = ptr; - ++tinyPoolSize; - - } - - void flushPool(MemBlock* pool, int& poolSize) { - for (int i = 0; i < poolSize; ++i) { - ::free(pool[i].ptr); - pool[i].ptr = NULL; - pool[i].bytes = 0; - } - poolSize = 0; - } - - - /** Allocate out of a specific pool-> Return NULL if no suitable - memory was found. - - */ - void* malloc(MemBlock* pool, int& poolSize, size_t bytes) { - - // OPT: find the smallest block that satisfies the request. - - // See if there's something we can use in the buffer pool-> - // Search backwards since usually we'll re-use the last one. - for (int i = (int)poolSize - 1; i >= 0; --i) { - if (pool[i].bytes >= bytes) { - // We found a suitable entry in the pool-> - - // No need to offset the pointer; it is already offset - void* ptr = pool[i].ptr; - - // Remove this element from the pool - --poolSize; - pool[i] = pool[poolSize]; - - return ptr; - } - } - - return NULL; - } - -public: - - /** Count of memory allocations that have occurred. */ - int totalMallocs; - int mallocsFromTinyPool; - int mallocsFromSmallPool; - int mallocsFromMedPool; - - /** Amount of memory currently allocated (according to the application). - This does not count the memory still remaining in the buffer pool, - but does count extra memory required for rounding off to the size - of a buffer. - Primarily useful for detecting leaks.*/ - // TODO: make me an atomic int! - volatile int bytesAllocated; - - BufferPool() { - totalMallocs = 0; - - mallocsFromTinyPool = 0; - mallocsFromSmallPool = 0; - mallocsFromMedPool = 0; - - bytesAllocated = true; - - tinyPoolSize = 0; - tinyHeap = NULL; - - smallPoolSize = 0; - - medPoolSize = 0; - - - // Initialize the tiny heap as a bunch of pointers into one - // pre-allocated buffer. - tinyHeap = ::malloc(maxTinyBuffers * tinyBufferSize); - for (int i = 0; i < maxTinyBuffers; ++i) { - tinyPool[i] = (uint8*)tinyHeap + (tinyBufferSize * i); - } - tinyPoolSize = maxTinyBuffers; - -# ifdef G3D_WIN32 - InitializeCriticalSection(&mutex); -# else - pthread_mutex_init(&mutex, NULL); -# endif - } - - - ~BufferPool() { - ::free(tinyHeap); -# ifdef G3D_WIN32 - DeleteCriticalSection(&mutex); -# else - // No destruction on pthreads -# endif - } - - - void* realloc(void* ptr, size_t bytes) { - if (ptr == NULL) { - return malloc(bytes); - } - - if (inTinyHeap(ptr)) { - if (bytes <= tinyBufferSize) { - // The old pointer actually had enough space. - return ptr; - } else { - // Free the old pointer and malloc - - void* newPtr = malloc(bytes); - System::memcpy(newPtr, ptr, tinyBufferSize); - tinyFree(ptr); - return newPtr; - - } - } else { - // In one of our heaps. - - // See how big the block really was - size_t realSize = *(uint32*)USERPTR_TO_REALPTR(ptr); - if (bytes <= realSize) { - // The old block was big enough. - return ptr; - } - - // Need to reallocate - void* newPtr = malloc(bytes); - System::memcpy(newPtr, ptr, realSize); - free(ptr); - return newPtr; - } - } - - - void* malloc(size_t bytes) { - lock(); - ++totalMallocs; - - if (bytes <= tinyBufferSize) { - - void* ptr = tinyMalloc(bytes); - - if (ptr) { - ++mallocsFromTinyPool; - unlock(); - return ptr; - } - - } - - // Failure to allocate a tiny buffer is allowed to flow - // through to a small buffer - if (bytes <= smallBufferSize) { - - void* ptr = malloc(smallPool, smallPoolSize, bytes); - - if (ptr) { - ++mallocsFromSmallPool; - unlock(); - return ptr; - } - - } else if (bytes <= medBufferSize) { - // Note that a small allocation failure does *not* fall - // through into a medium allocation because that would - // waste the medium buffer's resources. - - void* ptr = malloc(medPool, medPoolSize, bytes); - - if (ptr) { - ++mallocsFromMedPool; - unlock(); - debugAssertM(ptr != NULL, "BufferPool::malloc returned NULL"); - return ptr; - } - } - - bytesAllocated += REALBLOCK_SIZE(bytes); - unlock(); - - // Heap allocate - - // Allocate 4 extra bytes for our size header (unfortunate, - // since malloc already added its own header). - void* ptr = ::malloc(REALBLOCK_SIZE(bytes)); - - if (ptr == NULL) { - // Flush memory pools to try and recover space - flushPool(smallPool, smallPoolSize); - flushPool(medPool, medPoolSize); - ptr = ::malloc(REALBLOCK_SIZE(bytes)); - } - - if (ptr == NULL) { - if ((System::outOfMemoryCallback != NULL) && - (System::outOfMemoryCallback(REALBLOCK_SIZE(bytes), true) == true)) { - // Re-attempt the malloc - ptr = ::malloc(REALBLOCK_SIZE(bytes)); - } - } - - if (ptr == NULL) { - if (System::outOfMemoryCallback != NULL) { - // Notify the application - System::outOfMemoryCallback(REALBLOCK_SIZE(bytes), false); - } -# ifdef G3D_DEBUG - debugPrintf("::malloc(%d) returned NULL\n", REALBLOCK_SIZE(bytes)); -# endif - debugAssertM(ptr != NULL, - "::malloc returned NULL. Either the " - "operating system is out of memory or the " - "heap is corrupt."); - return NULL; - } - - *(uint32*)ptr = bytes; - - return REALPTR_TO_USERPTR(ptr); - } - - - void free(void* ptr) { - if (ptr == NULL) { - // Free does nothing on null pointers - return; - } - - assert(isValidPointer(ptr)); - - if (inTinyHeap(ptr)) { - lock(); - tinyFree(ptr); - unlock(); - return; - } - - uint32 bytes = *(uint32*)USERPTR_TO_REALPTR(ptr); - - lock(); - if (bytes <= smallBufferSize) { - if (smallPoolSize < maxSmallBuffers) { - smallPool[smallPoolSize] = MemBlock(ptr, bytes); - ++smallPoolSize; - unlock(); - return; - } - } else if (bytes <= medBufferSize) { - if (medPoolSize < maxMedBuffers) { - medPool[medPoolSize] = MemBlock(ptr, bytes); - ++medPoolSize; - unlock(); - return; - } - } - bytesAllocated -= REALBLOCK_SIZE(bytes); - unlock(); - - // Free; the buffer pools are full or this is too big to store. - ::free(USERPTR_TO_REALPTR(ptr)); - } - - std::string performance() const { - if (totalMallocs > 0) { - int pooled = mallocsFromTinyPool + - mallocsFromSmallPool + - mallocsFromMedPool; - - int total = totalMallocs; - - return format("malloc performance: %5.1f%% <= %db, %5.1f%% <= %db, " - "%5.1f%% <= %db, %5.1f%% > %db", - 100.0 * mallocsFromTinyPool / total, - BufferPool::tinyBufferSize, - 100.0 * mallocsFromSmallPool / total, - BufferPool::smallBufferSize, - 100.0 * mallocsFromMedPool / total, - BufferPool::medBufferSize, - 100.0 * (1.0 - (double)pooled / total), - BufferPool::medBufferSize); - } else { - return "No System::malloc calls made yet."; - } - } - - std::string status() const { - return format("preallocated shared buffers: %5d/%d x %db", - maxTinyBuffers - tinyPoolSize, maxTinyBuffers, tinyBufferSize); - } -}; - -// Dynamically allocated because we need to ensure that -// the buffer pool is still around when the last global variable -// is deallocated. -static BufferPool* bufferpool = NULL; - -std::string System::mallocPerformance() { -#ifndef NO_BUFFERPOOL - return bufferpool->performance(); -#else - return "NO_BUFFERPOOL"; -#endif -} - -std::string System::mallocStatus() { -#ifndef NO_BUFFERPOOL - return bufferpool->status(); -#else - return "NO_BUFFERPOOL"; -#endif -} - - -void System::resetMallocPerformanceCounters() { -#ifndef NO_BUFFERPOOL - bufferpool->totalMallocs = 0; - bufferpool->mallocsFromMedPool = 0; - bufferpool->mallocsFromSmallPool = 0; - bufferpool->mallocsFromTinyPool = 0; -#endif -} - - -#ifndef NO_BUFFERPOOL -inline void initMem() { - // Putting the test here ensures that the system is always - // initialized, even when globals are being allocated. - static bool initialized = false; - if (! initialized) { - bufferpool = new BufferPool(); - initialized = true; - } -} -#endif - - -void* System::malloc(size_t bytes) { -#ifndef NO_BUFFERPOOL - initMem(); - return bufferpool->malloc(bytes); -#else - return ::malloc(bytes); -#endif -} - -void* System::calloc(size_t n, size_t x) { -#ifndef NO_BUFFERPOOL - void* b = System::malloc(n * x); - debugAssertM(b != NULL, "System::malloc returned NULL"); - debugAssertM(isValidHeapPointer(b), "System::malloc returned an invalid pointer"); - System::memset(b, 0, n * x); - return b; -#else - return ::calloc(n, x); -#endif -} - - -void* System::realloc(void* block, size_t bytes) { -#ifndef NO_BUFFERPOOL - initMem(); - return bufferpool->realloc(block, bytes); -#else - return ::realloc(block, bytes); -#endif -} - - -void System::free(void* p) { -#ifndef NO_BUFFERPOOL - bufferpool->free(p); -#else - return ::free(p); -#endif -} - - -void* System::alignedMalloc(size_t bytes, size_t alignment) { - - alwaysAssertM(isPow2(alignment), "alignment must be a power of 2"); - - // We must align to at least a word boundary. - alignment = iMax(alignment, sizeof(void *)); - - // Pad the allocation size with the alignment size and the - // size of the redirect pointer. - size_t totalBytes = bytes + alignment + sizeof(void*); - - size_t truePtr = (size_t)System::malloc(totalBytes); - - if (truePtr == 0) { - // malloc returned NULL - return NULL; - } - - debugAssert(isValidHeapPointer((void*)truePtr)); - #ifdef G3D_WIN32 - // The blocks we return will not be valid Win32 debug heap - // pointers because they are offset - // debugAssert(_CrtIsValidPointer((void*)truePtr, totalBytes, TRUE) ); - #endif - - // The return pointer will be the next aligned location (we must at least - // leave space for the redirect pointer, however). - size_t alignedPtr = truePtr + sizeof(void*); - - // 2^n - 1 has the form 1111... in binary. - uint32 bitMask = (alignment - 1); - - // Advance forward until we reach an aligned location. - while ((alignedPtr & bitMask) != 0) { - alignedPtr += sizeof(void*); - } - - debugAssert(alignedPtr - truePtr + bytes <= totalBytes); - - // Immediately before the aligned location, write the true array location - // so that we can free it correctly. - size_t* redirectPtr = (size_t *)(alignedPtr - sizeof(void *)); - redirectPtr[0] = truePtr; - - debugAssert(isValidHeapPointer((void*)truePtr)); - - #ifdef G3D_WIN32 - debugAssert( _CrtIsValidPointer((void*)alignedPtr, bytes, TRUE) ); - #endif - return (void *)alignedPtr; -} - - -void System::alignedFree(void* _ptr) { - if (_ptr == NULL) { - return; - } - - size_t alignedPtr = (size_t)_ptr; - - // Back up one word from the pointer the user passed in. - // We now have a pointer to a pointer to the true start - // of the memory block. - size_t* redirectPtr = (size_t*)(alignedPtr - sizeof(void *)); - - // Dereference that pointer so that ptr = true start - void* truePtr = (void*)redirectPtr[0]; - - debugAssert(isValidHeapPointer((void*)truePtr)); - System::free(truePtr); -} - - -void System::setEnv(const std::string& name, const std::string& value) { - std::string cmd = name + "=" + value; -# ifdef G3D_WIN32 - _putenv(cmd.c_str()); -# else - // Many linux implementations of putenv expect char* - putenv(const_cast(cmd.c_str())); -# endif -} - -const char* System::getEnv(const std::string& name) { - return getenv(name.c_str()); -} - -static void var(TextOutput& t, const std::string& name, const std::string& val) { - t.writeSymbols(name,"="); - t.writeString(val); - t.writeNewline(); -} - - -static void var(TextOutput& t, const std::string& name, const bool val) { - t.writeSymbols(name, "=", val ? "Yes" : "No"); - t.writeNewline(); -} - - -static void var(TextOutput& t, const std::string& name, const int val) { - t.writeSymbols(name,"="); - t.writeNumber(val); - t.writeNewline(); -} - -void System::describeSystem( - std::string& s) { - - TextOutput t; - describeSystem(t); - t.commitString(s); -} - -void System::describeSystem( - TextOutput& t) { - - t.writeSymbols("App", "{"); - t.writeNewline(); - t.pushIndent(); - var(t, "Name", System::currentProgramFilename()); - char cwd[1024]; - getcwd(cwd, 1024); - var(t, "cwd", std::string(cwd)); - t.popIndent(); - t.writeSymbols("}"); - t.writeNewline(); - t.writeNewline(); - - t.writeSymbols("OS", "{"); - t.writeNewline(); - t.pushIndent(); - var(t, "Name", System::operatingSystem()); - t.popIndent(); - t.writeSymbols("}"); - t.writeNewline(); - t.writeNewline(); - - t.writeSymbols("CPU", "{"); - t.writeNewline(); - t.pushIndent(); - var(t, "Vendor", System::cpuVendor()); - var(t, "Architecture", System::cpuArchitecture()); - var(t, "hasCPUID", System::hasCPUID()); - var(t, "hasMMX", System::hasMMX()); - var(t, "hasSSE", System::hasSSE()); - var(t, "hasSSE2", System::hasSSE2()); - var(t, "hasSSE3", System::hasSSE3()); - var(t, "has3DNow", System::has3DNow()); - var(t, "hasRDTSC", System::hasRDTSC()); - t.popIndent(); - t.writeSymbols("}"); - t.writeNewline(); - t.writeNewline(); - - t.writeSymbols("G3D", "{"); - t.writeNewline(); - t.pushIndent(); - var(t, "Link version", G3D_VER); - var(t, "Compile version", System::version()); - t.popIndent(); - t.writeSymbols("}"); - t.writeNewline(); - t.writeNewline(); -} - - -int System::cpuSpeedMHz() { - return g_cpuInfo.m_cpuSpeed; -} - - -void System::setClipboardText(const std::string& s) { -# ifdef G3D_WIN32 - if (OpenClipboard(NULL)) { - HGLOBAL hMem = GlobalAlloc(GHND | GMEM_DDESHARE, s.size() + 1); - if (hMem) { - char *pMem = (char*)GlobalLock(hMem); - strcpy(pMem, s.c_str()); - GlobalUnlock(hMem); - - EmptyClipboard(); - SetClipboardData(CF_TEXT, hMem); - } - - CloseClipboard(); - GlobalFree(hMem); - } -# endif -} - - -std::string System::getClipboardText() { - std::string s; - -# ifdef G3D_WIN32 - if (OpenClipboard(NULL)) { - HANDLE h = GetClipboardData(CF_TEXT); - - if (h) { - char* temp = (char*)GlobalLock(h); - if (temp) { - s = temp; - } - temp = NULL; - GlobalUnlock(h); - } - CloseClipboard(); - } -# endif - return s; -} - - -std::string System::currentDateString() { - time_t t1; - ::time(&t1); - tm* t = localtime(&t1); - return format("%d-%02d-%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday); -} - - -} // namespace diff --git a/externals/g3dlite/G3D.lib/source/TextInput.cpp b/externals/g3dlite/G3D.lib/source/TextInput.cpp deleted file mode 100644 index d5dc14fb6a0..00000000000 --- a/externals/g3dlite/G3D.lib/source/TextInput.cpp +++ /dev/null @@ -1,988 +0,0 @@ -/** - @file TextInput.cpp - - @author Morgan McGuire, graphics3d.com - - @cite Based on a lexer written by Aaron Orenstein. - - @created 2001-11-27 - @edited 2008-07-14 - */ - -#include "G3D/fileutils.h" -#include "G3D/TextInput.h" -#include "G3D/BinaryInput.h" -#include "G3D/stringutils.h" - -#ifdef _MSC_VER -# pragma warning (push) -// conversion from 'int' to 'char', possible loss of data (TODO: fix underlying problems) -# pragma warning (disable: 4244) -#endif - -namespace G3D { - -double Token::number() const { - if (_type == NUMBER) { - std::string s = toLower(_string); - if (s == "-1.#ind00") { - return nan(); - } - - if (s == "1.#inf00") { - return inf(); - } - - if (s == "-1.#inf00") { - return -inf(); - } - - double n; - if ((_string.length() > 2) && - (_string[0] == '0') && - (_string[1] == 'x')) { - // Hex - uint32 i; - sscanf(_string.c_str(), "%x", &i); - n = i; - } else { - sscanf(_string.c_str(), "%lg", &n); - } - return n; - } else { - return 0.0; - } -} - - -TextInput::Settings::Settings () - : cComments(true), cppComments(true), escapeSequencesInStrings(true), - otherCommentCharacter('\0'), otherCommentCharacter2('\0'), - signedNumbers(true), singleQuotedStrings(true), sourceFileName(), - startingLineNumberOffset(0), msvcSpecials(true), proofSymbols(false), - caseSensitive(true) -{ - trueSymbols.insert("true"); - falseSymbols.insert("false"); -} - - -Token TextInput::peek() { - if (stack.size() == 0) { - Token t = nextToken(); - push(t); - } - - return stack.front(); -} - - -int TextInput::peekLineNumber() { - return peek().line(); -} - - -int TextInput::peekCharacterNumber() { - return peek().character(); -} - - -Token TextInput::read() { - if (stack.size() > 0) { - Token t = stack.front(); - stack.pop_front(); - return t; - } else { - return nextToken(); - } -} - -static void toUpper(Set& set) { - Array symbols; - set.getMembers(symbols); - set.clear(); - for (int i = 0; i < symbols.size(); ++i) { - set.insert(toUpper(symbols[i])); - } -} - -void TextInput::init() { - currentCharOffset = 0; - charNumber = 1; - lineNumber = 1 + options.startingLineNumberOffset; - - if (! options.caseSensitive) { - // Convert true and false symbols to all uppercase for fast comparisons - toUpper(options.trueSymbols); - toUpper(options.falseSymbols); - } -} - - -void TextInput::push(const Token& t) { - stack.push_front(t); -} - - -bool TextInput::hasMore() { - return (peek()._type != Token::END); -} - - -int TextInput::eatInputChar() { - // Don't go off the end - if (currentCharOffset >= (unsigned int)buffer.length()) { - return EOF; - } - - unsigned char c = buffer[currentCharOffset]; - ++currentCharOffset; - - // update lineNumber and charNumber to reflect the location of the *next* - // character which will be read. - // - // We update even for CR because the user is allowed to do arbitrarily - // stupid things, like put a bunch of literal CRs inside a quoted string. - // - // We eat all whitespace between tokens, so they should never see a - // lineNumber that points to a CR. However, if they have some kind of - // syntax error in a token that appears *after* a quoted string - // containing CRs, they should get a correct character number. - - // TODO: http://sourceforge.net/tracker/index.php?func=detail&aid=1341266&group_id=76879&atid=548565 - - if (c == '\n') { - ++lineNumber; - charNumber = 1; - } else { - ++charNumber; - } - - return c; -} - -int TextInput::peekInputChar(unsigned int distance) { - // Don't go off the end - if ((currentCharOffset + distance) >= (unsigned int)buffer.length()) { - return EOF; - } - - unsigned char c = buffer[currentCharOffset + distance]; - return c; -} - - -Token TextInput::nextToken() { - Token t; - - t._line = lineNumber; - t._character = charNumber; - t._type = Token::END; - t._extendedType = Token::END_TYPE; - - int c = peekInputChar(); - if (c == EOF) { - return t; - } - - bool whitespaceDone = false; - while (! whitespaceDone) { - whitespaceDone = true; - - // Consume whitespace - while (isWhiteSpace(c)) { - c = eatAndPeekInputChar(); - } - - int c2 = peekInputChar(1); - if ((options.cppComments && c == '/' && c2 == '/') - || (options.otherCommentCharacter != '\0' - && c == options.otherCommentCharacter) - || (options.otherCommentCharacter2 != '\0' - && c == options.otherCommentCharacter2)) { - - // Single line comment, consume to newline or EOF. - - do { - c = eatAndPeekInputChar(); - } while (! isNewline(c) && c != EOF); - - // There is whitespace after the comment (in particular, the - // newline that terminates the comment). There might also be - // whitespace at the start of the next line. - whitespaceDone = false; - - } else if (options.cComments && (c == '/') && (c2 == '*')) { - - // consume both start-comment chars, can't let the trailing one - // help close the comment. - eatInputChar(); - eatInputChar(); - - // Multi-line comment, consume to end-marker or EOF. - c = peekInputChar(); - c2 = peekInputChar(1); - while (! ((c == '*') && (c2 == '/')) && (c != EOF)) { - eatInputChar(); - c = c2; - c2 = peekInputChar(1); - } - eatInputChar(); // eat closing '*' - eatInputChar(); // eat closing '/' - - c = peekInputChar(); - - // May be whitespace after comment. - whitespaceDone = false; - } - - } // while (! whitespaceDone) - - t._line = lineNumber; - t._character = charNumber; - - // handle EOF - if (c == EOF) { - return t; - } - - // Extended ASCII parses as itself, except for EOF - if (c > 127 && c < 255) { - t._type = Token::SYMBOL; - t._extendedType = Token::SYMBOL_TYPE; - t._string = c; - c = eatAndPeekInputChar(); - } - - - // Perform appropriate setup for a symbol (including setting up the token - // string to start with c), eat the input character, and overwrite - // 'c' with the peeked next input character. -#define SETUP_SYMBOL(c) \ - { \ - t._type = Token::SYMBOL; \ - t._extendedType = Token::SYMBOL_TYPE; \ - t._string = c; \ - c = eatAndPeekInputChar(); \ - } - - switch (c) { - - case '@': // Simple symbols -> just themselves. - case '(': - case ')': - case ',': - case ';': - case '{': - case '}': - case '[': - case ']': - case '#': - case '$': - case '?': - case '%': - SETUP_SYMBOL(c); - return t; - - case '-': // negative number, -, --, -=, or -> - SETUP_SYMBOL(c); - - switch (c) { - case '>': // -> - case '-': // -- - case '=': // -= - t._string += c; - eatInputChar(); - return t; - } - - if (options.signedNumbers - && (isDigit(c) || (c == '.' && isDigit(peekInputChar(1))))) { - - // Negative number. 'c' is still the first digit, and is - // the next input char. - - goto numLabel; - } - - // plain - - return t; - - case '+': // positive number, +, ++, or += - SETUP_SYMBOL(c); - - switch (c) { - case '+': // ++ - case '=': // += - t._string += c; - eatInputChar(); - return t; - } - - if (options.signedNumbers - && (isDigit(c) || (c == '.' && isDigit(peekInputChar(1))))) { - - // Positive number. 'c' is still the first digit, and is - // the next input char. - - goto numLabel; - } - - return t; - - case ':': // : or :: or ::> or ::= or := or :> - SETUP_SYMBOL(c); - - if (c == ':') { - t._string += c; - eatInputChar(); - - if (options.proofSymbols) { - c = peekInputChar(0); - - if ((c == '>') || (c == '=')) { - t._string += c; - eatInputChar(); - } - } - } - else if (options.proofSymbols && (c == '=' || c == '>')) { - t._string += c; - eatInputChar(); - } - return t; - - case '=': // = or == or => - SETUP_SYMBOL(c); - - if (c == '=') { - t._string += c; - eatInputChar(); - return t; - } else if (options.proofSymbols && (c == '>')) { - t._string += c; - eatInputChar(); - return t; - } - return t; - - case '*': // * or *= - case '/': // / or /= - case '!': // ! or != - case '~': // ~ or ~= - case '^': // ^ or ^= - SETUP_SYMBOL(c); - - if (c == '=') { - t._string += c; - eatInputChar(); - return t; - } - return t; - - case '>': // >, >>,or >= - case '<': // <<, <<, or <= or <- or <: - case '|': // ||, ||, or |= or |- - case '&': // &, &&, or &= - { - int orig_c = c; - SETUP_SYMBOL(c); - - if ((c == '=') || (orig_c == c)) { - t._string += c; - eatInputChar(); - return t; - } else if (options.proofSymbols) { - if ((orig_c == '<') && (c == '-')) { - t._string += c; - eatInputChar(); - } else if ((orig_c == '|') && (c == '-')) { - t._string += c; - eatInputChar(); - } else if ((orig_c == '<') && (c == ':')) { - t._string += c; - - c = eatAndPeekInputChar(); - - if (c == ':') { - t._string += c; - eatInputChar(); - } - } - } - } - return t; - - case '\\': // backslash or escaped comment char. - SETUP_SYMBOL(c); - - if ((options.otherCommentCharacter != '\0' - && c == options.otherCommentCharacter) - || (options.otherCommentCharacter2 != '\0' - && c == options.otherCommentCharacter2)) { - - // escaped comment character. Return the raw comment - // char (no backslash). - - t._string = c; - eatInputChar(); - return t; - } - return t; - - case '.': // number, ., .., or ... - if (isDigit(peekInputChar(1))) { - // We're parsing a float that began without a leading zero - goto numLabel; - } - - SETUP_SYMBOL(c); - - if (c == '.') { // .. or ... - t._string += c; - c = eatAndPeekInputChar(); - - if (c == '.') { // ... - t._string += c; - eatInputChar(); - } - return t; - } - - return t; - - } // switch (c) - -#undef SETUP_SYMBOL - -numLabel: - if (isDigit(c) || (c == '.')) { - - // A number. Note-- single dots have been - // parsed already, so a . indicates a number - // less than 1 in floating point form. - - // [0-9]*(\.[0-9]) or [0-9]+ or 0x[0-9,A-F]+ - - if (t._string != "-") { - // If we picked up a leading "-" sign above, keep it, - // otherwise drop the string parsed thus far - t._string = ""; - } - t._type = Token::NUMBER; - if (c == '.') { - t._extendedType = Token::FLOATING_POINT_TYPE; - } else { - t._extendedType = Token::INTEGER_TYPE; - } - - if ((c == '0') && (peekInputChar(1) == 'x')) { - // Hex number - t._string += "0x"; - - // skip the 0x - eatInputChar(); - eatInputChar(); - - c = peekInputChar(); - while (isDigit(c) || ((c >= 'A') && (c <= 'F')) || ((c >= 'a') && (c <= 'f'))) { - t._string += c; - c = eatAndPeekInputChar(); - } - - } else { - // Non-hex number - - // Read the part before the decimal. - while (isDigit(c)) { - t._string += c; - c = eatAndPeekInputChar(); - } - - // True if we are reading a floating-point special type - bool isSpecial = false; - - // Read the decimal, if one exists - if (c == '.') { - t._extendedType = Token::FLOATING_POINT_TYPE; - - // The '.' character was a decimal point, not the start of a - // method or range operator - t._string += c; - c = eatAndPeekInputChar(); - - // Floating point specials (msvc format only) - if (options.msvcSpecials && (c == '#')) { - isSpecial = true; - // We are reading a floating point special value - // of the form -1.#IND00, -1.#INF00, or 1.#INF00 - c = eatAndPeekInputChar(); - char test = c; - if (! options.caseSensitive) { - test = toupper(c); - } - if (test != 'I') { - throw BadMSVCSpecial - ( - "Incorrect floating-point special (inf or nan) " - "format.", - t.line(), charNumber); - } - c = eatAndPeekInputChar(); - test = c; - if (! options.caseSensitive) { - test = toupper(c); - } - if (test != 'N') { - throw BadMSVCSpecial - ( - "Incorrect floating-point special (inf or nan) " - "format.", - t.line(), charNumber); - } - t._string += "#IN"; - c = eatAndPeekInputChar(); - test = c; - if (! options.caseSensitive) { - test = toupper(c); - } - if ((test != 'F') && (test != 'D')) { - throw BadMSVCSpecial - ( - "Incorrect floating-point special (inf or nan) " - "format.", - t.line(), charNumber); - } - t._string += c; - for (int j = 0; j < 2; ++j) { - c = eatAndPeekInputChar(); - if (c != '0') { - throw BadMSVCSpecial - ( - "Incorrect floating-point special (inf or" - "nan) format.", - t.line(), charNumber); - } - t._string += (char)c; - } - - } else { - - // Read the part after the decimal - while (isDigit((char)c)) { - t._string += (char)c; - c = eatAndPeekInputChar(); - } - } - } - - if (! isSpecial && ((c == 'e') || (c == 'E'))) { - // Read exponent - t._extendedType = Token::FLOATING_POINT_TYPE; - t._string += c; - - c = eatAndPeekInputChar(); - if ((c == '-') || (c == '+')) { - t._string += c; - c = eatAndPeekInputChar(); - } - - while (isDigit(c)) { - t._string += c; - c = eatAndPeekInputChar(); - } - } - } - return t; - - } else if (isLetter(c) || (c == '_')) { - // Identifier or keyword - // [A-Za-z_][A-Za-z_0-9]* - - t._type = Token::SYMBOL; - t._extendedType = Token::SYMBOL_TYPE; - t._string = ""; - do { - t._string += c; - c = eatAndPeekInputChar(); - } while (isLetter(c) || isDigit(c) || (c == '_')); - - // See if this symbol is actually a boolean - if ((options.trueSymbols.size() > 0) || (options.falseSymbols.size() > 0)) { - std::string str = t._string; - if (! options.caseSensitive) { - str = toUpper(str); - } - if (options.trueSymbols.contains(str)) { - t._type = Token::BOOLEAN; - t._extendedType = Token::BOOLEAN_TYPE; - t._bool = true; - } else if (options.falseSymbols.contains(str)) { - t._type = Token::BOOLEAN; - t._extendedType = Token::BOOLEAN_TYPE; - t._bool = false; - } - } - - return t; - - } else if (c == '\"') { - - // Discard the double-quote. - eatInputChar(); - - // Double quoted string - parseQuotedString('\"', t); - return t; - - } else if (c == '\'') { - - // Discard the single-quote. - eatInputChar(); - - if (options.singleQuotedStrings) { - // Single quoted string - parseQuotedString('\'', t); - } else { - t._string = c; - t._type = Token::SYMBOL; - t._extendedType = Token::SYMBOL_TYPE; - } - return t; - - } // end of special case tokens - - if (c == EOF) { - t._type = Token::END; - t._extendedType = Token::END_TYPE; - t._string = ""; - return t; - } - - // Some unknown token - debugAssertM(false, - format("Unrecognized token type beginning with character '%c' (ASCII %d)", - c, c)); - return t; -} - - -void TextInput::parseQuotedString(unsigned char delimiter, Token& t) { - - t._type = Token::STRING; - - if (delimiter == '\'') { - t._extendedType = Token::SINGLE_QUOTED_TYPE; - } else { - t._extendedType = Token::DOUBLE_QUOTED_TYPE; - } - - while (true) { - // We're definitely going to consume the next input char, so we get - // it right now. This makes the condition handling below a bit easier. - int c = eatInputChar(); - - if (c == EOF) { - // END inside a quoted string. (We finish the string.) - break; - } - - if (options.escapeSequencesInStrings && (c == '\\')) { - // An escaped character. We're definitely going to consume it, - // so we get it (and consume it) now. - - c = eatInputChar(); - - switch (c) { - case 'r': - t._string += '\r'; - break; - case 'n': - t._string += '\n'; - break; - case 't': - t._string += '\t'; - break; - case '0': - t._string += '\0'; - break; - - case '\\': - case '\"': - case '\'': - t._string += (char)c; - break; - - default: - if (((c == options.otherCommentCharacter) && - (options.otherCommentCharacter != '\0')) || - ((c == options.otherCommentCharacter2) && - (options.otherCommentCharacter2 != '\0'))) { - t._string += c; - } - // otherwise, some illegal escape sequence; skip it. - break; - - } // switch - - } else if (c == delimiter) { - // End of the string. Already consumed the character. - break; - } else { - // All other chars, go on to the string. Already consumed the - // character. - t._string += (char)c; - } - - } -} - -bool TextInput::readBoolean() { - Token t(read()); - - if (t._type == Token::BOOLEAN) { - return t.boolean(); - } - - // Push initial token back, and throw an error. We intentionally - // indicate that the wrong type is the type of the initial token. - // Logically, the number started there. - push(t); - throw WrongTokenType(options.sourceFileName, t.line(), t.character(), - Token::BOOLEAN, t._type); -} - -double TextInput::readNumber() { - Token t(read()); - - if (t._type == Token::NUMBER) { - return t.number(); - } - - // Even if signedNumbers is disabled, readNumber attempts to - // read a signed number, so we handle that case here. - if (! options.signedNumbers - && (t._type == Token::SYMBOL) - && ((t._string == "-") - || (t._string == "+"))) { - - Token t2(read()); - - if ((t2._type == Token::NUMBER) - && (t2._character == t._character + 1)) { - - if (t._string == "-") { - return -t2.number(); - } else { - return t2.number(); - } - } - - // push back the second token. - push(t2); - } - - // Push initial token back, and throw an error. We intentionally - // indicate that the wrong type is the type of the initial token. - // Logically, the number started there. - push(t); - throw WrongTokenType(options.sourceFileName, t.line(), t.character(), - Token::NUMBER, t._type); -} - - -Token TextInput::readStringToken() { - Token t(read()); - - if (t._type == Token::STRING) { // fast path - return t; - } - - push(t); - throw WrongTokenType(options.sourceFileName, t.line(), t.character(), - Token::STRING, t._type); -} - -std::string TextInput::readString() { - return readStringToken()._string; -} - -void TextInput::readString(const std::string& s) { - Token t(readStringToken()); - - if (t._string == s) { // fast path - return; - } - - push(t); - throw WrongString(options.sourceFileName, t.line(), t.character(), - s, t._string); -} - - -Token TextInput::readSymbolToken() { - Token t(read()); - - if (t._type == Token::SYMBOL) { // fast path - return t; - } - - push(t); - throw WrongTokenType(options.sourceFileName, t.line(), t.character(), - Token::SYMBOL, t._type); -} - - -std::string TextInput::readSymbol() { - return readSymbolToken()._string; -} - -void TextInput::readSymbol(const std::string& symbol) { - Token t(readSymbolToken()); - - if (t._string == symbol) { // fast path - return; - } - - push(t); - throw WrongSymbol(options.sourceFileName, t.line(), t.character(), - symbol, t._string); -} - - -TextInput::TextInput(const std::string& filename, const Settings& opt) : options(opt) { - init(); - std::string input = readWholeFile(filename); - - if (options.sourceFileName.empty()) { - options.sourceFileName = filename; - } - int n = input.size(); - buffer.resize(n); - System::memcpy(buffer.getCArray(), input.c_str(), n); -} - - -TextInput::TextInput(FS fs, const std::string& str, const Settings& opt) : options(opt) { - (void)fs; - init(); - if (options.sourceFileName.empty()) { - if (str.length() < 14) { - options.sourceFileName = std::string("\"") + str + "\""; - } else { - options.sourceFileName = std::string("\"") + str.substr(0, 10) + "...\""; - } - } - buffer.resize(str.length()); // we don't bother copying trailing NUL. - System::memcpy(buffer.getCArray(), str.c_str(), buffer.size()); -} - - -const std::string& TextInput::filename() const { - return options.sourceFileName; -} - -/////////////////////////////////////////////////////////////////////////////////// - -TextInput::TokenException::TokenException( - const std::string& src, - int ln, - int ch) : sourceFile(src), line(ln), character(ch) { - - message = format("%s(%d) : ", sourceFile.c_str(), line); -} - -/////////////////////////////////////////////////////////////////////////////////// - -static const char* tokenTypeToString(Token::Type t) { - switch (t) { - case Token::SYMBOL: - return "Token::SYMBOL"; - case Token::STRING: - return "Token::STRING"; - case Token::NUMBER: - return "Token::NUMBER"; - case Token::END: - return "Token::END"; - default: - debugAssertM(false, "Fell through switch"); - return "?"; - } -} - -TextInput::WrongTokenType::WrongTokenType( - const std::string& src, - int ln, - int ch, - Token::Type e, - Token::Type a) : - TokenException(src, ln, ch), expected(e), actual(a) { - - message += format("Expected token of type %s, found type %s.", - tokenTypeToString(e), tokenTypeToString(a)); -} - - -TextInput::BadMSVCSpecial::BadMSVCSpecial( - const std::string& src, - int ln, - int ch) : - TokenException(src, ln, ch) { -} - - -TextInput::WrongSymbol::WrongSymbol( - const std::string& src, - int ln, - int ch, - const std::string& e, - const std::string& a) : - TokenException(src, ln, ch), expected(e), actual(a) { - - message += format("Expected symbol '%s', found symbol '%s'.", - e.c_str(), a.c_str()); -} - - -TextInput::WrongString::WrongString( - const std::string& src, - int ln, - int ch, - const std::string& e, - const std::string& a) : - TokenException(src, ln, ch), expected(e), actual(a) { - - message += format("Expected string '%s', found string '%s'.", - e.c_str(), a.c_str()); -} - - -void deserialize(bool& b, TextInput& ti) { - b = ti.readSymbol() == "true"; -} - - -void deserialize(int& b, TextInput& ti) { - b = iRound(ti.readNumber()); -} - - -void deserialize(uint8& b, TextInput& ti) { - b = (uint8)iRound(ti.readNumber()); -} - - -void deserialize(double& b, TextInput& ti) { - b = ti.readNumber(); -} - - -void deserialize(float& b, TextInput& ti) { - b = (float)ti.readNumber(); -} - -} // namespace - -#ifdef _MSC_VER -# pragma warning (pop) -#endif diff --git a/externals/g3dlite/G3D.lib/source/TextOutput.cpp b/externals/g3dlite/G3D.lib/source/TextOutput.cpp deleted file mode 100644 index f7a40d9798b..00000000000 --- a/externals/g3dlite/G3D.lib/source/TextOutput.cpp +++ /dev/null @@ -1,452 +0,0 @@ -/** - @file TextOutput.cpp - - @maintainer Morgan McGuire, morgan@graphics3d.com - @created 2004-06-21 - @edited 2006-08-14 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#include "G3D/TextOutput.h" -#include "G3D/Log.h" -#include "G3D/fileutils.h" - -namespace G3D { - -TextOutput::TextOutput(const TextOutput::Settings& opt) : - startingNewLine(true), - currentColumn(0), - inDQuote(false), - filename(""), - indentLevel(0) -{ - setOptions(opt); -} - - -TextOutput::TextOutput(const std::string& fil, const TextOutput::Settings& opt) : - startingNewLine(true), - currentColumn(0), - inDQuote(false), - filename(fil), - indentLevel(0) -{ - - setOptions(opt); -} - - -void TextOutput::setIndentLevel(int i) { - indentLevel = i; - - // If there were more pops than pushes, don't let that take us below 0 indent. - // Don't ever indent more than the number of columns. - indentSpaces = - iClamp(option.spacesPerIndent * indentLevel, - 0, - option.numColumns - 1); -} - - -void TextOutput::setOptions(const Settings& _opt) { - option = _opt; - - debugAssert(option.numColumns > 1); - - setIndentLevel(indentLevel); - - newline = (option.newlineStyle == Settings::NEWLINE_WINDOWS) ? "\r\n" : "\n"; -} - - -void TextOutput::pushIndent() { - setIndentLevel(indentLevel + 1); -} - - -void TextOutput::popIndent() { - setIndentLevel(indentLevel - 1); -} - - -static std::string escape(const std::string& string) { - std::string result = ""; - - for (std::string::size_type i = 0; i < string.length(); ++i) { - char c = string.at(i); - switch (c) { - case '\0': - result += "\\0"; - break; - - case '\r': - result += "\\r"; - break; - - case '\n': - result += "\\n"; - break; - - case '\t': - result += "\\t"; - break; - - case '\\': - result += "\\\\"; - break; - - default: - result += c; - } - } - - return result; -} - -void TextOutput::writeString(const std::string& string) { - // Convert special characters to escape sequences - this->printf("\"%s\"", escape(string).c_str()); -} - - -void TextOutput::writeBoolean(bool b) { - this->printf("%s ", b ? option.trueSymbol.c_str() : option.falseSymbol.c_str()); -} - -void TextOutput::writeNumber(double n) { - this->printf("%f ", n); -} - - -void TextOutput::writeNumber(int n) { - this->printf("%d ", n); -} - - -void TextOutput::writeSymbol(const std::string& string) { - if (string.size() > 0) { - // TODO: check for legal symbols? - this->printf("%s ", string.c_str()); - } -} - -void TextOutput::writeSymbols( - const std::string& a, - const std::string& b, - const std::string& c, - const std::string& d, - const std::string& e, - const std::string& f) { - - writeSymbol(a); - writeSymbol(b); - writeSymbol(c); - writeSymbol(d); - writeSymbol(e); - writeSymbol(f); -} - - -void TextOutput::printf(const std::string formatString, ...) { - va_list argList; - va_start(argList, formatString); - this->vprintf(formatString.c_str(), argList); - va_end(argList); -} - - -void TextOutput::printf(const char* formatString, ...) { - va_list argList; - va_start(argList, formatString); - this->vprintf(formatString, argList); - va_end(argList); -} - - -void TextOutput::convertNewlines(const std::string& in, std::string& out) { - // TODO: can be significantly optimized in cases where - // single characters are copied in order by walking through - // the array and copying substrings as needed. - - if (option.convertNewlines) { - out = ""; - for (uint32 i = 0; i < in.size(); ++i) { - if (in[i] == '\n') { - // Unix newline - out += newline; - } else if ((in[i] == '\r') && (i + 1 < in.size()) && (in[i + 1] == '\n')) { - // Windows newline - out += newline; - ++i; - } else { - out += in[i]; - } - } - } else { - out = in; - } -} - - -void TextOutput::writeNewline() { - for (uint32 i = 0; i < newline.size(); ++i) { - indentAppend(newline[i]); - } -} - - -void TextOutput::writeNewlines(int numLines) { - for (int i = 0; i < numLines; ++i) { - writeNewline(); - } -} - - -void TextOutput::wordWrapIndentAppend(const std::string& str) { - // TODO: keep track of the last space character we saw so we don't - // have to always search. - - if ((option.wordWrap == Settings::WRAP_NONE) || - (currentColumn + (int)str.size() <= option.numColumns)) { - // No word-wrapping is needed - - // Add one character at a time. - // TODO: optimize for strings without newlines to add multiple - // characters. - for (uint32 i = 0; i < str.size(); ++i) { - indentAppend(str[i]); - } - return; - } - - // Number of columns to wrap against - int cols = option.numColumns - indentSpaces; - - // Copy forward until we exceed the column size, - // and then back up and try to insert newlines as needed. - for (uint32 i = 0; i < str.size(); ++i) { - - indentAppend(str[i]); - if ((str[i] == '\r') && (i + 1 < str.size()) && (str[i + 1] == '\n')) { - // \r\n, we need to hit the \n to enter word wrapping. - ++i; - indentAppend(str[i]); - } - - if (currentColumn >= cols) { - debugAssertM(str[i] != '\n' && str[i] != '\r', - "Should never enter word-wrapping on a newline character"); - - // True when we're allowed to treat a space as a space. - bool unquotedSpace = option.allowWordWrapInsideDoubleQuotes || ! inDQuote; - - // Cases: - // - // 1. Currently in a series of spaces that ends with a newline - // strip all spaces and let the newline - // flow through. - // - // 2. Currently in a series of spaces that does not end with a newline - // strip all spaces and replace them with single newline - // - // 3. Not in a series of spaces - // search backwards for a space, then execute case 2. - - // Index of most recent space - uint32 lastSpace = data.size() - 1; - - // How far back we had to look for a space - uint32 k = 0; - uint32 maxLookBackward = currentColumn - indentSpaces; - - // Search backwards (from current character), looking for a space. - while ((k < maxLookBackward) && - (lastSpace > 0) && - (! ((data[lastSpace] == ' ') && unquotedSpace))) { - --lastSpace; - ++k; - - if ((data[lastSpace] == '\"') && !option.allowWordWrapInsideDoubleQuotes) { - unquotedSpace = ! unquotedSpace; - } - } - - if (k == maxLookBackward) { - // We couldn't find a series of spaces - - if (option.wordWrap == Settings::WRAP_ALWAYS) { - // Strip the last character we wrote, force a newline, - // and replace the last character; - data.pop(); - writeNewline(); - indentAppend(str[i]); - } else { - // Must be Settings::WRAP_WITHOUT_BREAKING - // - // Don't write the newline; we'll come back to - // the word wrap code after writing another character - } - } else { - // We found a series of spaces. If they continue - // to the new string, strip spaces off both. Otherwise - // strip spaces from data only and insert a newline. - - // Find the start of the spaces. firstSpace is the index of the - // first non-space, looking backwards from lastSpace. - uint32 firstSpace = lastSpace; - while ((k < maxLookBackward) && - (firstSpace > 0) && - (data[firstSpace] == ' ')) { - --firstSpace; - ++k; - } - - if (k == maxLookBackward) { - ++firstSpace; - } - - if (lastSpace == (uint32)data.size() - 1) { - // Spaces continued up to the new string - data.resize(firstSpace + 1); - writeNewline(); - - // Delete the spaces from the new string - while ((i < str.size() - 1) && (str[i + 1] == ' ')) { - ++i; - } - } else { - // Spaces were somewhere in the middle of the old string. - // replace them with a newline. - - // Copy over the characters that should be saved - Array temp; - for (uint32 j = lastSpace + 1; j < (uint32)data.size(); ++j) { - char c = data[j]; - - if (c == '\"') { - // Undo changes to quoting (they will be re-done - // when we paste these characters back on). - inDQuote = !inDQuote; - } - temp.append(c); - } - - // Remove those characters and replace with a newline. - data.resize(firstSpace + 1); - writeNewline(); - - // Write them back - for (uint32 j = 0; j < (uint32)temp.size(); ++j) { - indentAppend(temp[j]); - } - - // We are now free to continue adding from the - // new string, which may or may not begin with spaces. - - } // if spaces included new string - } // if hit indent - } // if line exceeded - } // iterate over str -} - - -void TextOutput::indentAppend(char c) { - - if (startingNewLine) { - for (int j = 0; j < indentSpaces; ++j) { - data.push(' '); - } - startingNewLine = false; - currentColumn = indentSpaces; - } - - data.push(c); - - // Don't increment the column count on return character - // newline is taken care of below. - if (c != '\r') { - ++currentColumn; - } - - if (c == '\"') { - inDQuote = ! inDQuote; - } - - startingNewLine = (c == '\n'); - if (startingNewLine) { - currentColumn = 0; - } -} - - -void TextOutput::vprintf(const char* formatString, va_list argPtr) { - std::string str = vformat(formatString, argPtr); - - std::string clean; - convertNewlines(str, clean); - wordWrapIndentAppend(clean); -} - - -void TextOutput::commit(bool flush) { - std::string p = filenamePath(filename); - if (! fileExists(p, false)) { - createDirectory(p); - } - - FILE* f = fopen(filename.c_str(), "wb"); - debugAssert(f); - fwrite(data.getCArray(), 1, data.size(), f); - if (flush) { - fflush(f); - } - fclose(f); -} - - -void TextOutput::commitString(std::string& out) { - // Null terminate - data.push('\0'); - out = data.getCArray(); - data.pop(); -} - - -std::string TextOutput::commitString() { - std::string str; - commitString(str); - return str; -} - - - -///////////////////////////////////////////////////////////////////// - -void serialize(const float& b, TextOutput& to) { - to.writeNumber(b); -} - - -void serialize(const bool& b, TextOutput& to) { - to.writeSymbol(b ? "true" : "false"); -} - - -void serialize(const int& b, TextOutput& to) { - to.writeNumber(b); -} - - -void serialize(const uint8& b, TextOutput& to) { - to.writeNumber(b); -} - - -void serialize(const double& b, TextOutput& to) { - to.writeNumber(b); -} - - -} diff --git a/externals/g3dlite/G3D.lib/source/ThreadSet.cpp b/externals/g3dlite/G3D.lib/source/ThreadSet.cpp deleted file mode 100644 index 59060892247..00000000000 --- a/externals/g3dlite/G3D.lib/source/ThreadSet.cpp +++ /dev/null @@ -1,147 +0,0 @@ -#include "G3D/ThreadSet.h" - -namespace G3D { - -int ThreadSet::size() const { - ThreadSet* me = const_cast(this); - me->m_lock.lock(); - int s = m_thread.size(); - me->m_lock.unlock(); - return s; -} - - -int ThreadSet::numStarted() const { - ThreadSet* me = const_cast(this); - me->m_lock.lock(); - int count = 0; - for (int i = 0; i < m_thread.size(); ++i) { - if (m_thread[i]->started()) { - ++count; - } - } - me->m_lock.unlock(); - return count; -} - - -void ThreadSet::start() const { - ThreadSet* me = const_cast(this); - me->m_lock.lock(); - for (int i = 0; i < m_thread.size(); ++i) { - if (! m_thread[i]->started()) { - m_thread[i]->start(); - } - } - me->m_lock.unlock(); -} - - -void ThreadSet::terminate() const { - ThreadSet* me = const_cast(this); - me->m_lock.lock(); - for (int i = 0; i < m_thread.size(); ++i) { - if (m_thread[i]->started()) { - m_thread[i]->terminate(); - } - } - me->m_lock.unlock(); -} - - -void ThreadSet::waitForCompletion() const { - ThreadSet* me = const_cast(this); - me->m_lock.lock(); - for (int i = 0; i < m_thread.size(); ++i) { - if (m_thread[i]->started()) { - m_thread[i]->waitForCompletion(); - } - } - me->m_lock.unlock(); -} - - -int ThreadSet::removeCompleted() { - m_lock.lock(); - for (int i = 0; i < m_thread.size(); ++i) { - if (m_thread[i]->completed()) { - m_thread.fastRemove(i); - --i; - } - } - - int s = m_thread.size(); - m_lock.unlock(); - return s; -} - - -void ThreadSet::clear() { - m_lock.lock(); - m_thread.clear(); - m_lock.unlock(); -} - - -int ThreadSet::insert(const ThreadRef& t) { - m_lock.lock(); - bool found = false; - for (int i = 0; i < m_thread.size() && ! found; ++i) { - found = (m_thread[i] == t); - } - if (! found) { - m_thread.append(t); - } - int s = m_thread.size(); - m_lock.unlock(); - return s; -} - - -bool ThreadSet::remove(const ThreadRef& t) { - m_lock.lock(); - bool found = false; - for (int i = 0; i < m_thread.size() && ! found; ++i) { - found = (m_thread[i] == t); - if (found) { - m_thread.fastRemove(i); - } - } - m_lock.unlock(); - return found; -} - - -bool ThreadSet::contains(const ThreadRef& t) const { - ThreadSet* me = const_cast(this); - me->m_lock.lock(); - bool found = false; - for (int i = 0; i < m_thread.size() && ! found; ++i) { - found = (m_thread[i] == t); - } - me->m_lock.unlock(); - return found; -} - - -ThreadSet::Iterator ThreadSet::begin() { - return m_thread.begin(); -} - - -ThreadSet::Iterator ThreadSet::end() { - return m_thread.end(); -} - - -ThreadSet::ConstIterator ThreadSet::begin() const { - return m_thread.begin(); -} - - -ThreadSet::ConstIterator ThreadSet::end() const { - return m_thread.end(); -} - - -} // namespace G3D diff --git a/externals/g3dlite/G3D.lib/source/Triangle.cpp b/externals/g3dlite/G3D.lib/source/Triangle.cpp deleted file mode 100644 index ad264b1f72a..00000000000 --- a/externals/g3dlite/G3D.lib/source/Triangle.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/** - @file Triangle.cpp - - @maintainer Morgan McGuire, graphics3d.com - - @created 2001-04-06 - @edited 2006-01-20 - - Copyright 2000-2006, Morgan McGuire. - All rights reserved. - */ - -#include "G3D/platform.h" -#include "G3D/Triangle.h" -#include "G3D/Plane.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/debugAssert.h" -#include "G3D/AABox.h" - -namespace G3D { - - -void Triangle::init(const Vector3& v0, const Vector3& v1, const Vector3& v2) { - - _plane = Plane(v0, v1, v2); - _vertex[0] = v0; - _vertex[1] = v1; - _vertex[2] = v2; - - static int next[] = {1,2,0}; - - for (int i = 0; i < 3; ++i) { - const Vector3& e = _vertex[next[i]] - _vertex[i]; - edgeMagnitude[i] = e.magnitude(); - - if (edgeMagnitude[i] == 0) { - edgeDirection[i] = Vector3::zero(); - } else { - edgeDirection[i] = e / (float)edgeMagnitude[i]; - } - } - - _edge01 = _vertex[1] - _vertex[0]; - _edge02 = _vertex[2] - _vertex[0]; - - _primaryAxis = _plane.normal().primaryAxis(); - _area = 0.5f * edgeDirection[0].cross(edgeDirection[2]).magnitude() * (edgeMagnitude[0] * edgeMagnitude[2]); - //0.5f * (_vertex[1] - _vertex[0]).cross(_vertex[2] - _vertex[0]).dot(_plane.normal()); -} - - -Triangle::Triangle() { - init(Vector3::zero(), Vector3::zero(), Vector3::zero()); -} - - -Triangle::Triangle(const Vector3& v0, const Vector3& v1, const Vector3& v2) { - init(v0, v1, v2); -} - - -Triangle::~Triangle() { -} - - -Triangle::Triangle(class BinaryInput& b) { - deserialize(b); -} - - -void Triangle::serialize(class BinaryOutput& b) { - _vertex[0].serialize(b); - _vertex[1].serialize(b); - _vertex[2].serialize(b); -} - - -void Triangle::deserialize(class BinaryInput& b) { - _vertex[0].deserialize(b); - _vertex[1].deserialize(b); - _vertex[2].deserialize(b); - init(_vertex[0], _vertex[1], _vertex[2]); -} - - -float Triangle::area() const { - return _area; -} - - -const Vector3& Triangle::normal() const { - return _plane.normal(); -} - - -const Plane& Triangle::plane() const { - return _plane; -} - - -Vector3 Triangle::center() const { - return (_vertex[0] + _vertex[1] + _vertex[2]) / 3.0; -} - -Vector3 Triangle::randomPoint() const { - // Choose a random point in the parallelogram - - float s = uniformRandom(); - float t = uniformRandom(); - - if (t > 1.0f - s) { - // Outside the triangle; reflect about the - // diagonal of the parallelogram - t = 1.0f - t; - s = 1.0f - s; - } - - return _edge01 * s + _edge02 * t + _vertex[0]; -} - - -void Triangle::getBounds(AABox& out) const { - Vector3 lo = _vertex[0]; - Vector3 hi = lo; - - for (int i = 1; i < 3; ++i) { - lo = lo.min(_vertex[i]); - hi = hi.max(_vertex[i]); - } - - out = AABox(lo, hi); -} - -} // G3D diff --git a/externals/g3dlite/G3D.lib/source/UprightFrame.cpp b/externals/g3dlite/G3D.lib/source/UprightFrame.cpp deleted file mode 100644 index 78b2c0bb0bb..00000000000 --- a/externals/g3dlite/G3D.lib/source/UprightFrame.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/** - @file UprightFrame.cpp - Box class - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-05-02 - @edited 2007-05-05 -*/ - -#include "G3D/UprightFrame.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - -namespace G3D { - -UprightFrame::UprightFrame(const CoordinateFrame& cframe) { - Vector3 look = cframe.lookVector(); - - yaw = G3D::pi() + atan2(look.x, look.z); - pitch = asin(look.y); - - translation = cframe.translation; -} - - -CoordinateFrame UprightFrame::toCoordinateFrame() const { - CoordinateFrame cframe; - - Matrix3 P(Matrix3::fromAxisAngle(Vector3::unitX(), pitch)); - Matrix3 Y(Matrix3::fromAxisAngle(Vector3::unitY(), yaw)); - - cframe.rotation = Y * P; - cframe.translation = translation; - - return cframe; -} - - -UprightFrame UprightFrame::operator+(const UprightFrame& other) const { - return UprightFrame(translation + other.translation, pitch + other.pitch, yaw + other.yaw); -} - - -UprightFrame UprightFrame::operator*(const float k) const { - return UprightFrame(translation * k, pitch * k, yaw * k); -} - - -void UprightFrame::unwrapYaw(UprightFrame* a, int N) { - // Use the first point to establish the wrapping convention - for (int i = 1; i < N; ++i) { - const float prev = a[i - 1].yaw; - float& cur = a[i].yaw; - - // No two angles should be more than pi (i.e., 180-degrees) apart. - if (abs(cur - prev) > G3D::pi()) { - // These angles must have wrapped at zero, causing them - // to be interpolated the long way. - - // Find canonical [0, 2pi] versions of these numbers - float p = wrap(prev, twoPi()); - float c = wrap(cur, twoPi()); - - // Find the difference -pi < diff < pi between the current and previous values - float diff = c - p; - if (diff < -G3D::pi()) { - diff += twoPi(); - } else if (diff > G3D::pi()) { - diff -= twoPi(); - } - - // Offset the current from the previous by the difference - // between them. - cur = prev + diff; - } - } -} - - -void UprightFrame::serialize(class BinaryOutput& b) const { - translation.serialize(b); - b.writeFloat32(pitch); - b.writeFloat32(yaw); -} - - -void UprightFrame::deserialize(class BinaryInput& b) { - translation.deserialize(b); - pitch = b.readFloat32(); - yaw = b.readFloat32(); -} - - -void UprightSpline::serialize(class BinaryOutput& b) const { - b.writeBool8(cyclic); - - b.writeInt32(control.size()); - for (int i = 0; i < control.size(); ++i) { - control[i].serialize(b); - } - b.writeInt32(time.size()); - for (int i = 0; i < time.size(); ++i) { - b.writeFloat32(time[i]); - } -} - - -void UprightSpline::deserialize(class BinaryInput& b) { - cyclic = b.readBool8(); - - control.resize(b.readInt32()); - for (int i = 0; i < control.size(); ++i) { - control[i].deserialize(b); - } - - if (b.hasMore()) { - time.resize(b.readInt32()); - for (int i = 0; i < time.size(); ++i) { - time[i] = b.readFloat32(); - } - debugAssert(time.size() == control.size()); - } else { - // Import legacy path - time.resize(control.size()); - for (int i = 0; i < time.size(); ++i) { - time[i] = i; - } - } -} - -} diff --git a/externals/g3dlite/G3D.lib/source/Vector2.cpp b/externals/g3dlite/G3D.lib/source/Vector2.cpp deleted file mode 100644 index 6b7f96a764e..00000000000 --- a/externals/g3dlite/G3D.lib/source/Vector2.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/** - @file Vector2.cpp - - 2D vector class, used for texture coordinates primarily. - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @cite Portions based on Dave Eberly'x Magic Software Library - at http://www.magic-software.com - - @created 2001-06-02 - @edited 2006-01-16 - */ - -#include "G3D/platform.h" -#include -#include "G3D/Vector2.h" -#include "G3D/g3dmath.h" -#include "G3D/format.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/TextInput.h" -#include "G3D/TextOutput.h" - -namespace G3D { - -const Vector2& Vector2::zero() { - static Vector2 v(0, 0); - return v; -} - -const Vector2& Vector2::unitX() { - static Vector2 v(1, 0); - return v; -} - -const Vector2& Vector2::unitY() { - static Vector2 v(0, 1); - return v; -} - -const Vector2& Vector2::inf() { - static Vector2 v((float)G3D::inf(), (float)G3D::inf()); - return v; -} - - -const Vector2& Vector2::nan() { - static Vector2 v((float)G3D::nan(), (float)G3D::nan()); - return v; -} - - -const Vector2& Vector2::minFinite() { - static Vector2 v(-FLT_MAX, -FLT_MAX); - return v; -} - - -const Vector2& Vector2::maxFinite() { - static Vector2 v(FLT_MAX, FLT_MAX); - return v; -} - - -size_t Vector2::hashCode() const { - unsigned int xhash = (*(int*)(void*)(&x)); - unsigned int yhash = (*(int*)(void*)(&y)); - - return xhash + (yhash * 37); -} - - -Vector2::Vector2(BinaryInput& b) { - deserialize(b); -} - - -void Vector2::deserialize(BinaryInput& b) { - x = b.readFloat32(); - y = b.readFloat32(); -} - - -void Vector2::serialize(BinaryOutput& b) const { - b.writeFloat32(x); - b.writeFloat32(y); -} - - -void Vector2::deserialize(TextInput& t) { - t.readSymbol("("); - x = (float)t.readNumber(); - t.readSymbol(","); - y = (float)t.readNumber(); - t.readSymbol(")"); -} - - -void Vector2::serialize(TextOutput& t) const { - t.writeSymbol("("); - t.writeNumber(x); - t.writeSymbol(","); - t.writeNumber(y); - t.writeSymbol(")"); -} - -//---------------------------------------------------------------------------- - -Vector2 Vector2::random() { - Vector2 result; - - do { - result = Vector2(uniformRandom(-1, 1), uniformRandom(-1, 1)); - - } while (result.squaredLength() >= 1.0f); - - result.unitize(); - - return result; -} - -//---------------------------------------------------------------------------- -Vector2 Vector2::operator/ (float fScalar) const { - Vector2 kQuot; - - if ( fScalar != 0.0f ) { - float fInvScalar = 1.0f / fScalar; - kQuot.x = fInvScalar * x; - kQuot.y = fInvScalar * y; - return kQuot; - } else { - return Vector2::inf(); - } -} - -//---------------------------------------------------------------------------- -Vector2& Vector2::operator/= (float fScalar) { - if (fScalar != 0.0f) { - float fInvScalar = 1.0f / fScalar; - x *= fInvScalar; - y *= fInvScalar; - } else { - x = (float)G3D::inf(); - y = (float)G3D::inf(); - } - - return *this; -} - -//---------------------------------------------------------------------------- -float Vector2::unitize (float fTolerance) { - float fLength = length(); - - if (fLength > fTolerance) { - float fInvLength = 1.0f / fLength; - x *= fInvLength; - y *= fInvLength; - } else { - fLength = 0.0; - } - - return fLength; -} - -//---------------------------------------------------------------------------- - -std::string Vector2::toString() const { - return G3D::format("(%g, %g)", x, y); -} - -// 2-char swizzles - -Vector2 Vector2::xx() const { return Vector2 (x, x); } -Vector2 Vector2::yx() const { return Vector2 (y, x); } -Vector2 Vector2::xy() const { return Vector2 (x, y); } -Vector2 Vector2::yy() const { return Vector2 (y, y); } - -// 3-char swizzles - -Vector3 Vector2::xxx() const { return Vector3 (x, x, x); } -Vector3 Vector2::yxx() const { return Vector3 (y, x, x); } -Vector3 Vector2::xyx() const { return Vector3 (x, y, x); } -Vector3 Vector2::yyx() const { return Vector3 (y, y, x); } -Vector3 Vector2::xxy() const { return Vector3 (x, x, y); } -Vector3 Vector2::yxy() const { return Vector3 (y, x, y); } -Vector3 Vector2::xyy() const { return Vector3 (x, y, y); } -Vector3 Vector2::yyy() const { return Vector3 (y, y, y); } - -// 4-char swizzles - -Vector4 Vector2::xxxx() const { return Vector4 (x, x, x, x); } -Vector4 Vector2::yxxx() const { return Vector4 (y, x, x, x); } -Vector4 Vector2::xyxx() const { return Vector4 (x, y, x, x); } -Vector4 Vector2::yyxx() const { return Vector4 (y, y, x, x); } -Vector4 Vector2::xxyx() const { return Vector4 (x, x, y, x); } -Vector4 Vector2::yxyx() const { return Vector4 (y, x, y, x); } -Vector4 Vector2::xyyx() const { return Vector4 (x, y, y, x); } -Vector4 Vector2::yyyx() const { return Vector4 (y, y, y, x); } -Vector4 Vector2::xxxy() const { return Vector4 (x, x, x, y); } -Vector4 Vector2::yxxy() const { return Vector4 (y, x, x, y); } -Vector4 Vector2::xyxy() const { return Vector4 (x, y, x, y); } -Vector4 Vector2::yyxy() const { return Vector4 (y, y, x, y); } -Vector4 Vector2::xxyy() const { return Vector4 (x, x, y, y); } -Vector4 Vector2::yxyy() const { return Vector4 (y, x, y, y); } -Vector4 Vector2::xyyy() const { return Vector4 (x, y, y, y); } -Vector4 Vector2::yyyy() const { return Vector4 (y, y, y, y); } - - - -} // namespace diff --git a/externals/g3dlite/G3D.lib/source/Vector2int16.cpp b/externals/g3dlite/G3D.lib/source/Vector2int16.cpp deleted file mode 100644 index 04efee2b4b7..00000000000 --- a/externals/g3dlite/G3D.lib/source/Vector2int16.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - @file Vector2int16.cpp - - @author Morgan McGuire, matrix@graphics3d.com - - @created 2003-08-09 - @edited 2006-01-29 - */ - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Vector2int16.h" -#include "G3D/Vector2.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" - -namespace G3D { - -Vector2int16::Vector2int16(const class Vector2& v) { - x = (int16)iFloor(v.x + 0.5); - y = (int16)iFloor(v.y + 0.5); -} - - -Vector2int16::Vector2int16(class BinaryInput& bi) { - deserialize(bi); -} - - -void Vector2int16::serialize(class BinaryOutput& bo) const { - bo.writeInt16(x); - bo.writeInt16(y); -} - - -void Vector2int16::deserialize(class BinaryInput& bi) { - x = bi.readInt16(); - y = bi.readInt16(); -} - - -Vector2int16 Vector2int16::clamp(const Vector2int16& lo, const Vector2int16& hi) { - return Vector2int16(iClamp(x, lo.x, hi.x), iClamp(y, lo.y, hi.y)); -} - - -} diff --git a/externals/g3dlite/G3D.lib/source/Vector3.cpp b/externals/g3dlite/G3D.lib/source/Vector3.cpp deleted file mode 100644 index bc52640d297..00000000000 --- a/externals/g3dlite/G3D.lib/source/Vector3.cpp +++ /dev/null @@ -1,493 +0,0 @@ -/** - @file Vector3.cpp - - 3D vector class - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com - - @created 2001-06-02 - @edited 2006-01-30 - */ - -#include -#include -#include "G3D/Vector3.h" -#include "G3D/g3dmath.h" -#include "G3D/stringutils.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/TextInput.h" -#include "G3D/TextOutput.h" -#include "G3D/Vector3int16.h" -#include "G3D/Matrix3.h" -#include "G3D/Vector2.h" -#include "G3D/Vector4int8.h" - -namespace G3D { - -Vector3 Vector3::dummy; - - -Vector3::Vector3(const Vector4int8& v) : x(v.x / 127.0f), y(v.y / 127.0f), z(v.z / 127.0f) {} - -Vector3::Vector3(const class Vector2& v, float _z) : x(v.x), y(v.y), z(_z) { -} - - -Vector3::Axis Vector3::primaryAxis() const { - - Axis a = X_AXIS; - - double nx = abs(x); - double ny = abs(y); - double nz = abs(z); - - if (nx > ny) { - if (nx > nz) { - a = X_AXIS; - } else { - a = Z_AXIS; - } - } else { - if (ny > nz) { - a = Y_AXIS; - } else { - a = Z_AXIS; - } - } - - return a; -} - - -size_t Vector3::hashCode() const { - unsigned int xhash = (*(int*)(void*)(&x)); - unsigned int yhash = (*(int*)(void*)(&y)); - unsigned int zhash = (*(int*)(void*)(&z)); - - return xhash + (yhash * 37) + (zhash * 101); -} - -std::ostream& operator<<(std::ostream& os, const Vector3& v) { - return os << v.toString(); -} - - -//---------------------------------------------------------------------------- - -double frand() { - return rand() / (double) RAND_MAX; -} - -Vector3::Vector3(TextInput& t) { - deserialize(t); -} - -Vector3::Vector3(BinaryInput& b) { - deserialize(b); -} - - -Vector3::Vector3(const class Vector3int16& v) { - x = v.x; - y = v.y; - z = v.z; -} - - -void Vector3::deserialize(BinaryInput& b) { - x = b.readFloat32(); - y = b.readFloat32(); - z = b.readFloat32(); -} - - -void Vector3::deserialize(TextInput& t) { - t.readSymbol("("); - x = (float)t.readNumber(); - t.readSymbol(","); - y = (float)t.readNumber(); - t.readSymbol(","); - z = (float)t.readNumber(); - t.readSymbol(")"); -} - - -void Vector3::serialize(TextOutput& t) const { - t.writeSymbol("("); - t.writeNumber(x); - t.writeSymbol(","); - t.writeNumber(y); - t.writeSymbol(","); - t.writeNumber(z); - t.writeSymbol(")"); -} - - -void Vector3::serialize(BinaryOutput& b) const { - b.writeFloat32(x); - b.writeFloat32(y); - b.writeFloat32(z); -} - - -Vector3 Vector3::random() { - Vector3 result; - - do { - result = Vector3(uniformRandom(-1.0, 1.0), - uniformRandom(-1.0, 1.0), - uniformRandom(-1.0, 1.0)); - } while (result.squaredMagnitude() >= 1.0f); - - result.unitize(); - - return result; -} - -//---------------------------------------------------------------------------- -Vector3 Vector3::operator/ (float fScalar) const { - Vector3 kQuot; - - if ( fScalar != 0.0 ) { - float fInvScalar = 1.0f / fScalar; - kQuot.x = fInvScalar * x; - kQuot.y = fInvScalar * y; - kQuot.z = fInvScalar * z; - return kQuot; - } else { - return Vector3::inf(); - } -} - -//---------------------------------------------------------------------------- -Vector3& Vector3::operator/= (float fScalar) { - if (fScalar != 0.0) { - float fInvScalar = 1.0f / fScalar; - x *= fInvScalar; - y *= fInvScalar; - z *= fInvScalar; - } else { - x = (float)G3D::inf(); - y = (float)G3D::inf(); - z = (float)G3D::inf(); - } - - return *this; -} - -//---------------------------------------------------------------------------- -float Vector3::unitize (float fTolerance) { - float fMagnitude = magnitude(); - - if (fMagnitude > fTolerance) { - float fInvMagnitude = 1.0f / fMagnitude; - x *= fInvMagnitude; - y *= fInvMagnitude; - z *= fInvMagnitude; - } else { - fMagnitude = 0.0f; - } - - return fMagnitude; -} - -//---------------------------------------------------------------------------- - -Vector3 Vector3::reflectAbout(const Vector3& normal) const { - - Vector3 out; - - Vector3 N = normal.direction(); - - // 2 * normal.dot(this) * normal - this - return N * 2 * this->dot(N) - *this; -} - -//---------------------------------------------------------------------------- -Vector3 Vector3::cosRandom(const Vector3& normal) { - double e1 = G3D::uniformRandom(0, 1); - double e2 = G3D::uniformRandom(0, 1); - - // Angle from normal - double theta = acos(sqrt(e1)); - - // Angle about normal - double phi = 2 * pi() * e2; - - // Make a coordinate system - Vector3 U = normal.direction(); - Vector3 V = Vector3::unitX(); - - if (abs(U.dot(V)) > .9) { - V = Vector3::unitY(); - } - - Vector3 W = U.cross(V).direction(); - V = W.cross(U); - - // Convert to rectangular form - return cos(theta) * U + sin(theta) * (cos(phi) * V + sin(phi) * W); -} -//---------------------------------------------------------------------------- - -Vector3 Vector3::hemiRandom(const Vector3& normal) { - Vector3 V = Vector3::random(); - - if (V.dot(normal) < 0) { - return -V; - } else { - return V; - } -} - -//---------------------------------------------------------------------------- - -Vector3 Vector3::reflectionDirection(const Vector3& normal) const { - return -reflectAbout(normal).direction(); -} - -//---------------------------------------------------------------------------- - -Vector3 Vector3::refractionDirection( - const Vector3& normal, - float iInside, - float iOutside) const { - - // From pg. 24 of Henrik Wann Jensen. Realistic Image Synthesis - // Using Photon Mapping. AK Peters. ISBN: 1568811470. July 2001. - - // Invert the directions from Wann Jensen's formulation - // and normalize the vectors. - const Vector3 W = -direction(); - Vector3 N = normal.direction(); - - float h1 = iOutside; - float h2 = iInside; - - if (normal.dot(*this) > 0.0f) { - h1 = iInside; - h2 = iOutside; - N = -N; - } - - const float hRatio = h1 / h2; - const float WdotN = W.dot(N); - - float det = 1.0f - (float)square(hRatio) * (1.0f - (float)square(WdotN)); - - if (det < 0) { - // Total internal reflection - return Vector3::zero(); - } else { - return -hRatio * (W - WdotN * N) - N * sqrt(det); - } -} - -//---------------------------------------------------------------------------- -void Vector3::orthonormalize (Vector3 akVector[3]) { - // If the input vectors are v0, v1, and v2, then the Gram-Schmidt - // orthonormalization produces vectors u0, u1, and u2 as follows, - // - // u0 = v0/|v0| - // u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0| - // u2 = (v2-(u0*v2)u0-(u1*v2)u1)/|v2-(u0*v2)u0-(u1*v2)u1| - // - // where |A| indicates length of vector A and A*B indicates dot - // product of vectors A and B. - - // compute u0 - akVector[0].unitize(); - - // compute u1 - float fDot0 = akVector[0].dot(akVector[1]); - akVector[1] -= akVector[0] * fDot0; - akVector[1].unitize(); - - // compute u2 - float fDot1 = akVector[1].dot(akVector[2]); - fDot0 = akVector[0].dot(akVector[2]); - akVector[2] -= akVector[0] * fDot0 + akVector[1] * fDot1; - akVector[2].unitize(); -} - -//---------------------------------------------------------------------------- -void Vector3::generateOrthonormalBasis (Vector3& rkU, Vector3& rkV, - Vector3& rkW, bool bUnitLengthW) { - if ( !bUnitLengthW ) - rkW.unitize(); - - if ( G3D::abs(rkW.x) >= G3D::abs(rkW.y) - && G3D::abs(rkW.x) >= G3D::abs(rkW.z) ) { - rkU.x = -rkW.y; - rkU.y = + rkW.x; - rkU.z = 0.0; - } else { - rkU.x = 0.0; - rkU.y = + rkW.z; - rkU.z = -rkW.y; - } - - rkU.unitize(); - rkV = rkW.cross(rkU); -} - -//---------------------------------------------------------------------------- - -std::string Vector3::toString() const { - return G3D::format("(%g, %g, %g)", x, y, z); -} - - -//---------------------------------------------------------------------------- - -Matrix3 Vector3::cross() const { - return Matrix3( 0, -z, y, - z, 0, -x, - -y, x, 0); -} - - -void serialize(const Vector3::Axis& a, class BinaryOutput& bo) { - bo.writeUInt8((uint8)a); -} - -void deserialize(Vector3::Axis& a, class BinaryInput& bi) { - a = (Vector3::Axis)bi.readUInt8(); -} - -//---------------------------------------------------------------------------- -// 2-char swizzles - -Vector2 Vector3::xx() const { return Vector2 (x, x); } -Vector2 Vector3::yx() const { return Vector2 (y, x); } -Vector2 Vector3::zx() const { return Vector2 (z, x); } -Vector2 Vector3::xy() const { return Vector2 (x, y); } -Vector2 Vector3::yy() const { return Vector2 (y, y); } -Vector2 Vector3::zy() const { return Vector2 (z, y); } -Vector2 Vector3::xz() const { return Vector2 (x, z); } -Vector2 Vector3::yz() const { return Vector2 (y, z); } -Vector2 Vector3::zz() const { return Vector2 (z, z); } - -// 3-char swizzles - -Vector3 Vector3::xxx() const { return Vector3 (x, x, x); } -Vector3 Vector3::yxx() const { return Vector3 (y, x, x); } -Vector3 Vector3::zxx() const { return Vector3 (z, x, x); } -Vector3 Vector3::xyx() const { return Vector3 (x, y, x); } -Vector3 Vector3::yyx() const { return Vector3 (y, y, x); } -Vector3 Vector3::zyx() const { return Vector3 (z, y, x); } -Vector3 Vector3::xzx() const { return Vector3 (x, z, x); } -Vector3 Vector3::yzx() const { return Vector3 (y, z, x); } -Vector3 Vector3::zzx() const { return Vector3 (z, z, x); } -Vector3 Vector3::xxy() const { return Vector3 (x, x, y); } -Vector3 Vector3::yxy() const { return Vector3 (y, x, y); } -Vector3 Vector3::zxy() const { return Vector3 (z, x, y); } -Vector3 Vector3::xyy() const { return Vector3 (x, y, y); } -Vector3 Vector3::yyy() const { return Vector3 (y, y, y); } -Vector3 Vector3::zyy() const { return Vector3 (z, y, y); } -Vector3 Vector3::xzy() const { return Vector3 (x, z, y); } -Vector3 Vector3::yzy() const { return Vector3 (y, z, y); } -Vector3 Vector3::zzy() const { return Vector3 (z, z, y); } -Vector3 Vector3::xxz() const { return Vector3 (x, x, z); } -Vector3 Vector3::yxz() const { return Vector3 (y, x, z); } -Vector3 Vector3::zxz() const { return Vector3 (z, x, z); } -Vector3 Vector3::xyz() const { return Vector3 (x, y, z); } -Vector3 Vector3::yyz() const { return Vector3 (y, y, z); } -Vector3 Vector3::zyz() const { return Vector3 (z, y, z); } -Vector3 Vector3::xzz() const { return Vector3 (x, z, z); } -Vector3 Vector3::yzz() const { return Vector3 (y, z, z); } -Vector3 Vector3::zzz() const { return Vector3 (z, z, z); } - -// 4-char swizzles - -Vector4 Vector3::xxxx() const { return Vector4 (x, x, x, x); } -Vector4 Vector3::yxxx() const { return Vector4 (y, x, x, x); } -Vector4 Vector3::zxxx() const { return Vector4 (z, x, x, x); } -Vector4 Vector3::xyxx() const { return Vector4 (x, y, x, x); } -Vector4 Vector3::yyxx() const { return Vector4 (y, y, x, x); } -Vector4 Vector3::zyxx() const { return Vector4 (z, y, x, x); } -Vector4 Vector3::xzxx() const { return Vector4 (x, z, x, x); } -Vector4 Vector3::yzxx() const { return Vector4 (y, z, x, x); } -Vector4 Vector3::zzxx() const { return Vector4 (z, z, x, x); } -Vector4 Vector3::xxyx() const { return Vector4 (x, x, y, x); } -Vector4 Vector3::yxyx() const { return Vector4 (y, x, y, x); } -Vector4 Vector3::zxyx() const { return Vector4 (z, x, y, x); } -Vector4 Vector3::xyyx() const { return Vector4 (x, y, y, x); } -Vector4 Vector3::yyyx() const { return Vector4 (y, y, y, x); } -Vector4 Vector3::zyyx() const { return Vector4 (z, y, y, x); } -Vector4 Vector3::xzyx() const { return Vector4 (x, z, y, x); } -Vector4 Vector3::yzyx() const { return Vector4 (y, z, y, x); } -Vector4 Vector3::zzyx() const { return Vector4 (z, z, y, x); } -Vector4 Vector3::xxzx() const { return Vector4 (x, x, z, x); } -Vector4 Vector3::yxzx() const { return Vector4 (y, x, z, x); } -Vector4 Vector3::zxzx() const { return Vector4 (z, x, z, x); } -Vector4 Vector3::xyzx() const { return Vector4 (x, y, z, x); } -Vector4 Vector3::yyzx() const { return Vector4 (y, y, z, x); } -Vector4 Vector3::zyzx() const { return Vector4 (z, y, z, x); } -Vector4 Vector3::xzzx() const { return Vector4 (x, z, z, x); } -Vector4 Vector3::yzzx() const { return Vector4 (y, z, z, x); } -Vector4 Vector3::zzzx() const { return Vector4 (z, z, z, x); } -Vector4 Vector3::xxxy() const { return Vector4 (x, x, x, y); } -Vector4 Vector3::yxxy() const { return Vector4 (y, x, x, y); } -Vector4 Vector3::zxxy() const { return Vector4 (z, x, x, y); } -Vector4 Vector3::xyxy() const { return Vector4 (x, y, x, y); } -Vector4 Vector3::yyxy() const { return Vector4 (y, y, x, y); } -Vector4 Vector3::zyxy() const { return Vector4 (z, y, x, y); } -Vector4 Vector3::xzxy() const { return Vector4 (x, z, x, y); } -Vector4 Vector3::yzxy() const { return Vector4 (y, z, x, y); } -Vector4 Vector3::zzxy() const { return Vector4 (z, z, x, y); } -Vector4 Vector3::xxyy() const { return Vector4 (x, x, y, y); } -Vector4 Vector3::yxyy() const { return Vector4 (y, x, y, y); } -Vector4 Vector3::zxyy() const { return Vector4 (z, x, y, y); } -Vector4 Vector3::xyyy() const { return Vector4 (x, y, y, y); } -Vector4 Vector3::yyyy() const { return Vector4 (y, y, y, y); } -Vector4 Vector3::zyyy() const { return Vector4 (z, y, y, y); } -Vector4 Vector3::xzyy() const { return Vector4 (x, z, y, y); } -Vector4 Vector3::yzyy() const { return Vector4 (y, z, y, y); } -Vector4 Vector3::zzyy() const { return Vector4 (z, z, y, y); } -Vector4 Vector3::xxzy() const { return Vector4 (x, x, z, y); } -Vector4 Vector3::yxzy() const { return Vector4 (y, x, z, y); } -Vector4 Vector3::zxzy() const { return Vector4 (z, x, z, y); } -Vector4 Vector3::xyzy() const { return Vector4 (x, y, z, y); } -Vector4 Vector3::yyzy() const { return Vector4 (y, y, z, y); } -Vector4 Vector3::zyzy() const { return Vector4 (z, y, z, y); } -Vector4 Vector3::xzzy() const { return Vector4 (x, z, z, y); } -Vector4 Vector3::yzzy() const { return Vector4 (y, z, z, y); } -Vector4 Vector3::zzzy() const { return Vector4 (z, z, z, y); } -Vector4 Vector3::xxxz() const { return Vector4 (x, x, x, z); } -Vector4 Vector3::yxxz() const { return Vector4 (y, x, x, z); } -Vector4 Vector3::zxxz() const { return Vector4 (z, x, x, z); } -Vector4 Vector3::xyxz() const { return Vector4 (x, y, x, z); } -Vector4 Vector3::yyxz() const { return Vector4 (y, y, x, z); } -Vector4 Vector3::zyxz() const { return Vector4 (z, y, x, z); } -Vector4 Vector3::xzxz() const { return Vector4 (x, z, x, z); } -Vector4 Vector3::yzxz() const { return Vector4 (y, z, x, z); } -Vector4 Vector3::zzxz() const { return Vector4 (z, z, x, z); } -Vector4 Vector3::xxyz() const { return Vector4 (x, x, y, z); } -Vector4 Vector3::yxyz() const { return Vector4 (y, x, y, z); } -Vector4 Vector3::zxyz() const { return Vector4 (z, x, y, z); } -Vector4 Vector3::xyyz() const { return Vector4 (x, y, y, z); } -Vector4 Vector3::yyyz() const { return Vector4 (y, y, y, z); } -Vector4 Vector3::zyyz() const { return Vector4 (z, y, y, z); } -Vector4 Vector3::xzyz() const { return Vector4 (x, z, y, z); } -Vector4 Vector3::yzyz() const { return Vector4 (y, z, y, z); } -Vector4 Vector3::zzyz() const { return Vector4 (z, z, y, z); } -Vector4 Vector3::xxzz() const { return Vector4 (x, x, z, z); } -Vector4 Vector3::yxzz() const { return Vector4 (y, x, z, z); } -Vector4 Vector3::zxzz() const { return Vector4 (z, x, z, z); } -Vector4 Vector3::xyzz() const { return Vector4 (x, y, z, z); } -Vector4 Vector3::yyzz() const { return Vector4 (y, y, z, z); } -Vector4 Vector3::zyzz() const { return Vector4 (z, y, z, z); } -Vector4 Vector3::xzzz() const { return Vector4 (x, z, z, z); } -Vector4 Vector3::yzzz() const { return Vector4 (y, z, z, z); } -Vector4 Vector3::zzzz() const { return Vector4 (z, z, z, z); } - - - - - - -} // namespace diff --git a/externals/g3dlite/G3D.lib/source/Vector3int16.cpp b/externals/g3dlite/G3D.lib/source/Vector3int16.cpp deleted file mode 100644 index 8d8bb00bbef..00000000000 --- a/externals/g3dlite/G3D.lib/source/Vector3int16.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/** - @file Vector3int16.cpp - - @author Morgan McGuire, matrix@graphics3d.com - - @created 2003-04-07 - @edited 2006-01-17 - */ - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Vector3int16.h" -#include "G3D/Vector3.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/format.h" - -namespace G3D { - -Vector3int16::Vector3int16(const class Vector3& v) { - x = (int16)iFloor(v.x + 0.5); - y = (int16)iFloor(v.y + 0.5); - z = (int16)iFloor(v.z + 0.5); -} - - -Vector3int16::Vector3int16(class BinaryInput& bi) { - deserialize(bi); -} - - -void Vector3int16::serialize(class BinaryOutput& bo) const { - bo.writeInt16(x); - bo.writeInt16(y); - bo.writeInt16(z); -} - - -void Vector3int16::deserialize(class BinaryInput& bi) { - x = bi.readInt16(); - y = bi.readInt16(); - z = bi.readInt16(); -} - -std::string Vector3int16::toString() const { - return G3D::format("(%d, %d, %d)", x, y, z); -} - -} diff --git a/externals/g3dlite/G3D.lib/source/Vector3int32.cpp b/externals/g3dlite/G3D.lib/source/Vector3int32.cpp deleted file mode 100644 index 1328ba1aba5..00000000000 --- a/externals/g3dlite/G3D.lib/source/Vector3int32.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/** - @file Vector3int32.cpp - - @author Morgan McGuire, matrix@graphics3d.com - - @created 2008-07-01 - @edited 2008-07-01 - */ - -#include "G3D/platform.h" -#include "G3D/g3dmath.h" -#include "G3D/Vector3int32.h" -#include "G3D/Vector3int16.h" -#include "G3D/Vector3.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/format.h" - -namespace G3D { - -Vector3int32::Vector3int32(const class Vector3& v) { - x = (int32)iFloor(v.x + 0.5); - y = (int32)iFloor(v.y + 0.5); - z = (int32)iFloor(v.z + 0.5); -} - - -Vector3int32::Vector3int32(const class Vector3int16& v) { - x = v.x; - y = v.y; - z = v.z; -} - - -Vector3int32::Vector3int32(class BinaryInput& bi) { - deserialize(bi); -} - - -void Vector3int32::serialize(class BinaryOutput& bo) const { - bo.writeInt32(x); - bo.writeInt32(y); - bo.writeInt32(z); -} - - -void Vector3int32::deserialize(class BinaryInput& bi) { - x = bi.readInt32(); - y = bi.readInt32(); - z = bi.readInt32(); -} - -std::string Vector3int32::toString() const { - return G3D::format("(%d, %d, %d)", x, y, z); -} - -} diff --git a/externals/g3dlite/G3D.lib/source/Vector4.cpp b/externals/g3dlite/G3D.lib/source/Vector4.cpp deleted file mode 100644 index f562f2d6877..00000000000 --- a/externals/g3dlite/G3D.lib/source/Vector4.cpp +++ /dev/null @@ -1,475 +0,0 @@ -/** - @file Vector4.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2001-07-09 - @edited 2007-02-29 - */ - -#include -#include -#include "G3D/Vector4.h" -#include "G3D/Color4.h" -#include "G3D/g3dmath.h" -#include "G3D/stringutils.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/Vector4int8.h" -#include "G3D/Matrix4.h" - -namespace G3D { - -Vector4::Vector4(const Vector4int8& v) : x(v.x / 127.0f), y(v.y / 127.0f), z(v.z / 127.0f), w(v.w / 127.0f) { -} - -size_t Vector4::hashCode() const { - unsigned int xhash = (*(int*)(void*)(&x)); - unsigned int yhash = (*(int*)(void*)(&y)); - unsigned int zhash = (*(int*)(void*)(&z)); - unsigned int whash = (*(int*)(void*)(&w)); - - return xhash + (yhash * 37) + (zhash * 101) + (whash * 241); -} - - -Vector4::Vector4(const class Color4& c) { - x = c.r; - y = c.g; - z = c.b; - w = c.a; -} - - -Vector4::Vector4(const Vector2& v1, const Vector2& v2) { - x = v1.x; - y = v1.y; - z = v2.x; - w = v2.y; -} - - -Vector4::Vector4(const Vector2& v1, float fz, float fw) { - x = v1.x; - y = v1.y; - z = fz; - w = fw; -} - -Vector4::Vector4(BinaryInput& b) { - deserialize(b); -} - - -void Vector4::deserialize(BinaryInput& b) { - x = b.readFloat32(); - y = b.readFloat32(); - z = b.readFloat32(); - w = b.readFloat32(); -} - - -void Vector4::serialize(BinaryOutput& b) const { - b.writeFloat32(x); - b.writeFloat32(y); - b.writeFloat32(z); - b.writeFloat32(w); -} - -//---------------------------------------------------------------------------- - -Vector4 Vector4::operator*(const Matrix4& M) const { - Vector4 result; - for (int i = 0; i < 4; ++i) { - result[i] = 0.0f; - for (int j = 0; j < 4; ++j) { - result[i] += (*this)[j] * M[j][i]; - } - } - return result; -} - - -Vector4 Vector4::operator/ (float fScalar) const { - Vector4 kQuot; - - if ( fScalar != 0.0 ) { - float fInvScalar = 1.0f / fScalar; - kQuot.x = fInvScalar * x; - kQuot.y = fInvScalar * y; - kQuot.z = fInvScalar * z; - kQuot.w = fInvScalar * w; - return kQuot; - } else { - return Vector4::inf(); - } -} - -//---------------------------------------------------------------------------- -Vector4& Vector4::operator/= (float fScalar) { - if (fScalar != 0.0f) { - float fInvScalar = 1.0f / fScalar; - x *= fInvScalar; - y *= fInvScalar; - z *= fInvScalar; - w *= fInvScalar; - } else { - *this = Vector4::inf(); - } - - return *this; -} - - -//---------------------------------------------------------------------------- - -std::string Vector4::toString() const { - return G3D::format("(%g, %g, %g, %g)", x, y, z, w); -} -// 2-char swizzles - -Vector2 Vector4::xx() const { return Vector2 (x, x); } -Vector2 Vector4::yx() const { return Vector2 (y, x); } -Vector2 Vector4::zx() const { return Vector2 (z, x); } -Vector2 Vector4::wx() const { return Vector2 (w, x); } -Vector2 Vector4::xy() const { return Vector2 (x, y); } -Vector2 Vector4::yy() const { return Vector2 (y, y); } -Vector2 Vector4::zy() const { return Vector2 (z, y); } -Vector2 Vector4::wy() const { return Vector2 (w, y); } -Vector2 Vector4::xz() const { return Vector2 (x, z); } -Vector2 Vector4::yz() const { return Vector2 (y, z); } -Vector2 Vector4::zz() const { return Vector2 (z, z); } -Vector2 Vector4::wz() const { return Vector2 (w, z); } -Vector2 Vector4::xw() const { return Vector2 (x, w); } -Vector2 Vector4::yw() const { return Vector2 (y, w); } -Vector2 Vector4::zw() const { return Vector2 (z, w); } -Vector2 Vector4::ww() const { return Vector2 (w, w); } - -// 3-char swizzles - -Vector3 Vector4::xxx() const { return Vector3 (x, x, x); } -Vector3 Vector4::yxx() const { return Vector3 (y, x, x); } -Vector3 Vector4::zxx() const { return Vector3 (z, x, x); } -Vector3 Vector4::wxx() const { return Vector3 (w, x, x); } -Vector3 Vector4::xyx() const { return Vector3 (x, y, x); } -Vector3 Vector4::yyx() const { return Vector3 (y, y, x); } -Vector3 Vector4::zyx() const { return Vector3 (z, y, x); } -Vector3 Vector4::wyx() const { return Vector3 (w, y, x); } -Vector3 Vector4::xzx() const { return Vector3 (x, z, x); } -Vector3 Vector4::yzx() const { return Vector3 (y, z, x); } -Vector3 Vector4::zzx() const { return Vector3 (z, z, x); } -Vector3 Vector4::wzx() const { return Vector3 (w, z, x); } -Vector3 Vector4::xwx() const { return Vector3 (x, w, x); } -Vector3 Vector4::ywx() const { return Vector3 (y, w, x); } -Vector3 Vector4::zwx() const { return Vector3 (z, w, x); } -Vector3 Vector4::wwx() const { return Vector3 (w, w, x); } -Vector3 Vector4::xxy() const { return Vector3 (x, x, y); } -Vector3 Vector4::yxy() const { return Vector3 (y, x, y); } -Vector3 Vector4::zxy() const { return Vector3 (z, x, y); } -Vector3 Vector4::wxy() const { return Vector3 (w, x, y); } -Vector3 Vector4::xyy() const { return Vector3 (x, y, y); } -Vector3 Vector4::yyy() const { return Vector3 (y, y, y); } -Vector3 Vector4::zyy() const { return Vector3 (z, y, y); } -Vector3 Vector4::wyy() const { return Vector3 (w, y, y); } -Vector3 Vector4::xzy() const { return Vector3 (x, z, y); } -Vector3 Vector4::yzy() const { return Vector3 (y, z, y); } -Vector3 Vector4::zzy() const { return Vector3 (z, z, y); } -Vector3 Vector4::wzy() const { return Vector3 (w, z, y); } -Vector3 Vector4::xwy() const { return Vector3 (x, w, y); } -Vector3 Vector4::ywy() const { return Vector3 (y, w, y); } -Vector3 Vector4::zwy() const { return Vector3 (z, w, y); } -Vector3 Vector4::wwy() const { return Vector3 (w, w, y); } -Vector3 Vector4::xxz() const { return Vector3 (x, x, z); } -Vector3 Vector4::yxz() const { return Vector3 (y, x, z); } -Vector3 Vector4::zxz() const { return Vector3 (z, x, z); } -Vector3 Vector4::wxz() const { return Vector3 (w, x, z); } -Vector3 Vector4::xyz() const { return Vector3 (x, y, z); } -Vector3 Vector4::yyz() const { return Vector3 (y, y, z); } -Vector3 Vector4::zyz() const { return Vector3 (z, y, z); } -Vector3 Vector4::wyz() const { return Vector3 (w, y, z); } -Vector3 Vector4::xzz() const { return Vector3 (x, z, z); } -Vector3 Vector4::yzz() const { return Vector3 (y, z, z); } -Vector3 Vector4::zzz() const { return Vector3 (z, z, z); } -Vector3 Vector4::wzz() const { return Vector3 (w, z, z); } -Vector3 Vector4::xwz() const { return Vector3 (x, w, z); } -Vector3 Vector4::ywz() const { return Vector3 (y, w, z); } -Vector3 Vector4::zwz() const { return Vector3 (z, w, z); } -Vector3 Vector4::wwz() const { return Vector3 (w, w, z); } -Vector3 Vector4::xxw() const { return Vector3 (x, x, w); } -Vector3 Vector4::yxw() const { return Vector3 (y, x, w); } -Vector3 Vector4::zxw() const { return Vector3 (z, x, w); } -Vector3 Vector4::wxw() const { return Vector3 (w, x, w); } -Vector3 Vector4::xyw() const { return Vector3 (x, y, w); } -Vector3 Vector4::yyw() const { return Vector3 (y, y, w); } -Vector3 Vector4::zyw() const { return Vector3 (z, y, w); } -Vector3 Vector4::wyw() const { return Vector3 (w, y, w); } -Vector3 Vector4::xzw() const { return Vector3 (x, z, w); } -Vector3 Vector4::yzw() const { return Vector3 (y, z, w); } -Vector3 Vector4::zzw() const { return Vector3 (z, z, w); } -Vector3 Vector4::wzw() const { return Vector3 (w, z, w); } -Vector3 Vector4::xww() const { return Vector3 (x, w, w); } -Vector3 Vector4::yww() const { return Vector3 (y, w, w); } -Vector3 Vector4::zww() const { return Vector3 (z, w, w); } -Vector3 Vector4::www() const { return Vector3 (w, w, w); } - -// 4-char swizzles - -Vector4 Vector4::xxxx() const { return Vector4 (x, x, x, x); } -Vector4 Vector4::yxxx() const { return Vector4 (y, x, x, x); } -Vector4 Vector4::zxxx() const { return Vector4 (z, x, x, x); } -Vector4 Vector4::wxxx() const { return Vector4 (w, x, x, x); } -Vector4 Vector4::xyxx() const { return Vector4 (x, y, x, x); } -Vector4 Vector4::yyxx() const { return Vector4 (y, y, x, x); } -Vector4 Vector4::zyxx() const { return Vector4 (z, y, x, x); } -Vector4 Vector4::wyxx() const { return Vector4 (w, y, x, x); } -Vector4 Vector4::xzxx() const { return Vector4 (x, z, x, x); } -Vector4 Vector4::yzxx() const { return Vector4 (y, z, x, x); } -Vector4 Vector4::zzxx() const { return Vector4 (z, z, x, x); } -Vector4 Vector4::wzxx() const { return Vector4 (w, z, x, x); } -Vector4 Vector4::xwxx() const { return Vector4 (x, w, x, x); } -Vector4 Vector4::ywxx() const { return Vector4 (y, w, x, x); } -Vector4 Vector4::zwxx() const { return Vector4 (z, w, x, x); } -Vector4 Vector4::wwxx() const { return Vector4 (w, w, x, x); } -Vector4 Vector4::xxyx() const { return Vector4 (x, x, y, x); } -Vector4 Vector4::yxyx() const { return Vector4 (y, x, y, x); } -Vector4 Vector4::zxyx() const { return Vector4 (z, x, y, x); } -Vector4 Vector4::wxyx() const { return Vector4 (w, x, y, x); } -Vector4 Vector4::xyyx() const { return Vector4 (x, y, y, x); } -Vector4 Vector4::yyyx() const { return Vector4 (y, y, y, x); } -Vector4 Vector4::zyyx() const { return Vector4 (z, y, y, x); } -Vector4 Vector4::wyyx() const { return Vector4 (w, y, y, x); } -Vector4 Vector4::xzyx() const { return Vector4 (x, z, y, x); } -Vector4 Vector4::yzyx() const { return Vector4 (y, z, y, x); } -Vector4 Vector4::zzyx() const { return Vector4 (z, z, y, x); } -Vector4 Vector4::wzyx() const { return Vector4 (w, z, y, x); } -Vector4 Vector4::xwyx() const { return Vector4 (x, w, y, x); } -Vector4 Vector4::ywyx() const { return Vector4 (y, w, y, x); } -Vector4 Vector4::zwyx() const { return Vector4 (z, w, y, x); } -Vector4 Vector4::wwyx() const { return Vector4 (w, w, y, x); } -Vector4 Vector4::xxzx() const { return Vector4 (x, x, z, x); } -Vector4 Vector4::yxzx() const { return Vector4 (y, x, z, x); } -Vector4 Vector4::zxzx() const { return Vector4 (z, x, z, x); } -Vector4 Vector4::wxzx() const { return Vector4 (w, x, z, x); } -Vector4 Vector4::xyzx() const { return Vector4 (x, y, z, x); } -Vector4 Vector4::yyzx() const { return Vector4 (y, y, z, x); } -Vector4 Vector4::zyzx() const { return Vector4 (z, y, z, x); } -Vector4 Vector4::wyzx() const { return Vector4 (w, y, z, x); } -Vector4 Vector4::xzzx() const { return Vector4 (x, z, z, x); } -Vector4 Vector4::yzzx() const { return Vector4 (y, z, z, x); } -Vector4 Vector4::zzzx() const { return Vector4 (z, z, z, x); } -Vector4 Vector4::wzzx() const { return Vector4 (w, z, z, x); } -Vector4 Vector4::xwzx() const { return Vector4 (x, w, z, x); } -Vector4 Vector4::ywzx() const { return Vector4 (y, w, z, x); } -Vector4 Vector4::zwzx() const { return Vector4 (z, w, z, x); } -Vector4 Vector4::wwzx() const { return Vector4 (w, w, z, x); } -Vector4 Vector4::xxwx() const { return Vector4 (x, x, w, x); } -Vector4 Vector4::yxwx() const { return Vector4 (y, x, w, x); } -Vector4 Vector4::zxwx() const { return Vector4 (z, x, w, x); } -Vector4 Vector4::wxwx() const { return Vector4 (w, x, w, x); } -Vector4 Vector4::xywx() const { return Vector4 (x, y, w, x); } -Vector4 Vector4::yywx() const { return Vector4 (y, y, w, x); } -Vector4 Vector4::zywx() const { return Vector4 (z, y, w, x); } -Vector4 Vector4::wywx() const { return Vector4 (w, y, w, x); } -Vector4 Vector4::xzwx() const { return Vector4 (x, z, w, x); } -Vector4 Vector4::yzwx() const { return Vector4 (y, z, w, x); } -Vector4 Vector4::zzwx() const { return Vector4 (z, z, w, x); } -Vector4 Vector4::wzwx() const { return Vector4 (w, z, w, x); } -Vector4 Vector4::xwwx() const { return Vector4 (x, w, w, x); } -Vector4 Vector4::ywwx() const { return Vector4 (y, w, w, x); } -Vector4 Vector4::zwwx() const { return Vector4 (z, w, w, x); } -Vector4 Vector4::wwwx() const { return Vector4 (w, w, w, x); } -Vector4 Vector4::xxxy() const { return Vector4 (x, x, x, y); } -Vector4 Vector4::yxxy() const { return Vector4 (y, x, x, y); } -Vector4 Vector4::zxxy() const { return Vector4 (z, x, x, y); } -Vector4 Vector4::wxxy() const { return Vector4 (w, x, x, y); } -Vector4 Vector4::xyxy() const { return Vector4 (x, y, x, y); } -Vector4 Vector4::yyxy() const { return Vector4 (y, y, x, y); } -Vector4 Vector4::zyxy() const { return Vector4 (z, y, x, y); } -Vector4 Vector4::wyxy() const { return Vector4 (w, y, x, y); } -Vector4 Vector4::xzxy() const { return Vector4 (x, z, x, y); } -Vector4 Vector4::yzxy() const { return Vector4 (y, z, x, y); } -Vector4 Vector4::zzxy() const { return Vector4 (z, z, x, y); } -Vector4 Vector4::wzxy() const { return Vector4 (w, z, x, y); } -Vector4 Vector4::xwxy() const { return Vector4 (x, w, x, y); } -Vector4 Vector4::ywxy() const { return Vector4 (y, w, x, y); } -Vector4 Vector4::zwxy() const { return Vector4 (z, w, x, y); } -Vector4 Vector4::wwxy() const { return Vector4 (w, w, x, y); } -Vector4 Vector4::xxyy() const { return Vector4 (x, x, y, y); } -Vector4 Vector4::yxyy() const { return Vector4 (y, x, y, y); } -Vector4 Vector4::zxyy() const { return Vector4 (z, x, y, y); } -Vector4 Vector4::wxyy() const { return Vector4 (w, x, y, y); } -Vector4 Vector4::xyyy() const { return Vector4 (x, y, y, y); } -Vector4 Vector4::yyyy() const { return Vector4 (y, y, y, y); } -Vector4 Vector4::zyyy() const { return Vector4 (z, y, y, y); } -Vector4 Vector4::wyyy() const { return Vector4 (w, y, y, y); } -Vector4 Vector4::xzyy() const { return Vector4 (x, z, y, y); } -Vector4 Vector4::yzyy() const { return Vector4 (y, z, y, y); } -Vector4 Vector4::zzyy() const { return Vector4 (z, z, y, y); } -Vector4 Vector4::wzyy() const { return Vector4 (w, z, y, y); } -Vector4 Vector4::xwyy() const { return Vector4 (x, w, y, y); } -Vector4 Vector4::ywyy() const { return Vector4 (y, w, y, y); } -Vector4 Vector4::zwyy() const { return Vector4 (z, w, y, y); } -Vector4 Vector4::wwyy() const { return Vector4 (w, w, y, y); } -Vector4 Vector4::xxzy() const { return Vector4 (x, x, z, y); } -Vector4 Vector4::yxzy() const { return Vector4 (y, x, z, y); } -Vector4 Vector4::zxzy() const { return Vector4 (z, x, z, y); } -Vector4 Vector4::wxzy() const { return Vector4 (w, x, z, y); } -Vector4 Vector4::xyzy() const { return Vector4 (x, y, z, y); } -Vector4 Vector4::yyzy() const { return Vector4 (y, y, z, y); } -Vector4 Vector4::zyzy() const { return Vector4 (z, y, z, y); } -Vector4 Vector4::wyzy() const { return Vector4 (w, y, z, y); } -Vector4 Vector4::xzzy() const { return Vector4 (x, z, z, y); } -Vector4 Vector4::yzzy() const { return Vector4 (y, z, z, y); } -Vector4 Vector4::zzzy() const { return Vector4 (z, z, z, y); } -Vector4 Vector4::wzzy() const { return Vector4 (w, z, z, y); } -Vector4 Vector4::xwzy() const { return Vector4 (x, w, z, y); } -Vector4 Vector4::ywzy() const { return Vector4 (y, w, z, y); } -Vector4 Vector4::zwzy() const { return Vector4 (z, w, z, y); } -Vector4 Vector4::wwzy() const { return Vector4 (w, w, z, y); } -Vector4 Vector4::xxwy() const { return Vector4 (x, x, w, y); } -Vector4 Vector4::yxwy() const { return Vector4 (y, x, w, y); } -Vector4 Vector4::zxwy() const { return Vector4 (z, x, w, y); } -Vector4 Vector4::wxwy() const { return Vector4 (w, x, w, y); } -Vector4 Vector4::xywy() const { return Vector4 (x, y, w, y); } -Vector4 Vector4::yywy() const { return Vector4 (y, y, w, y); } -Vector4 Vector4::zywy() const { return Vector4 (z, y, w, y); } -Vector4 Vector4::wywy() const { return Vector4 (w, y, w, y); } -Vector4 Vector4::xzwy() const { return Vector4 (x, z, w, y); } -Vector4 Vector4::yzwy() const { return Vector4 (y, z, w, y); } -Vector4 Vector4::zzwy() const { return Vector4 (z, z, w, y); } -Vector4 Vector4::wzwy() const { return Vector4 (w, z, w, y); } -Vector4 Vector4::xwwy() const { return Vector4 (x, w, w, y); } -Vector4 Vector4::ywwy() const { return Vector4 (y, w, w, y); } -Vector4 Vector4::zwwy() const { return Vector4 (z, w, w, y); } -Vector4 Vector4::wwwy() const { return Vector4 (w, w, w, y); } -Vector4 Vector4::xxxz() const { return Vector4 (x, x, x, z); } -Vector4 Vector4::yxxz() const { return Vector4 (y, x, x, z); } -Vector4 Vector4::zxxz() const { return Vector4 (z, x, x, z); } -Vector4 Vector4::wxxz() const { return Vector4 (w, x, x, z); } -Vector4 Vector4::xyxz() const { return Vector4 (x, y, x, z); } -Vector4 Vector4::yyxz() const { return Vector4 (y, y, x, z); } -Vector4 Vector4::zyxz() const { return Vector4 (z, y, x, z); } -Vector4 Vector4::wyxz() const { return Vector4 (w, y, x, z); } -Vector4 Vector4::xzxz() const { return Vector4 (x, z, x, z); } -Vector4 Vector4::yzxz() const { return Vector4 (y, z, x, z); } -Vector4 Vector4::zzxz() const { return Vector4 (z, z, x, z); } -Vector4 Vector4::wzxz() const { return Vector4 (w, z, x, z); } -Vector4 Vector4::xwxz() const { return Vector4 (x, w, x, z); } -Vector4 Vector4::ywxz() const { return Vector4 (y, w, x, z); } -Vector4 Vector4::zwxz() const { return Vector4 (z, w, x, z); } -Vector4 Vector4::wwxz() const { return Vector4 (w, w, x, z); } -Vector4 Vector4::xxyz() const { return Vector4 (x, x, y, z); } -Vector4 Vector4::yxyz() const { return Vector4 (y, x, y, z); } -Vector4 Vector4::zxyz() const { return Vector4 (z, x, y, z); } -Vector4 Vector4::wxyz() const { return Vector4 (w, x, y, z); } -Vector4 Vector4::xyyz() const { return Vector4 (x, y, y, z); } -Vector4 Vector4::yyyz() const { return Vector4 (y, y, y, z); } -Vector4 Vector4::zyyz() const { return Vector4 (z, y, y, z); } -Vector4 Vector4::wyyz() const { return Vector4 (w, y, y, z); } -Vector4 Vector4::xzyz() const { return Vector4 (x, z, y, z); } -Vector4 Vector4::yzyz() const { return Vector4 (y, z, y, z); } -Vector4 Vector4::zzyz() const { return Vector4 (z, z, y, z); } -Vector4 Vector4::wzyz() const { return Vector4 (w, z, y, z); } -Vector4 Vector4::xwyz() const { return Vector4 (x, w, y, z); } -Vector4 Vector4::ywyz() const { return Vector4 (y, w, y, z); } -Vector4 Vector4::zwyz() const { return Vector4 (z, w, y, z); } -Vector4 Vector4::wwyz() const { return Vector4 (w, w, y, z); } -Vector4 Vector4::xxzz() const { return Vector4 (x, x, z, z); } -Vector4 Vector4::yxzz() const { return Vector4 (y, x, z, z); } -Vector4 Vector4::zxzz() const { return Vector4 (z, x, z, z); } -Vector4 Vector4::wxzz() const { return Vector4 (w, x, z, z); } -Vector4 Vector4::xyzz() const { return Vector4 (x, y, z, z); } -Vector4 Vector4::yyzz() const { return Vector4 (y, y, z, z); } -Vector4 Vector4::zyzz() const { return Vector4 (z, y, z, z); } -Vector4 Vector4::wyzz() const { return Vector4 (w, y, z, z); } -Vector4 Vector4::xzzz() const { return Vector4 (x, z, z, z); } -Vector4 Vector4::yzzz() const { return Vector4 (y, z, z, z); } -Vector4 Vector4::zzzz() const { return Vector4 (z, z, z, z); } -Vector4 Vector4::wzzz() const { return Vector4 (w, z, z, z); } -Vector4 Vector4::xwzz() const { return Vector4 (x, w, z, z); } -Vector4 Vector4::ywzz() const { return Vector4 (y, w, z, z); } -Vector4 Vector4::zwzz() const { return Vector4 (z, w, z, z); } -Vector4 Vector4::wwzz() const { return Vector4 (w, w, z, z); } -Vector4 Vector4::xxwz() const { return Vector4 (x, x, w, z); } -Vector4 Vector4::yxwz() const { return Vector4 (y, x, w, z); } -Vector4 Vector4::zxwz() const { return Vector4 (z, x, w, z); } -Vector4 Vector4::wxwz() const { return Vector4 (w, x, w, z); } -Vector4 Vector4::xywz() const { return Vector4 (x, y, w, z); } -Vector4 Vector4::yywz() const { return Vector4 (y, y, w, z); } -Vector4 Vector4::zywz() const { return Vector4 (z, y, w, z); } -Vector4 Vector4::wywz() const { return Vector4 (w, y, w, z); } -Vector4 Vector4::xzwz() const { return Vector4 (x, z, w, z); } -Vector4 Vector4::yzwz() const { return Vector4 (y, z, w, z); } -Vector4 Vector4::zzwz() const { return Vector4 (z, z, w, z); } -Vector4 Vector4::wzwz() const { return Vector4 (w, z, w, z); } -Vector4 Vector4::xwwz() const { return Vector4 (x, w, w, z); } -Vector4 Vector4::ywwz() const { return Vector4 (y, w, w, z); } -Vector4 Vector4::zwwz() const { return Vector4 (z, w, w, z); } -Vector4 Vector4::wwwz() const { return Vector4 (w, w, w, z); } -Vector4 Vector4::xxxw() const { return Vector4 (x, x, x, w); } -Vector4 Vector4::yxxw() const { return Vector4 (y, x, x, w); } -Vector4 Vector4::zxxw() const { return Vector4 (z, x, x, w); } -Vector4 Vector4::wxxw() const { return Vector4 (w, x, x, w); } -Vector4 Vector4::xyxw() const { return Vector4 (x, y, x, w); } -Vector4 Vector4::yyxw() const { return Vector4 (y, y, x, w); } -Vector4 Vector4::zyxw() const { return Vector4 (z, y, x, w); } -Vector4 Vector4::wyxw() const { return Vector4 (w, y, x, w); } -Vector4 Vector4::xzxw() const { return Vector4 (x, z, x, w); } -Vector4 Vector4::yzxw() const { return Vector4 (y, z, x, w); } -Vector4 Vector4::zzxw() const { return Vector4 (z, z, x, w); } -Vector4 Vector4::wzxw() const { return Vector4 (w, z, x, w); } -Vector4 Vector4::xwxw() const { return Vector4 (x, w, x, w); } -Vector4 Vector4::ywxw() const { return Vector4 (y, w, x, w); } -Vector4 Vector4::zwxw() const { return Vector4 (z, w, x, w); } -Vector4 Vector4::wwxw() const { return Vector4 (w, w, x, w); } -Vector4 Vector4::xxyw() const { return Vector4 (x, x, y, w); } -Vector4 Vector4::yxyw() const { return Vector4 (y, x, y, w); } -Vector4 Vector4::zxyw() const { return Vector4 (z, x, y, w); } -Vector4 Vector4::wxyw() const { return Vector4 (w, x, y, w); } -Vector4 Vector4::xyyw() const { return Vector4 (x, y, y, w); } -Vector4 Vector4::yyyw() const { return Vector4 (y, y, y, w); } -Vector4 Vector4::zyyw() const { return Vector4 (z, y, y, w); } -Vector4 Vector4::wyyw() const { return Vector4 (w, y, y, w); } -Vector4 Vector4::xzyw() const { return Vector4 (x, z, y, w); } -Vector4 Vector4::yzyw() const { return Vector4 (y, z, y, w); } -Vector4 Vector4::zzyw() const { return Vector4 (z, z, y, w); } -Vector4 Vector4::wzyw() const { return Vector4 (w, z, y, w); } -Vector4 Vector4::xwyw() const { return Vector4 (x, w, y, w); } -Vector4 Vector4::ywyw() const { return Vector4 (y, w, y, w); } -Vector4 Vector4::zwyw() const { return Vector4 (z, w, y, w); } -Vector4 Vector4::wwyw() const { return Vector4 (w, w, y, w); } -Vector4 Vector4::xxzw() const { return Vector4 (x, x, z, w); } -Vector4 Vector4::yxzw() const { return Vector4 (y, x, z, w); } -Vector4 Vector4::zxzw() const { return Vector4 (z, x, z, w); } -Vector4 Vector4::wxzw() const { return Vector4 (w, x, z, w); } -Vector4 Vector4::xyzw() const { return Vector4 (x, y, z, w); } -Vector4 Vector4::yyzw() const { return Vector4 (y, y, z, w); } -Vector4 Vector4::zyzw() const { return Vector4 (z, y, z, w); } -Vector4 Vector4::wyzw() const { return Vector4 (w, y, z, w); } -Vector4 Vector4::xzzw() const { return Vector4 (x, z, z, w); } -Vector4 Vector4::yzzw() const { return Vector4 (y, z, z, w); } -Vector4 Vector4::zzzw() const { return Vector4 (z, z, z, w); } -Vector4 Vector4::wzzw() const { return Vector4 (w, z, z, w); } -Vector4 Vector4::xwzw() const { return Vector4 (x, w, z, w); } -Vector4 Vector4::ywzw() const { return Vector4 (y, w, z, w); } -Vector4 Vector4::zwzw() const { return Vector4 (z, w, z, w); } -Vector4 Vector4::wwzw() const { return Vector4 (w, w, z, w); } -Vector4 Vector4::xxww() const { return Vector4 (x, x, w, w); } -Vector4 Vector4::yxww() const { return Vector4 (y, x, w, w); } -Vector4 Vector4::zxww() const { return Vector4 (z, x, w, w); } -Vector4 Vector4::wxww() const { return Vector4 (w, x, w, w); } -Vector4 Vector4::xyww() const { return Vector4 (x, y, w, w); } -Vector4 Vector4::yyww() const { return Vector4 (y, y, w, w); } -Vector4 Vector4::zyww() const { return Vector4 (z, y, w, w); } -Vector4 Vector4::wyww() const { return Vector4 (w, y, w, w); } -Vector4 Vector4::xzww() const { return Vector4 (x, z, w, w); } -Vector4 Vector4::yzww() const { return Vector4 (y, z, w, w); } -Vector4 Vector4::zzww() const { return Vector4 (z, z, w, w); } -Vector4 Vector4::wzww() const { return Vector4 (w, z, w, w); } -Vector4 Vector4::xwww() const { return Vector4 (x, w, w, w); } -Vector4 Vector4::ywww() const { return Vector4 (y, w, w, w); } -Vector4 Vector4::zwww() const { return Vector4 (z, w, w, w); } -Vector4 Vector4::wwww() const { return Vector4 (w, w, w, w); } - - -}; // namespace diff --git a/externals/g3dlite/G3D.lib/source/Vector4int8.cpp b/externals/g3dlite/G3D.lib/source/Vector4int8.cpp deleted file mode 100644 index 29ca0d678fc..00000000000 --- a/externals/g3dlite/G3D.lib/source/Vector4int8.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/** - @file Vector4int8.cpp - - Homogeneous vector class. - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2007-02-09 - @edited 2007-02-09 - - Copyright 2000-2007, Morgan McGuire. - All rights reserved. - */ - -#include "G3D/platform.h" -#include "G3D/Vector4int8.h" -#include "G3D/Vector3.h" -#include "G3D/Vector4.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include - -namespace G3D { - -Vector4int8::Vector4int8(const Vector4& source) { - x = iClamp(iRound(source.x), -128, 127); - y = iClamp(iRound(source.y), -128, 127); - z = iClamp(iRound(source.z), -128, 127); - w = iClamp(iRound(source.w), -128, 127); -} - -Vector4int8::Vector4int8(const Vector3& source, int8 w) : w(w) { - x = iClamp(iRound(source.x), -128, 127); - y = iClamp(iRound(source.y), -128, 127); - z = iClamp(iRound(source.z), -128, 127); -} - -Vector4int8::Vector4int8(class BinaryInput& b) { - deserialize(b); -} - -void Vector4int8::serialize(class BinaryOutput& b) const { - // Intentionally write individual bytes to avoid endian issues - b.writeInt8(x); - b.writeInt8(y); - b.writeInt8(z); - b.writeInt8(w); -} - -void Vector4int8::deserialize(class BinaryInput& b) { - x = b.readInt8(); - y = b.readInt8(); - z = b.readInt8(); - w = b.readInt8(); -} - -} // namespace G3D - diff --git a/externals/g3dlite/G3D.lib/source/WinMain.cpp b/externals/g3dlite/G3D.lib/source/WinMain.cpp deleted file mode 100644 index 94653de4d43..00000000000 --- a/externals/g3dlite/G3D.lib/source/WinMain.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - Dervied from SDL_main.c, which was placed in the public domain by Sam Lantinga 4/13/98 - - The WinMain function -- calls your program's main() function -*/ - -#include "G3D/platform.h" - -#ifdef G3D_WIN32 - -#include -#include -#include - -#ifdef main -# ifndef _WIN32_WCE_EMULATION -# undef main -# endif /* _WIN32_WCE_EMULATION */ -#endif /* main */ - -#if defined(_WIN32_WCE) && _WIN32_WCE < 300 -/* seems to be undefined in Win CE although in online help */ -#define isspace(a) (((CHAR)a == ' ') || ((CHAR)a == '\t')) -#endif /* _WIN32_WCE < 300 */ - -// Turn off the G3D for loop scoping for C++ -#ifdef for -# undef for -#endif - -extern int main(int argc, const char** argv); - -/* Parse a command line buffer into arguments */ -static int ParseCommandLine(char *cmdline, char **argv) { - char *bufp; - int argc; - - argc = 0; - for (bufp = cmdline; *bufp;) { - /* Skip leading whitespace */ - while (isspace(*bufp)) { - ++bufp; - } - /* Skip over argument */ - if (*bufp == '"') { - ++bufp; - if (*bufp) { - if (argv) { - argv[argc] = bufp; - } - ++argc; - } - /* Skip over word */ - while (*bufp && (*bufp != '"')) { - ++bufp; - } - } else { - if (*bufp) { - if (argv) { - argv[argc] = bufp; - } - ++argc; - } - /* Skip over word */ - while (*bufp && !isspace(*bufp)) { - ++bufp; - } - } - if (*bufp) { - if (argv) { - *bufp = '\0'; - } - ++bufp; - } - } - if (argv) { - argv[argc] = NULL; - } - return (argc); -} - -/* Show an error message */ -static void ShowError(const char *title, const char *message) { -/* If USE_MESSAGEBOX is defined, you need to link with user32.lib */ -#ifdef USE_MESSAGEBOX - MessageBox(NULL, message, title, MB_ICONEXCLAMATION | MB_OK); -#else - fprintf(stderr, "%s: %s\n", title, message); -#endif -} - -/* Pop up an out of memory message, returns to Windows */ -static BOOL OutOfMemory(void) { - ShowError("Fatal Error", "Out of memory - aborting"); - return FALSE; -} - - -int WINAPI G3D_WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) { - char **argv; - int argc; - int status; - char *cmdline; -# ifdef _WIN32_WCE - wchar_t *bufp; - int nLen; -# else - char *bufp; - size_t nLen; -# endif - -#ifdef _WIN32_WCE -#error WinCE not supported - /* - nLen = wcslen(szCmdLine) + 128 + 1; - bufp = SDL_stack_alloc(wchar_t, nLen * 2); - wcscpy(bufp, TEXT("\"")); - GetModuleFileName(NULL, bufp + 1, 128 - 3); - wcscpy(bufp + wcslen(bufp), TEXT("\" ")); - wcsncpy(bufp + wcslen(bufp), szCmdLine, nLen - wcslen(bufp)); - nLen = wcslen(bufp) + 1; - cmdline = SDL_stack_alloc(char, nLen); - if (cmdline == NULL) { - return OutOfMemory(); - } - WideCharToMultiByte(CP_ACP, 0, bufp, -1, cmdline, nLen, NULL, NULL); - */ -#else - /* Grab the command line */ - bufp = GetCommandLineA(); - nLen = strlen(bufp) + 1; - cmdline = (char*)malloc(sizeof(char) * nLen); - if (cmdline == NULL) { - return OutOfMemory(); - } - strncpy(cmdline, bufp, nLen); -#endif - - /* Parse it into argv and argc */ - argc = ParseCommandLine(cmdline, NULL); - argv = (char**)malloc(sizeof(char*) * (argc + 1)); - if (argv == NULL) { - return OutOfMemory(); - } - ParseCommandLine(cmdline, argv); - - /* Run the main program */ - status = main(argc, (const char**)argv); - free(argv); - free(cmdline); - - return status; -} - -#endif // if Win32 diff --git a/externals/g3dlite/G3D.lib/source/debugAssert.cpp b/externals/g3dlite/G3D.lib/source/debugAssert.cpp deleted file mode 100644 index 4b24546a661..00000000000 --- a/externals/g3dlite/G3D.lib/source/debugAssert.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/** - @file debugAssert.cpp - - Windows implementation of assertion routines. - - @maintainer Morgan McGuire, graphics3d.com - - @created 2001-08-26 - @edited 2006-02-02 - */ - -#include "G3D/debugAssert.h" -#include "G3D/platform.h" -#ifdef G3D_WIN32 - #include -#endif -#include "G3D/format.h" -#include "G3D/prompt.h" -#include -#include "G3D/debugPrintf.h" -#include "G3D/Log.h" - -#include - -#ifdef _MSC_VER - // disable: "C++ exception handler used" -# pragma warning (push) -# pragma warning (disable : 4530) -#endif - -using namespace std; - -namespace G3D { namespace _internal { - -ConsolePrintHook _consolePrintHook; -AssertionHook _debugHook = _handleDebugAssert_; -AssertionHook _failureHook = _handleErrorCheck_; - -#ifdef G3D_LINUX - Display* x11Display = NULL; - Window x11Window = 0; -#endif - - -#ifdef G3D_WIN32 -static void postToClipboard(const char *text) { - if (OpenClipboard(NULL)) { - HGLOBAL hMem = GlobalAlloc(GHND | GMEM_DDESHARE, strlen(text) + 1); - if (hMem) { - char *pMem = (char*)GlobalLock(hMem); - strcpy(pMem, text); - GlobalUnlock(hMem); - - EmptyClipboard(); - SetClipboardData(CF_TEXT, hMem); - } - - CloseClipboard(); - GlobalFree(hMem); - } -} -#endif - -/** - outTitle should be set before the call - */ -static void createErrorMessage( - const char* expression, - const std::string& message, - const char* filename, - int lineNumber, - std::string& outTitle, - std::string& outMessage) { - - std::string le = ""; - const char* newline = "\n"; - - #ifdef G3D_WIN32 - newline = "\r\n"; - - // The last error value. (Which is preserved across the call). - DWORD lastErr = GetLastError(); - - // The decoded message from FormatMessage - LPTSTR formatMsg = NULL; - - if (NULL == formatMsg) { - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - lastErr, - 0, - (LPTSTR)&formatMsg, - 0, - NULL); - } - - // Make sure the message got translated into something. - LPTSTR realLastErr; - if (NULL != formatMsg) { - realLastErr = formatMsg; - } else { - realLastErr = _T("Last error code does not exist."); - } - - if (lastErr != 0) { - le = G3D::format("Last Error (0x%08X): %s\r\n\r\n", lastErr, (LPCSTR)realLastErr); - } - - // Get rid of the allocated memory from FormatMessage. - if (NULL != formatMsg) { - LocalFree((LPVOID)formatMsg); - } - - char modulePath[MAX_PATH]; - GetModuleFileNameA(NULL, modulePath, MAX_PATH); - - const char* moduleName = strrchr(modulePath, '\\'); - outTitle = outTitle + string(" - ") + string(moduleName ? (moduleName + 1) : modulePath); - - #endif - - // Build the message. - outMessage = - G3D::format("%s%s%sExpression: %s%s%s:%d%s%s%s", - message.c_str(), newline, newline, expression, newline, - filename, lineNumber, newline, newline, le.c_str()); -} - - -bool _handleDebugAssert_( - const char* expression, - const std::string& message, - const char* filename, - int lineNumber, - bool& ignoreAlways, - bool useGuiPrompt) { - - std::string dialogTitle = "Assertion Failure"; - std::string dialogText = ""; - createErrorMessage(expression, message, filename, lineNumber, dialogTitle, dialogText); - - #ifdef G3D_WIN32 - DWORD lastErr = GetLastError(); - postToClipboard(dialogText.c_str()); - debugPrintf("\n%s\n", dialogText.c_str()); - #endif - - const int cBreak = 0; - const int cIgnore = 1; - const int cIgnoreAlways = 2; - const int cAbort = 3; - - static const char* choices[] = {"Debug", "Ignore", "Ignore Always", "Exit"}; - - // Log the error - Log::common()->print(std::string("\n**************************\n\n") + dialogTitle + "\n" + dialogText); - - int result = G3D::prompt(dialogTitle.c_str(), dialogText.c_str(), (const char**)choices, 4, useGuiPrompt); - -# ifdef G3D_WIN32 - // Put the incoming last error back. - SetLastError(lastErr); -# endif - - switch (result) { - // -1 shouldn't actually occur because it means - // that we're in release mode. - case -1: - case cBreak: - return true; - break; - - case cIgnore: - return false; - break; - - case cIgnoreAlways: - ignoreAlways = true; - return false; - break; - - case cAbort: - exit(-1); - break; - } - - // Should never get here - return false; -} - - -bool _handleErrorCheck_( - const char* expression, - const std::string& message, - const char* filename, - int lineNumber, - bool& ignoreAlways, - bool useGuiPrompt) { - - (void)ignoreAlways; - - std::string dialogTitle = "Critical Error"; - std::string dialogText = ""; - - createErrorMessage(expression, message, filename, lineNumber, dialogTitle, dialogText); - - // Log the error - Log::common()->print(std::string("\n**************************\n\n") + dialogTitle + "\n" + dialogText); - #ifdef G3D_WIN32 - DWORD lastErr = GetLastError(); - postToClipboard(dialogText.c_str()); - debugPrintf("\n%s\n", dialogText.c_str()); - #endif - - static const char* choices[] = {"Ok"}; - - std::string m = - std::string("An internal error has occured in your program and it will now close. Details about the error have been reported in \"") + - Log::getCommonLogFilename() + "\"."; - - int result = G3D::prompt("Error", m.c_str(), (const char**)choices, 1, useGuiPrompt); - (void)result; - - return true; -} - - -#ifdef G3D_WIN32 -static HCURSOR oldCursor; -static RECT oldCursorRect; -static POINT oldCursorPos; -static int oldShowCursorCount; -#endif - -void _releaseInputGrab_() { - #ifdef G3D_WIN32 - - GetCursorPos(&oldCursorPos); - - // Stop hiding the cursor if the application hid it. - oldShowCursorCount = ShowCursor(true) - 1; - - if (oldShowCursorCount < -1) { - for (int c = oldShowCursorCount; c < -1; ++c) { - ShowCursor(true); - } - } - - // Set the default cursor in case the application - // set the cursor to NULL. - oldCursor = GetCursor(); - SetCursor(LoadCursor(NULL, IDC_ARROW)); - - // Allow the cursor full access to the screen - GetClipCursor(&oldCursorRect); - ClipCursor(NULL); - - #elif defined(G3D_LINUX) - if (x11Display != NULL) { - XUngrabPointer(x11Display, CurrentTime); - XUngrabKeyboard(x11Display, CurrentTime); - if (x11Window != 0) { - //XUndefineCursor(x11Display, x11Window); - // TODO: Note that we leak this cursor; it should be - // freed in the restore code. - Cursor c = XCreateFontCursor(x11Display, 68); - XDefineCursor(x11Display, x11Window, c); - } - XSync(x11Display, false); - XAllowEvents(x11Display, AsyncPointer, CurrentTime); - XFlush(x11Display); - } - #elif defined(G3D_OSX) - // TODO: OS X - #endif -} - - -void _restoreInputGrab_() { - #ifdef G3D_WIN32 - - // Restore the old clipping region - ClipCursor(&oldCursorRect); - - SetCursorPos(oldCursorPos.x, oldCursorPos.y); - - // Restore the old cursor - SetCursor(oldCursor); - - // Restore old visibility count - if (oldShowCursorCount < 0) { - for (int c = 0; c > oldShowCursorCount; --c) { - ShowCursor(false); - } - } - - #elif defined(G3D_LINUX) - // TODO: Linux - #elif defined(G3D_OSX) - // TODO: OS X - #endif -} - - -}; // internal namespace - -void setAssertionHook(AssertionHook hook) { - G3D::_internal::_debugHook = hook; -} - -AssertionHook assertionHook() { - return G3D::_internal::_debugHook; -} - -void setFailureHook(AssertionHook hook) { - G3D::_internal::_failureHook = hook; -} - -AssertionHook failureHook() { - return G3D::_internal::_failureHook; -} - - -void setConsolePrintHook(ConsolePrintHook h) { - G3D::_internal::_consolePrintHook = h; -} - -ConsolePrintHook consolePrintHook() { - return G3D::_internal::_consolePrintHook; -} - - -std::string __cdecl debugPrint(const std::string& s) { -# ifdef G3D_WIN32 - const int MAX_STRING_LEN = 1024; - - // Windows can't handle really long strings sent to - // the console, so we break the string. - if (s.size() < MAX_STRING_LEN) { - OutputDebugStringA(s.c_str()); - } else { - for (unsigned int i = 0; i < s.size(); i += MAX_STRING_LEN) { - std::string sub = s.substr(i, MAX_STRING_LEN); - OutputDebugStringA(sub.c_str()); - } - } -# else - fprintf(stderr, "%s", s.c_str()); - fflush(stderr); -# endif - - return s; -} - -std::string __cdecl debugPrintf(const char* fmt ...) { - va_list argList; - va_start(argList, fmt); - std::string s = G3D::vformat(fmt, argList); - va_end(argList); - - return debugPrint(consolePrint(s)); -} - -std::string consolePrint(const std::string& s) { - FILE* L = Log::common()->getFile(); - fprintf(L, "%s", s.c_str()); - - if (consolePrintHook()) { - consolePrintHook()(s); - } - - fflush(L); - return s; -} - - -std::string __cdecl consolePrintf(const char* fmt ...) { - va_list argList; - va_start(argList, fmt); - std::string s = G3D::vformat(fmt, argList); - va_end(argList); - - return consolePrint(s); -} - -} // namespace - -#ifdef _MSC_VER -# pragma warning (pop) -#endif diff --git a/externals/g3dlite/G3D.lib/source/fileutils.cpp b/externals/g3dlite/G3D.lib/source/fileutils.cpp deleted file mode 100644 index 3a5e8c715c8..00000000000 --- a/externals/g3dlite/G3D.lib/source/fileutils.cpp +++ /dev/null @@ -1,1092 +0,0 @@ -/** - @file fileutils.cpp - - @author Morgan McGuire, graphics3d.com - - @author 2002-06-06 - @edited 2008-01-20 - */ - -#include "G3D/platform.h" -#include "G3D/fileutils.h" -#include "G3D/BinaryInput.h" -#include "G3D/g3dmath.h" -#include -#include -#include -#include -#include "G3D/stringutils.h" -#include "G3D/Set.h" - -#include - -#ifdef G3D_WIN32 - // Needed for _getcwd - #include - #include -#else - #include - #include - #include - #define _getcwd getcwd -#endif -#include -#include "G3D/BinaryOutput.h" - -#ifdef G3D_WIN32 - //for _mkdir and _stat -# include -#else -# define _stat stat -#endif - - -namespace G3D { - -namespace _internal { - Set currentFilesUsed; -} - -std::string pathConcat(const std::string& dirname, const std::string& file) { - // Ensure that the directory ends in a slash - if ((dirname.size() != 0) && - (dirname[dirname.size() - 1] != '/') && - (dirname[dirname.size() - 1] != '\\') && - (dirname[dirname.size() - 1] != ':')) { - return dirname + '/' + file; - } else { - return dirname + file; - } -} - -std::string resolveFilename(const std::string& filename) { - if (filename.size() >= 1) { - if ((filename[0] == '/') || (filename[0] == '\\')) { - // Already resolved - return filename; - } else { - - #ifdef G3D_WIN32 - if ((filename.size() >= 2) && (filename[1] == ':')) { - // There is a drive spec on the front. - if ((filename.size() >= 3) && ((filename[2] == '\\') || - (filename[2] == '/'))) { - // Already fully qualified - return filename; - } else { - // The drive spec is relative to the - // working directory on that drive. - debugAssertM(false, "Files of the form d:path are" - " not supported (use a fully qualified" - " name)."); - return filename; - } - } - #endif - } - } - - char buffer[1024]; - - // Prepend the working directory. - _getcwd(buffer, 1024); - - return format("%s/%s", buffer, filename.c_str()); -} - -bool zipfileExists(const std::string& filename) { - std::string outZipfile; - std::string outInternalFile; - return zipfileExists(filename, outZipfile, outInternalFile); -} - -std::string readWholeFile( - const std::string& filename) { - - _internal::currentFilesUsed.insert(filename); - - std::string s; - - debugAssert(filename != ""); - if (fileExists(filename, false)) { - - int64 length = fileLength(filename); - - char* buffer = (char*)System::alignedMalloc(length + 1, 16); - debugAssert(buffer); - FILE* f = fopen(filename.c_str(), "rb"); - debugAssert(f); - int ret = fread(buffer, 1, length, f); - debugAssert(ret == length);(void)ret; - fclose(f); - - buffer[length] = '\0'; - s = std::string(buffer); - - System::alignedFree(buffer); - - } else if (zipfileExists(filename)) { - - void* zipBuffer; - size_t length; - zipRead(filename, zipBuffer, length); - - char* buffer = (char*)System::alignedMalloc(length + 1, 16); - System::memcpy(buffer,zipBuffer, length + 1); - zipClose(zipBuffer); - - buffer[length] = '\0'; - s = std::string(buffer); - System::alignedFree(buffer); - } else { - debugAssertM(false, filename + " not found"); - } - - return s; -} - - -void zipRead(const std::string& file, - void*& data, - size_t& length) { - std::string zip, desiredFile; - - if (zipfileExists(file, zip, desiredFile)) { - unzFile f = unzOpen(zip.c_str()); - { - unzLocateFile(f, desiredFile.c_str(), 2); - unz_file_info info; - unzGetCurrentFileInfo(f, &info, NULL, 0, NULL, 0, NULL, 0); - length = info.uncompressed_size; - // sets machines up to use MMX, if they want - data = System::alignedMalloc(length, 16); - unzOpenCurrentFile(f); - { - int test = unzReadCurrentFile(f, data, length); - debugAssertM((size_t)test == length, - desiredFile + " was corrupt because it unzipped to the wrong size."); - (void)test; - } - unzCloseCurrentFile(f); - } - unzClose(f); - } else { - data = NULL; - } -} - - -void zipClose(void* data) { - System::alignedFree(data); -} - - -int64 fileLength(const std::string& filename) { - struct _stat st; - int result = _stat(filename.c_str(), &st); - - if (result == -1) { - std::string zip, contents; - if(zipfileExists(filename, zip, contents)){ - int64 requiredMem; - - unzFile f = unzOpen(zip.c_str()); - { - unzLocateFile(f, contents.c_str(), 2); - unz_file_info info; - unzGetCurrentFileInfo(f, &info, NULL, 0, NULL, 0, NULL, 0); - requiredMem = info.uncompressed_size; - } - unzClose(f); - return requiredMem; - } else { - return -1; - } - } - - return st.st_size; -} - -/** Used by robustTmpfile. Returns nonzero if fread, fwrite, and fseek all -succeed on the file. - @author Morgan McGuire, morgan@graphics3d.com */ -static int isFileGood(FILE* f) { - - int x, n, result; - - /* Must be a valid file handle */ - if (f == NULL) { - return 0; - } - - /* Try to write */ - x = 1234; - n = fwrite(&x, sizeof(int), 1, f); - - if (n != 1) { - return 0; - } - - /* Seek back to the beginning */ - result = fseek(f, 0, SEEK_SET); - if (result != 0) { - return 0; - } - - /* Read */ - n = fread(&x, sizeof(int), 1, f); - if (n != 1) { - return 0; - } - - /* Seek back to the beginning again */ - fseek(f, 0, SEEK_SET); - - return 1; -} - -FILE* createTempFile() { - FILE* t = NULL; - -//# ifdef G3D_WIN32 - t = tmpfile(); -//# else -// // On Unix, tmpfile generates a warning for any code that links against it. -// const char* tempfilename = "/tmp/g3dtemp.XXXXXXXX"; -// mktemp(tempfilename); -// t = fopen(tempfilename, "w"); -//# endif - -# ifdef _WIN32 - char* n = NULL; -# endif - char name[256]; - - if (isFileGood(t)) { - return t; - } - -# ifdef G3D_WIN32 - /* tmpfile failed; try the tmpnam routine */ - t = fopen(tmpnam(NULL), "w+"); - if (isFileGood(t)) { - return t; - } - - n = _tempnam("c:/tmp/", "t"); - /* Try to create something in C:\tmp */ - t = fopen(n, "w+"); - if (isFileGood(t)) { - return t; - } - - /* Try c:\temp */ - n = _tempnam("c:/temp/", "t"); - t = fopen(n, "w+"); - if (isFileGood(t)) { - return t; - } - - /* try the current directory */ - n = _tempnam("./", "t"); - t = fopen(n, "w+"); - if (isFileGood(t)) { - return t; - } - - sprintf(name, "%s/tmp%d", "c:/temp", rand()); - t = fopen(name, "w+"); - if (isFileGood(t)) { - return t; - } - - /* Try some hardcoded paths */ - sprintf(name, "%s/tmp%d", "c:/tmp", rand()); - t = fopen(name, "w+"); - if (isFileGood(t)) { - return t; - } -# else - sprintf(name, "%s/tmp%d", "/tmp", rand()); - t = fopen(name, "w+"); - if (isFileGood(t)) { - return t; - } -#endif - - sprintf(name, "tmp%d", rand()); - t = fopen(name, "w+"); - if (isFileGood(t)) { - return t; - } - - fprintf(stderr, "Unable to create a temporary file; robustTmpfile returning NULL\n"); - - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// -void writeWholeFile( - const std::string& filename, - const std::string& str, - bool flush) { - - // Make sure the directory exists. - std::string root, base, ext, path; - Array pathArray; - parseFilename(filename, root, pathArray, base, ext); - - path = root + stringJoin(pathArray, '/'); - if (! fileExists(path, false)) { - createDirectory(path); - } - - FILE* file = fopen(filename.c_str(), "wb"); - - debugAssert(file); - - fwrite(str.c_str(), str.size(), 1, file); - - if (flush) { - fflush(file); - } - fclose(file); -} - -/////////////////////////////////////////////////////////////////////////////// - -/** - Creates the directory (which may optionally end in a /) - and any parents needed to reach it. - */ -void createDirectory( - const std::string& dir) { - - if (dir == "") { - return; - } - - std::string d; - - // Add a trailing / if there isn't one. - switch (dir[dir.size() - 1]) { - case '/': - case '\\': - d = dir; - break; - - default: - d = dir + "/"; - } - - // If it already exists, do nothing - if (fileExists(d.substr(0, d.size() - 1)), false) { - return; - } - - // Parse the name apart - std::string root, base, ext; - Array path; - - std::string lead; - parseFilename(d, root, path, base, ext); - debugAssert(base == ""); - debugAssert(ext == ""); - - // Begin with an extra period so "c:\" becomes "c:\.\" after - // appending a path and "c:" becomes "c:.\", not root: "c:\" - std::string p = root + "."; - - // Create any intermediate that doesn't exist - for (int i = 0; i < path.size(); ++i) { - p += "/" + path[i]; - if (! fileExists(p, false)) { - // Windows only requires one argument to mkdir, - // where as unix also requires the permissions. -# ifndef G3D_WIN32 - mkdir(p.c_str(), 0777); -# else - _mkdir(p.c_str()); -# endif - } - } -} - -/////////////////////////////////////////////////////////////////////////////// - -bool fileExists( - const std::string& filename, - const bool lookInZipfiles) { - - if (filename == "") { - return true; - } - - - // Useful for debugging - //char curdir[1024]; _getcwd(curdir, 1024); - - struct _stat st; - int ret = _stat(filename.c_str(), &st); - - // _stat returns zero on success - bool exists = (ret == 0); - - if (exists) { - // Exists - return true; - } else if (lookInZipfiles) { - // Does not exist standalone, but might exist in a zipfile - - // These output arguments will be ignored - std::string zipDir, internalPath; - return zipfileExists(filename, zipDir, internalPath); - } else { - // Does not exist - return false; - } -} - -/////////////////////////////////////////////////////////////////////////////// - -/* Helper methods for zipfileExists()*/ -// Given a string (the drive) and an array (the path), computes the directory -static void _zip_resolveDirectory(std::string& completeDir, const std::string& drive, const Array& path, const int length){ - completeDir = drive; - int tempLength; - // if the given length is longer than the array, we correct it - if(length > path.length()){ - tempLength = path.length(); - } else{ - tempLength = length; - } - - for(int t = 0; t < tempLength; ++t){ - if(t > 0){ - completeDir += "/"; - } - completeDir += path[t]; - } -} - - -// assumes that zipDir references a .zip file -static bool _zip_zipContains(const std::string& zipDir, const std::string& desiredFile){ - unzFile f = unzOpen(zipDir.c_str()); - //the last parameter, an int, determines case sensitivity: - //1 is sensitive, 2 is not, 0 is default - int test = unzLocateFile(f, desiredFile.c_str(), 2); - unzClose(f); - if(test == UNZ_END_OF_LIST_OF_FILE){ - return false; - } - return true; -} - - -// If no zipfile exists, outZipfile and outInternalFile are unchanged -bool zipfileExists(const std::string& filename, std::string& outZipfile, - std::string& outInternalFile){ - if (fileExists(filename, false)) { - // Not inside a zipfile if the file itself exists - return false; - } else { - Array path; - std::string drive, base, ext, zipfile, infile; - parseFilename(filename, drive, path, base, ext); - - // Put the filename back together - if ((base != "") && (ext != "")) { - infile = base + "." + ext; - } else { - infile = base + ext; - } - - // Remove "." from path - for (int i = 0; i < path.length(); ++i) { - if (path[i] == ".") { - path.remove(i); - --i; - } - } - - // Remove ".." from path - for (int i = 1; i < path.length(); ++i) { - if ((path[i] == "..") && (i > 0) && (path[i - 1] != "..")) { - // Remove both i and i - 1 - path.remove(i - 1, 2); - i -= 2; - } - } - - // Walk the path backwards, accumulating pieces onto the infile until - // we find a zipfile that contains it - for (int t = 0; t < path.length(); ++t){ - _zip_resolveDirectory(zipfile, drive, path, path.length() - t); - if (t > 0) { - infile = path[path.length() - t] + "/" + infile; - } - - if (fileExists(zipfile, false)) { - // test if it actually is a zipfile - // if not, return false, a bad - // directory structure has been given, - // not a .zip - if (isZipfile(zipfile)){ - - if (_zip_zipContains(zipfile, infile)){ - outZipfile = zipfile; - outInternalFile = infile; - return true; - } else { - return false; - } - } else { - // the directory structure was valid but did not point to a .zip - return false; - } - } - - } - } - - // not a valid directory structure ever, - // obviously no .zip was found within the path - return false; -} - -/////////////////////////////////////////////////////////////////////////////// - -std::string generateFilenameBase(const std::string& prefix) { - Array exist; - - // Note "template" is a reserved word in C++ - std::string templat = prefix + System::currentDateString(); - getFiles(templat + "*", exist); - - // Remove extensions - for (int i = 0; i < exist.size(); ++i) { - exist[i] = filenameBase(exist[i]); - } - - int num = 0; - std::string result; - templat += "_%03d"; - do { - result = format(templat.c_str(), num); - ++num; - } while (exist.contains(result)); - - return result; -} - -/////////////////////////////////////////////////////////////////////////////// - -void copyFile( - const std::string& source, - const std::string& dest) { - - #ifdef G3D_WIN32 - CopyFileA(source.c_str(), dest.c_str(), FALSE); - #else - // TODO: don't use BinaryInput and BinaryOutput - // Read it all in, then dump it out - BinaryInput in(source, G3D_LITTLE_ENDIAN); - BinaryOutput out(dest, G3D_LITTLE_ENDIAN); - out.writeBytes(in.getCArray(), in.size()); - out.commit(false); - #endif -} - -////////////////////////////////////////////////////////////////////////////// - -void parseFilename( - const std::string& filename, - std::string& root, - Array& path, - std::string& base, - std::string& ext) { - - std::string f = filename; - - root = ""; - path.clear(); - base = ""; - ext = ""; - - if (f == "") { - // Empty filename - return; - } - - // See if there is a root/drive spec. - if ((f.size() >= 2) && (f[1] == ':')) { - - if ((f.size() > 2) && isSlash(f[2])) { - - // e.g. c:\foo - root = f.substr(0, 3); - f = f.substr(3, f.size() - 3); - - } else { - - // e.g. c:foo - root = f.substr(2); - f = f.substr(2, f.size() - 2); - - } - - } else if ((f.size() >= 2) & isSlash(f[0]) && isSlash(f[1])) { - - // e.g. //foo - root = f.substr(0, 2); - f = f.substr(2, f.size() - 2); - - } else if (isSlash(f[0])) { - - root = f.substr(0, 1); - f = f.substr(1, f.size() - 1); - - } - - // Pull the extension off - { - // Find the period - size_t i = f.rfind('.'); - - if (i != std::string::npos) { - // Make sure it is after the last slash! - size_t j = iMax(f.rfind('/'), f.rfind('\\')); - if ((j == std::string::npos) || (i > j)) { - ext = f.substr(i + 1, f.size() - i - 1); - f = f.substr(0, i); - } - } - } - - // Pull the basename off - { - // Find the last slash - size_t i = iMax(f.rfind('/'), f.rfind('\\')); - - if (i == std::string::npos) { - - // There is no slash; the basename is the whole thing - base = f; - f = ""; - - } else if ((i != std::string::npos) && (i < f.size() - 1)) { - - base = f.substr(i + 1, f.size() - i - 1); - f = f.substr(0, i); - - } - } - - // Parse what remains into path. - size_t prev, cur = 0; - - while (cur < f.size()) { - prev = cur; - - // Allow either slash - size_t i = f.find('/', prev + 1); - size_t j = f.find('\\', prev + 1); - if (i == std::string::npos) { - i = f.size(); - } - - if (j == std::string::npos) { - j = f.size(); - } - - cur = iMin(i, j); - - if (cur == std::string::npos) { - cur = f.size(); - } - - path.append(f.substr(prev, cur - prev)); - ++cur; - } -} - - -/** - Helper for getFileList and getDirectoryList. - - @param wantFiles If false, returns the directories, otherwise - returns the files. - @param includePath If true, the names include paths - */ -static void getFileOrDirListNormal -( - const std::string& filespec, - Array& files, - bool wantFiles, - bool includePath) { - - bool test = wantFiles ? true : false; - - std::string path = ""; - - // Find the place where the path ends and the file-spec begins - size_t i = filespec.rfind('/'); - size_t j = filespec.rfind('\\'); - - // Drive letters on Windows can separate a path - size_t k = filespec.rfind(':'); - - if (((j != std::string::npos) && (j > i)) || - (i == std::string::npos)) { - i = j; - } - - if (((k != std::string::npos) && (k > i)) || - (i == std::string::npos)) { - i = k; - } - - // If there is a path, pull it off - if (i != std::string::npos) { - path = filespec.substr(0, i + 1); - } - - std::string prefix = path; - - if (path.size() > 0) { - // Strip the trailing character - path = path.substr(0, path.size() - 1); - } - -# ifdef G3D_WIN32 - { - struct _finddata_t fileinfo; - - long handle = _findfirst(filespec.c_str(), &fileinfo); - int result = handle; - - while (result != -1) { - if ((((fileinfo.attrib & _A_SUBDIR) == 0) == test) && - strcmp(fileinfo.name, ".") && - strcmp(fileinfo.name, "..")) { - - if (includePath) { - files.append(prefix + fileinfo.name); - } else { - files.append(fileinfo.name); - } - } - - result = _findnext(handle, &fileinfo); - } - } -# else - { - if (path == "") { - // Empty paths don't work on Unix - path = "."; - } - - // Unix implementation - DIR* dir = opendir(path.c_str()); - - if (dir != NULL) { - struct dirent* entry = readdir(dir); - - while (entry != NULL) { - - // Exclude '.' and '..' - if ((strcmp(entry->d_name, ".") != 0) && - (strcmp(entry->d_name, "..") != 0)) { - - // Form a name with a path - std::string filename = prefix + entry->d_name; - // See if this is a file or a directory - struct _stat st; - bool exists = _stat(filename.c_str(), &st) != -1; - - if (exists && - - // Make sure it has the correct type - (((st.st_mode & S_IFDIR) == 0) == test) && - - // Make sure it matches the wildcard - (fnmatch(filespec.c_str(), - filename.c_str(), - FNM_PATHNAME) == 0)) { - - if (includePath) { - files.append(filename); - } else { - files.append(entry->d_name); - } - } - } - - entry = readdir(dir); - } - closedir(dir); - } - } -# endif -} - -/** - - c:/temp/foo.zip/plainsky\\* -" path " - "prefix " - - @param path The zipfile name (no trailing slash) - @param prefix Directory inside the zipfile. No leading slash, must have trailing slash if non-empty. - @param file Name inside the zipfile that we are testing to see if it matches prefix + "*" - */ -static void _zip_addEntry(const std::string& path, - const std::string& prefix, - const std::string& file, - Set& files, - bool wantFiles, - bool includePath) { - - // Make certain we are within the desired parent folder (prefix) - if (beginsWith(file, prefix)) { - // validityTest was prefix/file - - // Extract everything to the right of the prefix - std::string s = file.substr(prefix.length()); - - if (s == "") { - // This was the name of the prefix - return; - } - - // See if there are any slashes - size_t slashPos = s.find('/'); - - bool add = false; - - if (slashPos == std::string::npos) { - // No slashes, so s must be a file - add = wantFiles; - } else if (! wantFiles) { - // Not all zipfiles list directories as explicit entries. - // Because of this, if we're looking for directories and see - // any path longer than prefix, we must add the subdirectory. - // The Set will fix duplicates for us. - s = s.substr(0, slashPos); - add = true; - } - - if (add) { - if (includePath) { - files.insert(path + "/" + prefix + s); - } else { - files.insert(s); - } - } - } -} - - -static void getFileOrDirListZip(const std::string& path, - const std::string& prefix, - Array& files, - bool wantFiles, - bool includePath){ - unzFile f = unzOpen(path.c_str()); - - enum {MAX_STRING_LENGTH=1024}; - char filename[MAX_STRING_LENGTH]; - Set fileSet; - - do { - - // prefix is valid, either "" or a subfolder - unzGetCurrentFileInfo(f, NULL, filename, MAX_STRING_LENGTH, NULL, 0, NULL, 0); - _zip_addEntry(path, prefix, filename, fileSet, wantFiles, includePath); - - } while (unzGoToNextFile(f) != UNZ_END_OF_LIST_OF_FILE); - - unzClose(f); - - fileSet.getMembers(files); -} - - -static void determineFileOrDirList( - const std::string& filespec, - Array& files, - bool wantFiles, - bool includePath) { - - // if it is a .zip, prefix will specify the folder within - // whose contents we want to see - std::string prefix = ""; - std::string path = filenamePath(filespec); - - if ((path.size() > 0) && isSlash(path[path.size() - 1])) { - // Strip the trailing slash - path = path.substr(0, path.length() -1); - } - - if (fileExists(path, false)) { - if (isZipfile(path)) { - // .zip should only work if * is specified as the Base + Ext - // Here, we have been asked for the root's contents - debugAssertM(filenameBaseExt(filespec) == "*", "Can only call getFiles/getDirs on zipfiles using '*' wildcard"); - getFileOrDirListZip(path, prefix, files, wantFiles, includePath); - } else { - // It is a normal directory - getFileOrDirListNormal(filespec, files, wantFiles, includePath); - } - } else if (zipfileExists(filenamePath(filespec), path, prefix)) { - // .zip should only work if * is specified as the Base + Ext - // Here, we have been asked for the contents of a folder within the .zip - debugAssertM(filenameBaseExt(filespec) == "*", "Can only call getFiles/getDirs on zipfiles using '*' wildcard"); - getFileOrDirListZip(path, prefix, files, wantFiles, includePath); - } -} - - -void getFiles( - const std::string& filespec, - Array& files, - bool includePath) { - - determineFileOrDirList(filespec, files, true, includePath); -} - - -void getDirs( - const std::string& filespec, - Array& files, - bool includePath) { - - determineFileOrDirList(filespec, files, false, includePath); -} - - -std::string filenameBaseExt(const std::string& filename) { - int i = filename.rfind("/"); - int j = filename.rfind("\\"); - - if ((j > i) && (j >= 0)) { - i = j; - } - -# ifdef G3D_WIN32 - j = filename.rfind(":"); - if ((i == -1) && (j >= 0)) { - i = j; - } -# endif - - if (i == -1) { - return filename; - } else { - return filename.substr(i + 1, filename.length() - i); - } -} - - -std::string filenameBase(const std::string& s) { - std::string drive; - std::string base; - std::string ext; - Array path; - - parseFilename(s, drive, path, base, ext); - return base; -} - - -std::string filenameExt(const std::string& filename) { - int i = filename.rfind("."); - if (i >= 0) { - return filename.substr(i + 1, filename.length() - i); - } else { - return ""; - } -} - - -std::string filenamePath(const std::string& filename) { - int i = filename.rfind("/"); - int j = filename.rfind("\\"); - - if ((j > i) && (j >= 0)) { - i = j; - } - -# ifdef G3D_WIN32 - j = filename.rfind(":"); - if ((i == -1) && (j >= 0)) { - i = j; - } -# endif - - if (i == -1) { - return ""; - } else { - return filename.substr(0, i+1); - } -} - - -bool isZipfile(const std::string& filename) { - - FILE* f = fopen(filename.c_str(), "r"); - if (f == NULL) { - return false; - } - uint8 header[4]; - fread(header, 4, 1, f); - - const uint8 zipHeader[4] = {0x50, 0x4b, 0x03, 0x04}; - for (int i = 0; i < 4; ++i) { - if (header[i] != zipHeader[i]) { - fclose(f); - return false; - } - } - - fclose(f); - return true; -} - - -bool isDirectory(const std::string& filename) { - struct _stat st; - bool exists = _stat(filename.c_str(), &st) != -1; - return exists && ((st.st_mode & S_IFDIR) != 0); -} - - -bool filenameContainsWildcards(const std::string& filename) { - return (filename.find('*') != std::string::npos) || (filename.find('?') != std::string::npos); -} - - -bool fileIsNewer(const std::string& src, const std::string& dst) { - struct _stat sts; - bool sexists = _stat(src.c_str(), &sts) != -1; - - struct _stat dts; - bool dexists = _stat(dst.c_str(), &dts) != -1; - - return sexists && ((! dexists) || (sts.st_mtime > dts.st_mtime)); -} - - -Array filesUsed() { - Array f; - _internal::currentFilesUsed.getMembers(f); - return f; -} - -} - -#ifndef G3D_WIN32 - #undef _stat -#endif diff --git a/externals/g3dlite/G3D.lib/source/filter.cpp b/externals/g3dlite/G3D.lib/source/filter.cpp deleted file mode 100644 index f6c0467820f..00000000000 --- a/externals/g3dlite/G3D.lib/source/filter.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/** - @file filter.cpp - - @author Morgan McGuire, matrix@graphics3d.com - @created 2007-03-01 - @edited 2007-03-01 - - Copyright 2000-2007, Morgan McGuire. - All rights reserved. - */ -#include "G3D/filter.h" - -namespace G3D { - -void gaussian1D(Array& coeff, int N, float std) { - coeff.resize(N); - float sum = 0.0f; - for (int i = 0; i < N; ++i) { - float x = i - (N - 1) / 2.0f; - float p = -square(x / std) / 2.0f; - float y = exp(p); - coeff[i] = y; - sum += y; - } - - for (int i = 0; i < N; ++i) { - coeff[i] /= sum; - } -} - - -} // namespace diff --git a/externals/g3dlite/G3D.lib/source/format.cpp b/externals/g3dlite/G3D.lib/source/format.cpp deleted file mode 100644 index d9d1b516393..00000000000 --- a/externals/g3dlite/G3D.lib/source/format.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/** - @file format.cpp - - @author Morgan McGuire, graphics3d.com - - @created 2000-09-09 - @edited 2006-08-14 -*/ - -#include "G3D/format.h" -#include "G3D/platform.h" -#include "G3D/System.h" - -#ifdef _MSC_VER - // disable: "C++ exception handler used" -# pragma warning (push) -# pragma warning (disable : 4530) -#endif // _MSC_VER - -// If your platform does not have vsnprintf, you can find a -// implementation at http://www.ijs.si/software/snprintf/ - -namespace G3D { - -std::string __cdecl format(const char* fmt,...) { - va_list argList; - va_start(argList,fmt); - std::string result = vformat(fmt, argList); - va_end(argList); - - return result; -} - -#if defined(_MSC_VER) && (_MSC_VER >= 1300) -// Both MSVC seems to use the non-standard vsnprintf -// so we are using vscprintf to determine buffer size, however -// only MSVC7 and up headers include vscprintf for some reason. -std::string vformat(const char *fmt, va_list argPtr) { - // We draw the line at a 1MB string. - const int maxSize = 1000000; - - // If the string is less than 161 characters, - // allocate it on the stack because this saves - // the malloc/free time. - const int bufSize = 161; - char stackBuffer[bufSize]; - - // MSVC does not support va_copy - int actualSize = _vscprintf(fmt, argPtr) + 1; - - if (actualSize > bufSize) { - - // Now use the heap. - char* heapBuffer = NULL; - - if (actualSize < maxSize) { - - heapBuffer = (char*)System::malloc(maxSize + 1); - _vsnprintf(heapBuffer, maxSize, fmt, argPtr); - heapBuffer[maxSize] = '\0'; - } else { - heapBuffer = (char*)System::malloc(actualSize); - vsprintf(heapBuffer, fmt, argPtr); - } - - std::string formattedString(heapBuffer); - System::free(heapBuffer); - return formattedString; - } else { - - vsprintf(stackBuffer, fmt, argPtr); - return std::string(stackBuffer); - } -} - -#elif defined(_MSC_VER) && (_MSC_VER < 1300) - -std::string vformat(const char *fmt, va_list argPtr) { - // We draw the line at a 1MB string. - const int maxSize = 1000000; - - // If the string is less than 161 characters, - // allocate it on the stack because this saves - // the malloc/free time. - const int bufSize = 161; - char stackBuffer[bufSize]; - - // MSVC6 doesn't support va_copy, however it also seems to compile - // correctly if we just pass our argument list along. Note that - // this whole code block is only compiled if we're on MSVC6 anyway - int actualWritten = _vsnprintf(stackBuffer, bufSize, fmt, argPtr); - - // Not a big enough buffer, bufSize characters written - if (actualWritten == -1) { - - int heapSize = 512; - double powSize = 1.0; - char* heapBuffer = (char*)System::malloc(heapSize); - - while ((_vsnprintf(heapBuffer, heapSize, fmt, argPtr) == -1) && - (heapSize < maxSize)) { - - heapSize = iCeil(heapSize * ::pow((double)2.0, powSize++)); - heapBuffer = (char*)System::realloc(heapBuffer, heapSize); - } - - heapBuffer[heapSize-1] = '\0'; - - std::string heapString(heapBuffer); - System::free(heapBuffer); - - return heapString; - } else { - - return std::string(stackBuffer); - } -} - -#else - -// glibc 2.1 has been updated to the C99 standard -std::string vformat(const char* fmt, va_list argPtr) { - // If the string is less than 161 characters, - // allocate it on the stack because this saves - // the malloc/free time. The number 161 is chosen - // to support two lines of text on an 80 character - // console (plus the null terminator). - const int bufSize = 161; - char stackBuffer[bufSize]; - - va_list argPtrCopy; - va_copy(argPtrCopy, argPtr); - int numChars = vsnprintf(stackBuffer, bufSize, fmt, argPtrCopy); - va_end(argPtrCopy); - - if (numChars >= bufSize) { - // We didn't allocate a big enough string. - char* heapBuffer = (char*)System::malloc((numChars + 1) * sizeof(char)); - - debugAssert(heapBuffer); - int numChars2 = vsnprintf(heapBuffer, numChars + 1, fmt, argPtr); - debugAssert(numChars2 == numChars); - (void)numChars2; - - std::string result(heapBuffer); - - System::free(heapBuffer); - - return result; - - } else { - - return std::string(stackBuffer); - - } -} - -#endif - -} // namespace - -#ifdef _MSC_VER -# pragma warning (pop) -#endif diff --git a/externals/g3dlite/G3D.lib/source/g3dmath.cpp b/externals/g3dlite/G3D.lib/source/g3dmath.cpp deleted file mode 100644 index 95c9e16cc24..00000000000 --- a/externals/g3dlite/G3D.lib/source/g3dmath.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/** - @file g3dmath.cpp - - @author Morgan McGuire, graphics3d.com - - @created 2001-06-02 - @edited 2004-02-24 - */ - -#include "G3D/g3dmath.h" -#include - -namespace G3D { - -float gaussRandom(float mean, float stdev) { - - // Using Box-Mueller method from http://www.taygeta.com/random/gaussian.html - // Modified to specify standard deviation and mean of distribution - float w, x1, x2; - - // Loop until w is less than 1 so that log(w) is negative - do { - x1 = uniformRandom(-1.0, 1.0); - x2 = uniformRandom(-1.0, 1.0); - - w = float(square(x1) + square(x2)); - } while (w > 1.0f); - - // Transform to gassian distribution - // Multiply by sigma (stdev ^ 2) and add mean. - return x2 * (float)square(stdev) * sqrtf((-2.0f * logf(w) ) / w) + mean; -} - - -int highestBit(uint32 x) { - // Binary search. - int base = 0; - - if (x & 0xffff0000) { - base = 16; - x >>= 16; - } - if (x & 0x0000ff00) { - base += 8; - x >>= 8; - } - if (x & 0x000000f0) { - base += 4; - x >>= 4; - } - - static const int lut[] = {-1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3}; - return base + lut[x]; -} - - -int iRandom(int low, int high) { - int r = iFloor(low + (high - low + 1) * (double)rand() / RAND_MAX); - - // There is a *very small* chance of generating - // a number larger than high. - if (r > high) { - return high; - } else { - return r; - } -} - - -} diff --git a/externals/g3dlite/G3D.lib/source/license.cpp b/externals/g3dlite/G3D.lib/source/license.cpp deleted file mode 100644 index b362ad3f45f..00000000000 --- a/externals/g3dlite/G3D.lib/source/license.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/** - @file license.cpp - - @author Morgan McGuire, graphics3d.com - - @created 2004-04-15 - @edited 2004-04-15 -*/ - -#include "G3D/format.h" -#include - -namespace G3D { - -std::string license() { - return format( - -"This software is based in part on the PNG Reference Library which is\n" -"Copyright (c) 2004 Glenn Randers-Pehrson\n\n" -"This software is based in part on the work of the Independent JPEG Group.\n\n" -"This software is based on part on the FFmpeg libavformat and libavcodec libraries\n" -"(\"FFmpeg\", http://ffmpeg.mplayerhq.hu), which are included under the terms of the\n" -"GNU Lesser General Public License (LGPL), (http://www.gnu.org/copyleft/lesser.html).\n\n" -"%s" -"This program uses the G3D Library (http://g3d-cpp.sf.net), which\n" -"is licensed under the \"BSD\" Open Source license. The Graphics3D library\n" -"source code is Copyright © 2000-2008, Morgan McGuire, All rights reserved.\n" -"The BSD license requires the following statement regarding G3D:\n" -"\n" -"Redistribution and use in source and binary forms, with or without\n" -"modification, are permitted provided that the following conditions\n" -"are met:\n" -"\n" -"Redistributions of source code must retain the above copyright\n" -"notice, this list of conditions and the following disclaimer.\n" -"\n" -"Redistributions in binary form must reproduce the above copyright\n" -"notice, this list of conditions and the following disclaimer in the\n" -"documentation and/or other materials provided with the distribution.\n" -"\n" -"Neither the name of Morgan McGuire, Brown University, Williams College, nor the names\n" -"of the G3D contributors may be used to endorse or promote products derived\n" -"from this software without specific prior written permission.\n" -"\n" -"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" -"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" -"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" -"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" -"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" -"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" -"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" -"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" -"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" -"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" -"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" -"\n\n" -"G3D VERSION %d\n", - -#ifdef G3D_WIN32 - "" // Win32 doesn't use SDL -#else - "This software uses the Simple DirectMedia Layer library (\"SDL\",\n" - "http://www.libsdl.org), which is included under the terms of the\n" - "GNU Lesser General Public License, (http://www.gnu.org/copyleft/lesser.html).\n\n" -#endif -, -G3D_VER); -} - -} diff --git a/externals/g3dlite/G3D.lib/source/prompt.cpp b/externals/g3dlite/G3D.lib/source/prompt.cpp deleted file mode 100644 index 1fb3bd4cfee..00000000000 --- a/externals/g3dlite/G3D.lib/source/prompt.cpp +++ /dev/null @@ -1,716 +0,0 @@ -/** - @file prompt.cpp - - @author Morgan McGuire, morgan@graphics3d.com - @cite Windows dialog interface by Max McGuire, mmcguire@ironlore.com - @cite Font setting code by Kurt Miller, kurt@flipcode.com - - @created 2000-08-26 - @edited 2005-01-14 - */ - -#include "G3D/prompt.h" -#include "G3D/platform.h" - -#include - -#ifdef G3D_WIN32 -# include -# include -#else -# define _getch getchar -#endif - -#ifdef G3D_OSX -# include -#endif - -namespace G3D { - -#ifdef G3D_WIN32 - -namespace _internal { -/** - Generic Win32 dialog facility. - @author Max McGuire - */ -class DialogTemplate { -public: - - DialogTemplate(LPCSTR caption, DWORD style, - int x, int y, int w, int h, - LPCSTR font = NULL, WORD fontSize = 8) { - - usedBufferLength = sizeof(DLGTEMPLATE); - totalBufferLength = usedBufferLength; - - dialogTemplate = (DLGTEMPLATE*)malloc(totalBufferLength); - - dialogTemplate->style = style; - - if (font != NULL) { - dialogTemplate->style |= DS_SETFONT; - } - - dialogTemplate->x = (short)x; - dialogTemplate->y = (short)y; - dialogTemplate->cx = (short)w; - dialogTemplate->cy = (short)h; - dialogTemplate->cdit = 0; - - dialogTemplate->dwExtendedStyle = 0; - - // The dialog box doesn't have a menu or a special class - AppendData("\0", 2); - AppendData("\0", 2); - - // Add the dialog's caption to the template - - AppendString(caption); - - if (font != NULL) { - AppendData(&fontSize, sizeof(WORD)); - AppendString(font); - } - } - - void AddComponent(LPCSTR type, LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) { - - DLGITEMTEMPLATE item; - - item.style = style; - item.x = (short)x; - item.y = (short)y; - item.cx = (short)w; - item.cy = (short)h; - item.id = id; - - item.dwExtendedStyle = exStyle; - - AppendData(&item, sizeof(DLGITEMTEMPLATE)); - - AppendString(type); - AppendString(caption); - - WORD creationDataLength = 0; - AppendData(&creationDataLength, sizeof(WORD)); - - // Increment the component count - dialogTemplate->cdit++; - - } - - - void AddButton(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) { - - AddStandardComponent(0x0080, caption, style, exStyle, x, y, w, h, id); - - WORD creationDataLength = 0; - AppendData(&creationDataLength, sizeof(WORD)); - - } - - - void AddEditBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) { - - AddStandardComponent(0x0081, caption, style, exStyle, x, y, w, h, id); - - WORD creationDataLength = 0; - AppendData(&creationDataLength, sizeof(WORD)); - - } - - - void AddStatic(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) { - - AddStandardComponent(0x0082, caption, style, exStyle, x, y, w, h, id); - - WORD creationDataLength = 0; - AppendData(&creationDataLength, sizeof(WORD)); - - } - - - void AddListBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) { - - AddStandardComponent(0x0083, caption, style, exStyle, x, y, w, h, id); - - WORD creationDataLength = sizeof(WORD) + 5 * sizeof(WCHAR); - AppendData(&creationDataLength, sizeof(WORD)); - - AppendString("TEST"); - - } - - - void AddScrollBar(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) { - - AddStandardComponent(0x0084, caption, style, exStyle, x, y, w, h, id); - - WORD creationDataLength = 0; - AppendData(&creationDataLength, sizeof(WORD)); - - } - - - void AddComboBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) { - - AddStandardComponent(0x0085, caption, style, exStyle, x, y, w, h, id); - - WORD creationDataLength = 0; - AppendData(&creationDataLength, sizeof(WORD)); - - } - - - /** - * - * Returns a pointer to the Win32 dialog template which the object - * represents. This pointer may become invalid if additional components - * are added to the template. - * - */ - operator const DLGTEMPLATE*() const { - return dialogTemplate; - } - - virtual ~DialogTemplate() { - free(dialogTemplate); - } - -protected: - - void AddStandardComponent(WORD type, LPCSTR caption, DWORD style, DWORD exStyle, - int x, int y, int w, int h, WORD id, LPSTR font = NULL, WORD fontSize = 8) { - - DLGITEMTEMPLATE item; - - // DWORD align the beginning of the component data - - AlignData(sizeof(DWORD)); - - item.style = style; - if (font != NULL) { - item.style |= DS_SETFONT; - } - item.x = (short)x; - item.y = (short)y; - item.cx = (short)w; - item.cy = (short)h; - item.id = id; - - item.dwExtendedStyle = exStyle; - - AppendData(&item, sizeof(DLGITEMTEMPLATE)); - - WORD preType = 0xFFFF; - - AppendData(&preType, sizeof(WORD)); - AppendData(&type, sizeof(WORD)); - - AppendString(caption); - - if (font != NULL) { - AppendData(&fontSize, sizeof(WORD)); - AppendString(font); - } - - // Increment the component count - dialogTemplate->cdit++; - } - - - void AlignData(int size) { - - int paddingSize = usedBufferLength % size; - - if (paddingSize != 0) { - EnsureSpace(paddingSize); - usedBufferLength += paddingSize; - } - - } - - void AppendString(LPCSTR string) { - - int length = MultiByteToWideChar(CP_ACP, 0, string, -1, NULL, 0); - - WCHAR* wideString = (WCHAR*)malloc(sizeof(WCHAR) * length); - MultiByteToWideChar(CP_ACP, 0, string, -1, wideString, length); - - AppendData(wideString, length * sizeof(WCHAR)); - free(wideString); - - } - - void AppendData(const void* data, int dataLength) { - - EnsureSpace(dataLength); - - memcpy((char*)dialogTemplate + usedBufferLength, data, dataLength); - usedBufferLength += dataLength; - - } - - void EnsureSpace(int length) { - if (length + usedBufferLength > totalBufferLength) { - totalBufferLength += length * 2; - - void* newBuffer = malloc(totalBufferLength); - memcpy(newBuffer, dialogTemplate, usedBufferLength); - - free(dialogTemplate); - dialogTemplate = (DLGTEMPLATE*)newBuffer; - } - } - -private: - - DLGTEMPLATE* dialogTemplate; - - int totalBufferLength; - int usedBufferLength; - -}; - - -struct PromptParams { - const char* message; - const char* title; -}; - -/** - * Constants for controls. - */ -#define IDC_MESSAGE 1000 -#define IDC_BUTTON0 2000 - -INT_PTR CALLBACK PromptDlgProc(HWND hDlg, UINT msg, - WPARAM wParam, LPARAM lParam) { - switch(msg) { - case WM_INITDIALOG: - { - PromptParams *params = (PromptParams*)lParam; - ::SetWindowTextA(::GetDlgItem(hDlg, IDC_MESSAGE), params->message); - - ::SetFocus(::GetDlgItem(hDlg, IDC_BUTTON0)); - - SetWindowTextA(hDlg, params->title); - - HFONT hfont = - CreateFontA(16, 0, 0, 0, FW_NORMAL, - FALSE, FALSE, FALSE, - ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, - PROOF_QUALITY, FIXED_PITCH | FF_MODERN, "Courier New"); - - SendDlgItemMessage(hDlg, IDC_MESSAGE, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE,0)); - - - break; - } - case WM_COMMAND: - { - int choiceNumber = LOWORD(wParam) - IDC_BUTTON0; - if ((choiceNumber >= 0) && (choiceNumber < 10)) { - EndDialog(hDlg, choiceNumber); - return TRUE; - } - } - - break; - - case WM_NCDESTROY: - // Under SDL 1.2.6 we get a NCDESTROY message for no reason and the - // window is immediately closed. This is here to debug the problem. - (void)0; - break; - - } - - return FALSE; -} - -}; // namespace _internal - - -using namespace _internal; - -/** - * Show a dialog prompt. - */ -static int guiPrompt( - const char* windowTitle, - const char* prompt, - const char** choice, - int numChoices) { - - int width = 280; - int height = 128; - - const int buttonSpacing = 2; - const int buttonWidth = - (width - buttonSpacing * 2 - - buttonSpacing * (numChoices - 1)) / numChoices; - const int buttonHeight = 13; - - - DialogTemplate dialogTemplate( - windowTitle, - WS_CAPTION | DS_CENTER | WS_SYSMENU, - 10, 10, width, height, - "Tahoma"); - - dialogTemplate.AddEditBox( - "Edit", WS_VISIBLE | ES_READONLY | ES_OEMCONVERT | ES_MULTILINE | WS_TABSTOP, WS_EX_STATICEDGE, - 2, 2, width - 4, height - buttonHeight - 7, IDC_MESSAGE); - - int i; - for (i = 0; i < numChoices; i++) { - - int x = buttonSpacing + i * (buttonWidth + buttonSpacing); - int y = height - buttonHeight - buttonSpacing; - - dialogTemplate.AddButton(choice[i], WS_VISIBLE | WS_TABSTOP, 0, - x, y, buttonWidth, buttonHeight, IDC_BUTTON0 + (WORD)i); - - } - - // Convert all single \n characters to \r\n for proper printing - int strLen = 0; - const char* pStr = prompt; - - while (*pStr != '\0') { - if ((*pStr == '\n') && (pStr != prompt)) { - if (*(pStr - 1) != '\r') { - ++strLen; - } - } - ++strLen; - ++pStr; - } - - char* newStr = (char*)malloc(strLen + 1); - - const char* pStr2 = prompt; - char* pNew = newStr; - - while (*pStr2 != '\0') { - if ((*pStr2 == '\n') && (pStr2 != prompt)) { - if (*(pStr2 - 1) != '\r') { - *pNew = '\r'; - ++pNew; - } - } - *pNew = *pStr2; - ++pNew; - ++pStr2; - } - - *pNew = '\0'; - - PromptParams params; - params.message = newStr;; - params.title = windowTitle; - - HMODULE module = GetModuleHandle(0); - int ret = DialogBoxIndirectParam(module, dialogTemplate, NULL, (DLGPROC) PromptDlgProc, (DWORD)¶ms); - - free(newStr); - - /* - For debugging when DialogBoxIndirectParam fails: - - // The last error value. (Which is preserved across the call). - DWORD lastErr = GetLastError(); - - // The decoded message from FormatMessage - LPTSTR formatMsg = NULL; - - if (NULL == formatMsg) { - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - lastErr, - 0, - (LPTSTR)&formatMsg, - 0, - NULL); - } - - // Make sure the message got translated into something. - LPTSTR realLastErr; - if (NULL != formatMsg) { - realLastErr = formatMsg; - } else { - realLastErr = "Last error code does not exist."; - } - - // Get rid of the allocated memory from FormatMessage. - if (NULL != formatMsg) { - LocalFree((LPVOID)formatMsg); - } - */ - - return ret; -} - -#endif - - -/** - * Show a prompt on stdout - */ -static int textPrompt( - const char* windowTitle, - const char* prompt, - const char** choice, - int numChoices) { - - printf("\n___________________________________________________\n"); - printf("%s\n", windowTitle); - printf("%s", prompt); - - if (numChoices > 10) { - numChoices = 10; - } - - int c = -1; - if (numChoices > 1) { - printf("\n"); - printf("Choose an option by number:"); - - while ((c < 0) || (c >= numChoices)) { - printf("\n"); - - for (int i = 0; i < numChoices; i++) { - if (numChoices <= 3) { - printf(" (%d) %s ", i, choice[i]); - } else { - printf(" (%d) %s\n", i, choice[i]); - } - } - - printf("\n> "); - c = _getch() - '0'; - - if ((c < 0) || (c >= numChoices)) { - printf("'%d' is not a valid choice.", c); - } else { - printf("%d", c); - } - } - - } else if (numChoices == 1) { - - printf("\nPress any key for '%s'...", choice[0]); - _getch(); - c = 0; - - } else { - - printf("\nPress any key..."); - _getch(); - c = 0; - } - - printf("\n___________________________________________________\n"); - return c; -} - -#ifdef G3D_OSX - -// See http://developer.apple.com/documentation/Carbon/Reference/Carbon_Event_Manager_Ref/index.html - -#define CARBON_COMMANDID_START 128 -#define CARBON_BUTTON_SPACING 12 -#define CARBON_BUTTON_HEIGHT 20 -#define CARBON_BUTTON_MINWIDTH 69 -#define CARBON_WINDOW_PADDING 20 - -struct CallbackData { - WindowRef refWindow; - - /** Index of this particular button */ - int myIndex; - - /** Buttons store their index into here when pressed. */ - int* whichButton; -}; - -/** - Assumes that userData is a pointer to a carbon_evt_data_t. - - */ -static pascal OSStatus DoCommandEvent(EventHandlerCallRef handlerRef, EventRef event, void* userData) { - // See http://developer.apple.com/documentation/Carbon/Conceptual/HandlingWindowsControls/index.html - - CallbackData& callbackData = *(CallbackData*)userData; - -# pragma unused(handlerRef) - - callbackData.whichButton[0] = callbackData.myIndex; - - // If we get here we can close the window - QuitAppModalLoopForWindow(callbackData.refWindow); - - // Return noErr to indicate that we handled the event - return noErr; -} - -static int guiPrompt -(const char* windowTitle, - const char* prompt, - const char** choice, - int numChoices) { - - WindowRef window; - - int iNumButtonRows = 0; - int iButtonWidth = -1; - OSStatus err = noErr; - - // Determine number of rows of buttons - while (iButtonWidth < CARBON_BUTTON_MINWIDTH) { - ++iNumButtonRows; - iButtonWidth = - (550 - (CARBON_WINDOW_PADDING*2 + - (CARBON_BUTTON_SPACING*numChoices))) / - (numChoices/iNumButtonRows); - } - - // Window Variables - Rect rectWin = {0, 0, 200 + ((iNumButtonRows-1) * (CARBON_BUTTON_HEIGHT+CARBON_BUTTON_SPACING)), 550}; // top, left, bottom, right - CFStringRef szWindowTitle = CFStringCreateWithCString(kCFAllocatorDefault, windowTitle, kCFStringEncodingUTF8); - - window = NULL; - - err = CreateNewWindow(kMovableAlertWindowClass, kWindowStandardHandlerAttribute|kWindowCompositingAttribute, &rectWin, &window); - err = SetWindowTitleWithCFString(window, szWindowTitle); - err = SetThemeWindowBackground(window, kThemeBrushAlertBackgroundActive, false); - assert(err == noErr); - - // Event Handler Variables - EventTypeSpec buttonSpec[] = {{ kEventClassControl, kEventControlHit }, { kEventClassCommand, kEventCommandProcess }}; - EventHandlerUPP buttonHandler = NewEventHandlerUPP(DoCommandEvent); - - // Static Text Variables - Rect rectStatic = {20, 20, 152, 530}; - CFStringRef szStaticText = CFStringCreateWithCString(kCFAllocatorDefault, prompt, kCFStringEncodingUTF8); - ControlRef refStaticText = NULL; - err = CreateStaticTextControl(window, &rectStatic, szStaticText, NULL, &refStaticText); - - // Button Variables - Rect bounds[numChoices]; - CFStringRef caption[numChoices]; - ControlRef button[numChoices]; - - int whichButton=-1; - CallbackData callbackData[numChoices]; - - // Create the Buttons and assign event handlers - for (int i = 0; i < numChoices; ++i) { - bounds[i].top = 160 + ((CARBON_BUTTON_HEIGHT+CARBON_BUTTON_SPACING)*(i%iNumButtonRows)); - bounds[i].right = 530 - ((iButtonWidth+CARBON_BUTTON_SPACING)*(i/iNumButtonRows)); - bounds[i].left = bounds[i].right - iButtonWidth; - bounds[i].bottom = bounds[i].top + CARBON_BUTTON_HEIGHT; - - // Convert the button captions to Apple strings - caption[i] = CFStringCreateWithCString(kCFAllocatorDefault, choice[i], kCFStringEncodingUTF8); - - err = CreatePushButtonControl(window, &bounds[i], caption[i], &button[i]); - assert(err == noErr); - - err = SetControlCommandID(button[i], CARBON_COMMANDID_START + i); - assert(err == noErr); - - callbackData[i].refWindow = window; - callbackData[i].myIndex = i; - callbackData[i].whichButton = &whichButton; - - err = InstallControlEventHandler(button[i], buttonHandler, - GetEventTypeCount(buttonSpec), buttonSpec, - &callbackData[i], NULL); - assert(err == noErr); - } - - // Show Dialog - err = RepositionWindow(window, NULL, kWindowCenterOnMainScreen); - ShowWindow(window); - BringToFront(window); - err = ActivateWindow(window, true); - - // Hack to get our window/process to the front... - ProcessSerialNumber psn = { 0, kCurrentProcess}; - TransformProcessType(&psn, kProcessTransformToForegroundApplication); - SetFrontProcess (&psn); - - // Run in Modal State - err = RunAppModalLoopForWindow(window); - - // Dispose of Button Related Data - for (int i = 0; i < numChoices; ++i) { - // Dispose of controls - DisposeControl(button[i]); - - // Release CFStrings - CFRelease(caption[i]); - } - - // Dispose of Other Controls - DisposeControl(refStaticText); - - // Dispose of Event Handlers - DisposeEventHandlerUPP(buttonHandler); - - // Dispose of Window - DisposeWindow(window); - - // Release CFStrings - CFRelease(szWindowTitle); - CFRelease(szStaticText); - - // Return Selection - return whichButton; -} - -#endif - -int prompt( - const char* windowTitle, - const char* prompt, - const char** choice, - int numChoices, - bool useGui) { - - #ifdef G3D_WIN32 - if (useGui) { - // Build the message box - return guiPrompt(windowTitle, prompt, choice, numChoices); - } - #endif - - #ifdef G3D_OSX - if (useGui){ - //Will default to text prompt if numChoices > 4 - return guiPrompt(windowTitle, prompt, choice, numChoices); - } - #endif - return textPrompt(windowTitle, prompt, choice, numChoices); -} - - -void msgBox( - const std::string& message, - const std::string& title) { - - const char *choice[] = {"Ok"}; - prompt(title.c_str(), message.c_str(), choice, 1, true); -} - -#ifndef G3D_WIN32 - #undef _getch -#endif - -};// namespace - diff --git a/externals/g3dlite/G3D.lib/source/stringutils.cpp b/externals/g3dlite/G3D.lib/source/stringutils.cpp deleted file mode 100644 index a21fc1f377c..00000000000 --- a/externals/g3dlite/G3D.lib/source/stringutils.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/** - @file stringutils.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - - @created 2000-09-09 - @edited 2008-01-10 -*/ - -#include "G3D/platform.h" -#include "G3D/stringutils.h" -#include "G3D/BinaryInput.h" -#include - -namespace G3D { - -#ifdef _MSC_VER - // disable: "C++ exception handler used" -# pragma warning (push) -# pragma warning (disable : 4530) -#endif -#ifdef G3D_WIN32 - const char* NEWLINE = "\r\n"; -#else - const char* NEWLINE = "\n"; - static bool iswspace(int ch) { return (ch==' ' || ch=='\t' || ch=='\n'); } -#endif - -bool beginsWith( - const std::string& test, - const std::string& pattern) { - - if (test.size() >= pattern.size()) { - for (int i = 0; i < (int)pattern.size(); ++i) { - if (pattern[i] != test[i]) { - return false; - } - } - return true; - } else { - return false; - } -} - - -bool endsWith( - const std::string& test, - const std::string& pattern) { - - if (test.size() >= pattern.size()) { - int te = test.size() - 1; - int pe = pattern.size() - 1; - for (int i = pattern.size() - 1; i >= 0; --i) { - if (pattern[pe - i] != test[te - i]) { - return false; - } - } - return true; - } else { - return false; - } -} - - -std::string wordWrap( - const std::string& input, - int numCols) { - - std::string output; - size_t c = 0; - int len; - - // Don't make lines less than this length - int minLength = numCols / 4; - size_t inLen = input.size(); - - bool first = true; - while (c < inLen) { - if (first) { - first = false; - } else { - output += NEWLINE; - } - - if ((int)inLen - (int)c - 1 < numCols) { - // The end - output += input.substr(c, inLen - c); - break; - } - - len = numCols; - - // Look at character c + numCols, see if it is a space. - while ((len > minLength) && - (input[c + len] != ' ')) { - len--; - } - - if (len == minLength) { - // Just crop - len = numCols; - - } - - output += input.substr(c, len); - c += len; - if (c < input.size()) { - // Collapse multiple spaces. - while ((input[c] == ' ') && (c < input.size())) { - c++; - } - } - } - - return output; -} - - -int stringCompare( - const std::string& s1, - const std::string& s2) { - - return stringPtrCompare(&s1, &s2); -} - - -int stringPtrCompare( - const std::string* s1, - const std::string* s2) { - - return s1->compare(*s2); -} - - -std::string toUpper(const std::string& x) { - std::string result = x; - std::transform(result.begin(), result.end(), result.begin(), toupper); - return result; -} - - -std::string toLower(const std::string& x) { - std::string result = x; - std::transform(result.begin(), result.end(), result.begin(), tolower); - return result; -} - - -Array stringSplit( - const std::string& x, - char splitChar) { - - Array out; - - // Pointers to the beginning and end of the substring - const char* start = x.c_str(); - const char* stop = start; - - while ((stop = strchr(start, splitChar))) { - out.append(std::string(start, stop - start)); - start = stop + 1; - } - - // Append the last one - out.append(std::string(start)); - - return out; -} - - -std::string stringJoin( - const Array& a, - char joinChar) { - - std::string out; - - for (int i = 0; i < (int)a.size() - 1; ++i) { - out += a[i] + joinChar; - } - - if (a.size() > 0) { - return out + a.last(); - } else { - return out; - } -} - - -std::string stringJoin( - const Array& a, - const std::string& joinStr) { - - std::string out; - - for (int i = 0; i < (int)a.size() - 1; ++i) { - out += a[i] + joinStr; - } - - if (a.size() > 0) { - return out + a.last(); - } else { - return out; - } -} - - -std::string trimWhitespace( - const std::string& s) { - - size_t left = 0; - - // Trim from left - while ((left < s.length()) && iswspace(s[left])) { - ++left; - } - - int right = s.length() - 1; - // Trim from right - while ((right > (int)left) && iswspace(s[right])) { - --right; - } - - return s.substr(left, right - left + 1); -} - -}; // namespace - -#undef NEWLINE -#ifdef _MSC_VER -# pragma warning (pop) -#endif diff --git a/externals/g3dlite/G3D.lib/source/uint128.cpp b/externals/g3dlite/G3D.lib/source/uint128.cpp deleted file mode 100644 index 450009a5cff..00000000000 --- a/externals/g3dlite/G3D.lib/source/uint128.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/** - @file uint128.cpp - - @maintainer Morgan McGuire, matrix@graphics3d.com - @author Kyle Whitson - - @created 2008-07-17 - @edited 2008-07-17 - */ - -#include "G3D/uint128.h" - -namespace G3D { - -/** Adds two 64-bit integers, placing the result and the overflow into 64-bit integers.*/ -static void addAndCarry(const uint64& _a, const uint64& _b, uint64& carry, uint64& result) { - - // Break each number into 4 32-bit chunks. Since we are using uints, right-shifting will fill with zeros. - // This eliminates the need to and with 0xFFFFFFFF. - uint32 a [2] = {_a & 0xFFFFFFFF, _a >> 32}; - uint32 b [2] = {_b & 0xFFFFFFFF, _b >> 32}; - - uint64 tmp = uint64(a[0]) + b[0]; - - result = tmp & 0xFFFFFFFF; - uint32 c = tmp >> 32; - - tmp = uint64(c) + a[1] + b[1]; - result += tmp << 32; - carry = (tmp >> 32); -} - -/** Multiplies two unsigned 64-bit integers, placing the result into one 64-bit int and the overflow into another.*/ -void multiplyAndCarry(const uint64& _a, const uint64& _b, uint64& carry, uint64& result) { - - // Break each number into 4 32-bit chunks. Since we are using uints, right-shifting will fill with zeros. - // This eliminates the need to and with 0xFFFFFFFF. - uint32 a [2] = {_a & 0xFFFFFFFF, _a >> 32}; - uint32 b [2] = {_b & 0xFFFFFFFF, _b >> 32}; - - uint64 prod [2][2]; - for(int i = 0; i < 2; ++i) { - for(int j = 0; j < 2; ++j) { - prod[i][j] = uint64(a[i]) * b[j]; - } - } - - // The product of the low bits of a and b will always fit into the result - result = prod[0][0]; - - // The product of the high bits of a and b will never fit into the result - carry = prod[1][1]; - - // The high 32 bits of prod[0][1] and prod[1][0] will never fit into the result - carry += prod[0][1] >> 32; - carry += prod[1][0] >> 32; - - uint64 tmp; - addAndCarry(result, (prod[0][1] << 32), tmp, result); - carry += tmp; - addAndCarry(result, (prod[1][0] << 32), tmp, result); - carry += tmp; -} - - -uint128::uint128(const uint64& hi, const uint64& lo) : hi(hi), lo(lo) { -} - -uint128::uint128(const uint64& lo) : hi(0), lo(lo) { -} - -uint128& uint128::operator+=(const uint128& x) { - - G3D::uint64 carry; - addAndCarry(lo, x.lo, carry, lo); - - // Adding the carry will change hi. Save the old hi bits in case this == x. - const uint64 xHi = x.hi; - hi += carry; - hi += xHi; - return *this; -} - -uint128& uint128::operator*=(const uint128& x) { - - // The low bits will get overwritten when doing the multiply, so back up both (in case &x == this) - const uint64 oldLo = lo; - const uint64 oldXLo = x.lo; - - G3D::uint64 carry; - multiplyAndCarry(oldLo, oldXLo, carry, lo); - - // Overflow doesn't matter here because the result is going into hi - any overflow will exceed the capacity of a 128-bit number - // Note: hi * x.hi will always overflow, since (x * 2^64) * (y * 2^64) = x*y*(2^128). The largest number expressable in 128 bits is - // 2^128 - 1. - hi = carry + (oldLo * x.hi) + (hi * oldXLo); - - return *this; -} - -uint128& uint128::operator^=(const uint128& x) { - hi ^= x.hi; - lo ^= x.lo; - return *this; -} - -uint128& uint128::operator&=(const uint128& x) { - hi &= x.hi; - lo &= x.lo; - return *this; -} - -uint128& uint128::operator|=(const uint128& x) { - hi |= x.hi; - lo |= x.lo; - return *this; -} - -bool uint128::operator==(const uint128& x) { - return (hi == x.hi) && (lo == x.lo); -} - -uint128& uint128::operator>>=(const int x) { - - //Before shifting, mask out the bits that will be shifted out of hi. - //Put a 1 in the first bit that will not be lost in the shift, then subtract 1 to get the mask. - uint64 mask = ((uint64)1L << x) - 1; - uint64 tmp = hi & mask; - hi >>= x; - - //Shift lo and add the bits shifted down from hi - lo = (lo >> x) + (tmp << (64 - x)); - - return *this; -} - -uint128& uint128::operator<<=(const int x) { - - //Before shifting, mask out the bits that will be shifted out of lo. - //Put a 1 in the last bit that will be lost in the shift, then subtract 1 to get the logical inverse of the mask. - //A bitwise NOT will then produce the correct mask. - uint64 mask = ~((((uint64)1L) << (64 - x)) - 1); - uint64 tmp = lo & mask; - lo <<= x; - - //Shift hi and add the bits shifted up from lo - hi = (hi << x) + (tmp >> (64 - x)); - - return *this; -} - -uint128 uint128::operator&(const uint128& x) { - return uint128(hi & x.hi, lo & x.lo); -} -} diff --git a/externals/g3dlite/G3D/AABox.h b/externals/g3dlite/G3D/AABox.h new file mode 100644 index 00000000000..2e8da1f6098 --- /dev/null +++ b/externals/g3dlite/G3D/AABox.h @@ -0,0 +1,272 @@ +/** + @file AABox.h + + Axis-aligned box class + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2004-01-10 + @edited 2009-02-10 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_AABOX_H +#define G3D_AABOX_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/debug.h" +#include "G3D/Array.h" +#include "G3D/Plane.h" + +namespace G3D { + +/** + An axis-aligned box. + */ +class AABox { +private: + friend class Intersect; + + /** Optional argument placeholder */ + static int dummy; + + Vector3 lo; + Vector3 hi; + +public: + + /** Does not initialize the fields */ + inline AABox() {} + + /** + Constructs a zero-area AABox at v. + */ + inline explicit AABox(const Vector3& v) { + lo = hi = v; + } + + /** Assumes that low is less than or equal to high along each dimension. + To have this automatically enforced, use + AABox(low.min(high), low.max(high)); + */ + inline AABox(const Vector3& low, const Vector3& high) { + set(low, high); + } + + /** Assumes that low is less than or equal to high along each dimension. + */ + inline void set(const Vector3& low, const Vector3& high) { + debugAssert( + (low.x <= high.x) && + (low.y <= high.y) && + (low.z <= high.z)); + lo = low; + hi = high; + } + + /** + Grows to include the bounds of a + */ + inline void merge(const AABox& a) { + lo = lo.min(a.lo); + hi = hi.max(a.hi); + } + + inline void merge(const Vector3& a) { + lo = lo.min(a); + hi = hi.max(a); + } + + void serialize(class BinaryOutput& b) const; + + void deserialize(class BinaryInput& b); + + inline bool isFinite() const { + return lo.isFinite() && hi.isFinite(); + } + + inline const Vector3& low() const { + return lo; + } + + inline const Vector3& high() const { + return hi; + } + + /** + The largest possible finite box. + */ + static const AABox& maxFinite(); + + /** A large finite box. This is smaller than FLT_MAX + because it leaves room to add boxes together. */ + static const AABox& large(); + + static const AABox& inf(); + + static const AABox& zero(); + + /** + Returns the centroid of the box. + */ + inline Vector3 center() const { + return (lo + hi) * 0.5; + } + + Vector3 corner(int index) const; + + /** + Distance from corner(0) to the next corner along axis a. + */ + inline float extent(int a) const { + debugAssert(a < 3); + return hi[a] - lo[a]; + } + + + inline Vector3 extent() const { + return hi - lo; + } + + + /** + Splits the box into two AABoxes along the specified axis. low contains + the part that was closer to negative infinity along axis, high contains + the other part. Either may have zero volume. + */ + void split(const Vector3::Axis& axis, float location, AABox& low, AABox& high) const; + + /** + Conservative culling test for up to 32 planes. + Returns true if there exists a plane[p] for + which the entire object is in the negative half space + (opposite the plane normal). + + testMask and childMask + are used for optimizing bounding volume hierarchies. + The version of this method that produces childMask + is slower than the version without; it should only + be used for parent nodes. + + @param cullingPlaneIndex The index of the first plane for which + the entire object is in the negative half-space. The function + exits early when one plane is found. -1 when the function + returns false (i.e. when no plane culls the whole object). + + @param testMask If bit p is 0, the + bounding volume automatically passes the culling test for + plane[p] (i.e. it is known that the volume + is entirely within the positive half space). The function + must return false if testMask is 0 and test all planes + when testMask is -1 (0xFFFFFFFF). + + @param childMask Test mask for the children of this volume. + + */ + bool culledBy( + const Array& plane, + int32& cullingPlaneIndex, + const uint32 testMask, + uint32& childMask) const; + + /** + Conservative culling test that does not produce a mask for children. + */ + bool culledBy( + const Array& plane, + int32& cullingPlaneIndex = dummy, + const uint32 testMask = 0xFFFFFFFF) const; + + /** less than or equal to containment */ + inline bool contains(const AABox& other) const { + return + (other.hi.x <= hi.x) && + (other.hi.y <= hi.y) && + (other.hi.z <= hi.z) && + (other.lo.x >= lo.x) && + (other.lo.y >= lo.y) && + (other.lo.z >= lo.z); + } + + inline bool contains( + const Vector3& point) const { + return + (point.x >= lo.x) && + (point.y >= lo.y) && + (point.z >= lo.z) && + (point.x <= hi.x) && + (point.y <= hi.y) && + (point.z <= hi.z); + } + + inline float area() const { + Vector3 diag = hi - lo; + return 2.0f * (diag.x * diag.y + diag.y * diag.z + diag.x * diag.z); + } + + inline float volume() const { + Vector3 diag = hi - lo; + return diag.x * diag.y * diag.z; + } + + Vector3 randomInteriorPoint() const; + + Vector3 randomSurfacePoint() const; + + /** Returns true if there is any overlap */ + bool intersects(const AABox& other) const; + + /** Returns true if there is any overlap. + @cite Jim Arvo's algorithm from Graphics Gems II*/ + bool intersects(const class Sphere& other) const; + + /** Return the intersection of the two boxes */ + AABox intersect(const AABox& other) const { + Vector3 H = hi.min(other.hi); + Vector3 L = lo.max(other.lo).min(H); + return AABox(L, H); + } + + inline size_t hashCode() const { + return lo.hashCode() + hi.hashCode(); + } + + inline bool operator==(const AABox& b) const { + return (lo == b.lo) && (hi == b.hi); + } + + inline bool operator!=(const AABox& b) const { + return !((lo == b.lo) && (hi == b.hi)); + } + + inline AABox operator+(const Vector3& v) const { + AABox out; + out.lo = lo + v; + out.hi = hi + v; + return out; + } + + inline AABox operator-(const Vector3& v) const { + AABox out; + out.lo = lo - v; + out.hi = hi - v; + return out; + } + + void getBounds(AABox& out) const { + out = *this; + } +}; + +} + +template <> struct HashTrait { + static size_t hashCode(const G3D::AABox& key) { return key.hashCode(); } +}; + + + +#endif diff --git a/externals/g3dlite/G3D/Any.h b/externals/g3dlite/G3D/Any.h new file mode 100644 index 00000000000..49701202ca9 --- /dev/null +++ b/externals/g3dlite/G3D/Any.h @@ -0,0 +1,570 @@ +/** + @file Any.h + + @author Morgan McGuire, Shawn Yarbrough, and Corey Taylor + @maintainer Morgan McGuire + + @created 2006-06-11 + @edited 2009-12-16 + + Copyright 2000-2010, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_Any_h +#define G3D_Any_h + +#include "G3D/platform.h" +#include "G3D/Table.h" +#include "G3D/Array.h" +#include "G3D/AtomicInt32.h" +#include + +// needed for Token +#include "G3D/TextInput.h" + +#ifdef verify +#undef verify +#endif + +namespace G3D { + +class TextOutput; + +/** +\brief Easy loading and saving of human-readable configuration files. + +Encodes typed, structured data and can serialize it to a human +readable format that is very similar to the Python language's data +syntax. Well-suited for quickly creating human-readable file formats, +especially since deserialization and serialization preserve comments and +an Any can tell you what file and line it came from. + +The class is designed so that copying Anys generally is fast, even if +it is a large array or table. This is because data is shared between +copies until it is mutated, at which point an actual copy occurs. + +\section Example +Sample File: +
+{
+   shape = "round",
+
+   # in meters
+   radius = 3.7,
+
+   position = Vector3(1.0, -1.0, 0.0),
+   texture = { format = "RGB8", size = (320, 200)}
+}
+
+ +Sample code using: +
+Any x;
+x.load("ball.txt");
+if (x["shape"].string() == "round") {
+    x["density"] = 3;
+}
+x.save("ball.txt");
+
+ +The custom serialization format was chosen to be terse, easy for +humans to read, and easy for machines to parse. It was specifically +chosen over formats like XML, YAML, JSON, S-expressions, and Protocol +Buffers, although there is no reason you could not write readers and +writers for G3D::Any that support those. + +G3D::Any assumes that structures do not contain cycles; it is an +error to create a structure like: + +
+Any x(Any::ARRAY);
+x.array().append(x);    // don't do this!
+
+ +although no exception will be thrown at runtime during that append. + + +\section Parsing + +The primary use of Any is to create your own text file formats. +The Vector3 constructor is a good example of how to use the Any::verify +methods to provide good error checking while parsing such formats: + +
+Vector3::Vector3(const Any& any) {
+    any.verifyName("Vector3");
+    any.verifyType(Any::TABLE, Any::ARRAY);
+    any.verifySize(3);
+
+    if (any.type() == Any::ARRAY) {
+        x = any[0];
+        y = any[1];
+        z = any[2];
+    } else {
+        // Table
+        x = any["x"];
+        y = any["y"];
+        z = any["z"];
+    }
+}
+
+ +\section BNF +Serialized format BNF: + +
+identifier  ::= (letter | "_") (letter | digit | "_")*
+identifier-op ::= "::" | "->" | "."
+
+identifier-exp ::= [identifier-op] identifier (identifier-op identifier)*
+
+comment     ::= "#"  "\n"
+separator   ::= "," | ";"
+
+number      ::= 
+string      ::= 
+boolean     ::= "True" | "False"
+none        ::= "None"
+array       ::= "(" [value ("," value)*] ")"
+pair        ::= (identifier | string) "=" value
+table       ::= "{" [pair (separator pair)*] "}"
+named-array ::= identifier-exp tuple
+named-table ::= identifier-exp dict
+
+value       ::= [comment] (none | number | boolean | string | array | table | named-array | named-table)
+
+ +Except for single-line comments, whitespace is not significant. +All parsing is case-insensitive. + +The deserializer allows the substitution of [] for () when writing +tuples and ";" for ",". + +The serializer indents four spaces for each level of nesting. +Tables are written with the keys in alphabetic order. +*/ +class Any { +public: + + enum Type {NONE, BOOLEAN, NUMBER, STRING, ARRAY, TABLE}; + + static std::string toString(Type t); + + /** Where an Any came from in a file. Useful for throwing parsing errors */ + class Source { + public: + std::string filename; + int line; + int character; + + Source() : line(0), character(0) {} + + void set(const TextInput& ti, const Token& t) { + filename = ti.filename(); + line = t.line(); + character = t.character(); + } + }; + + typedef Array AnyArray; + typedef Table AnyTable; + +private: + + /** Called from deserialize() */ + static void deserializeComment(TextInput& ti, Token& token, std::string& comment); + + /** NONE, BOOLEAN, and NUMBER are stored directly in the Any */ + union SimpleValue { + bool b; + double n; + + inline SimpleValue() : n(0.0) {} + inline SimpleValue(bool x) : b(x) {} + inline SimpleValue(double x) : n(x) {} + }; + + class Data { + public: + /** ARRAY, TABLE, or STRING value only. NULL otherwise. */ + union Value { + std::string* s; + Array* a; + AnyTable* t; + inline Value() : s(NULL) {} + }; + + // Needed so that the destructor knows what is in Value + // and can call its destructor. + Type type; + + /** Always points to memory that is allocated with the Data, so + the destructor does not delete this. */ + Value value; + + std::string comment; + + std::string name; + + /** For STRING, ARRAY and TABLE types, m_value is shared between + multiple instances. Mutation is allowed only if the reference + count is exactly 1, otherwise the mutating instance must copy + the value. This is not used for other types. + */ + AtomicInt32 referenceCount; + + Source source; + + private: + + /** Called by create() */ + inline Data(Type t) : type(t), referenceCount(1) {} + + /** Called by destroy */ + ~Data(); + + public: + + /** Clones the argument */ + static Data* create(const Data* d); + static Data* create(Type t); + + /** Free d, invoking its destructor and freeing the memory for + the value. */ + static void destroy(Data* d); + + }; + + /** If not empty, this Any was created from operator[] on a table + and perhaps was not intended to exist. The name is needed to + format the error message if it is read from before it is + written to. + + The source of a placeholder object is that of the parent + object until it is written. + */ + std::string m_placeholderName; + + Type m_type; + SimpleValue m_simpleValue; + mutable Data* m_data; + + /** Called before every read operation to ensure that this object + is not a placeholder. */ + void beforeRead() const; + + /** Called before every write operation to wipe the placeholder + status. */ + void beforeWrite(); + + /** Decrements the reference count (if there is one). If the + reference count is zero after decrement, calls delete on @a m_data + and sets it to NULL. + */ + void dropReference(); + + /** Allocate the Data object if it does not exist */ + void ensureData(); + + /** If m_data is not NULL, ensure that it has a unique reference + and contains a valid m_data. This has a race condition if two + threads are both trying to modify the same Any + simultaneously.*/ + void ensureMutable(); + + /** Read an unnamed a TABLE or ARRAY. Token should be the open + paren token; it is the next token after the close on + return. Called from deserialize().*/ + void deserializeBody(TextInput& ti, Token& token); + + void deserialize(TextInput& ti, Token& token); + + /** Read the name of a named Array or Table. */ + static void deserializeName(TextInput& ti, Token& token, std::string& name); + + /** Read until a comma is consumed or a close paren is hit, and + return that token. Considers the passed in token to be the first + value read. */ + static void readUntilCommaOrClose(TextInput& ti, Token& token); + + /** Construct an Any that is a proxy for a table fetch from \a data. + This proxy can be copied exactly once on return from operator[].*/ + Any(const std::string& key, Data* data); + + inline bool isPlaceholder() const { + return ! m_placeholderName.empty(); + } + +public: + + /** Base class for all Any exceptions.*/ + class Exception { + public: + virtual ~Exception() {} + }; + + /** Thrown by operator[] when a key is not present in a const table. */ + class KeyNotFound : public ParseError { + public: + std::string key; + }; + + /** Thrown by operator[] when an array index is not present. */ + class IndexOutOfBounds : public Exception { + public: + int index; + int size; + inline IndexOutOfBounds() : index(0), size(0) {} + inline IndexOutOfBounds(int i, int s) : index(i), size(s) {} + }; + + /** NONE constructor */ + Any(); + + /** Deserialize */ + explicit Any(TextInput& t); + + Any(const Any& x); + + /** NUMBER constructor */ + Any(double x); + +#ifdef G3D_32BIT + /** NUMBER constructor */ + Any(int64 x); +#endif // G3D_32BIT + +#if 0 + /** NUMBER constructor */ + Any(int32 x); +#endif // 0 + + /** NUMBER constructor */ + Any(long x); + + /** NUMBER constructor */ + Any(int x); + + /** NUMBER constructor */ + Any(short x); + + /** BOOLEAN constructor */ + Any(bool x); + + /** STRING constructor */ + Any(const std::string& x); + + /** STRING constructor */ + Any(const char* x); + + /** \a t must be ARRAY or TABLE */ + Any(Type t, const std::string& name = ""); + + ~Any(); + + /** Removes the comment and name */ + Any& operator=(const Any& x); + + /** Removes the comment and name */ + Any& operator=(double x); + + /** Removes the comment and name */ + Any& operator=(int x); + + /** Removes the comment and name */ + Any& operator=(bool x); + + /** Removes the comment and name */ + Any& operator=(const std::string& x); + + /** Removes the comment and name */ + Any& operator=(const char* x); + + /** \a t must be ARRAY, TABLE, or NONE. Removes the comment and name */ + Any& operator=(Type t); + + Type type() const; + + /** Same as deserialize or load, but operates on a string instead + of a stream or file. + + \sa deserialize, load + */ + void parse(const std::string& src); + + std::string unparse() const; + + /** Comments appear before values when they are in serialized form.*/ + const std::string& comment() const; + void setComment(const std::string& c); + + /** True if this is the NONE value */ + bool isNone() const; + + /** Throws a ParseError exception if this is not a number */ + double number() const; + const std::string& string() const; + bool boolean() const; + + /** If this is named ARRAY or TABLE, returns the name. */ + const std::string& name() const; + + /** \brief Set the name used when serializing an ARRAY or TABLE. + + Only legal for ARRAY or TABLE. The \a name must begin with a letter + and contain only letters, numbers, underscores and scope operators. + +
+        a2z
+        hello
+        Foo::bar
+        color.red
+        this->that
+        __x
+        
+ + + The scope operators "::", "->", and + ".", may have spaces around them. The name may not + contain parentheses. + */ + void setName(const std::string& name); + + /** Number of elements if this is an ARRAY or TABLE */ + int size() const; + int length() const; + + /** For an array, returns the ith element */ + const Any& operator[](int i) const; + Any& operator[](int i); + + /** Directly exposes the underlying data structure for an ARRAY. */ + const Array& array() const; + void append(const Any& v0); + void append(const Any& v0, const Any& v1); + void append(const Any& v0, const Any& v1, const Any& v2); + void append(const Any& v0, const Any& v1, const Any& v2, const Any& v3); + + /** Directly exposes the underlying data structure for table.*/ + const Table& table() const; + + /** For a table, returns the element for \a key. Throws KeyNotFound + exception if the element does not exist. + */ + const Any& operator[](const std::string& key) const; + + // Needed to prevent the operator[](int) overload from catching + // string literals + inline const Any& operator[](const char* key) const { + return operator[](std::string(key)); + } + + /** + Fetch an element from a table. This can be used as: + +
+        a["key"] = value;  (create the key if it did not exist)
+        
+ + or + +
+        value = a["key"];  (throw an error if the key did not exist)
+        
+ + Note: + In order to cause elements to be correctly created in the + first case while still providing "key not found" errors in the + second case, the Any returned is a special object that delays + the actual fetch until the following assignment or method + call. This means that in the event of an error, the exception + may be thrown from a line other than the actual fetch. Use + the Any::get() or the const Any::operator[]() methods to avoid + this behavior and ensure error-checking at fetch time. + */ + Any& operator[](const std::string& key); + + /** \copydoc Any::operator[](const std::string&) */ + inline Any& operator[](const char* key) { + return operator[](std::string(key)); + } + + /** For a table, returns the element for key \a x and \a + defaultVal if it does not exist. */ + const Any& get(const std::string& key, const Any& defaultVal) const; + + /** Returns true if this key is in the TABLE. Illegal to call on an object that is not a TABLE. */ + bool containsKey(const std::string& key) const; + + /** For a table, assigns the element for key k. */ + void set(const std::string& key, const Any& val); + + /** for an ARRAY, resizes and returns the last element */ + Any& next(); + + + /** True if the Anys are exactly equal, ignoring comments. Applies deeply on arrays and tables. */ + bool operator==(const Any& x) const; + bool operator!=(const Any& x) const; + + operator int() const; + operator float() const; + operator double() const; + operator bool() const; + operator std::string() const; + + /** Resize to \a n elements, where new elements are NIL + It is an error to call this method if this is not an Any::ARRAY */ + void resize(int n); + + /** + Clears all entries. + This must be a TABLE or ARRAY */ + void clear(); + + /** Parse from a file. + \sa deserialize, parse */ + void load(const std::string& filename); + + /** Uses the serialize method. */ + void save(const std::string& filename) const; + + void serialize(TextOutput& to) const; + /** Parse from a stream. + \sa load, parse */ + void deserialize(TextInput& ti); + + const Source& source() const; + + /** Throws a ParseError if \a value is false. Useful for quickly + creating parse rules in classes that deserialize from Any. + */ + void verify(bool value, const std::string& message = "") const; + + /** Verifies that the name begins with identifier \a n. It may contain + identifier operators after this */ + void verifyName(const std::string& n) const; + + /** Verifies that the type is \a t. */ + void verifyType(Type t) const; + + /** Throws an exception if the type is not \a t0 or \a t1. */ + void verifyType(Type t0, Type t1) const; + + /** Verifies that the size is between \a low and \a high, inclusive */ + void verifySize(int low, int high) const; + + /** Verifies that the size is exactly \a s */ + void verifySize(int s) const; + +private: + + void deserializeTable(TextInput& ti); + void deserializeArray(TextInput& ti,const std::string& term); + +}; // class Any + +} // namespace G3D + +#endif diff --git a/externals/g3dlite/G3D/AnyVal.h b/externals/g3dlite/G3D/AnyVal.h new file mode 100644 index 00000000000..8c1bc72f206 --- /dev/null +++ b/externals/g3dlite/G3D/AnyVal.h @@ -0,0 +1,512 @@ +/** + @file AnyVal.h + @author Morgan McGuire + @created 2006-06-11 + @edited 2008-07-14 + */ + +#ifndef G3D_ANYVAL_H +#define G3D_ANYVAL_H + +#include "G3D/platform.h" +#include +#include "G3D/Array.h" +#include "G3D/TextInput.h" + +namespace G3D { +// Forward declarations for G3D types +class Vector2; +class Vector3; +class Vector4; +class Color1; +class Color3; +class Color4; +class Quat; +class Matrix2; +class Matrix3; +class Matrix4; +class CoordinateFrame; +class TextInput; +class TextOutput; +class BinaryInput; +class BinaryOutput; +class Rect2D; +class AABox; + +/** + \deprecated + Use the G3D::Any class instead. This is only provided for + backwards compatibility to G3D 7.xx. + + A generic value, useful for defining property trees that can + be loaded from and saved to disk. The values are intentionally + restricted to a small set. + + When written to files, the syntax is as follows. Note that you can + nest arrays and tables in order to create full tree (i.e., XML-like) + structures as configuration files: + + + + + + + + + + + + + + + + + + + + + + + +
NULLNil
doubleThe number in printf double format
booltrue or false
std::stringThe string in double-quotes (")
Rect2DR(x0,y0,x1,y1)
Color1C1(value)
Color3C3(r,g,b)
Color4C4(r,g,b,a)
Vector2V2(x,y)
Vector3V3(x,y,z)
Vector4V4(x,y,z,w)
QuatV(x,y,z,w)
AABoxAAB(low Vector3, high Vector3)
Matrix2M2(r0c0, r0c1, +
   
r1c0, r1c1)
Matrix3M3(r0c0, r0c1, r0c2, +
   
r1c0, r1c1, r1c2, +
   
r2c0, r2c1, r2c2)
Matrix4M4(r0c0, r0c1, r0c2, r0c3, +
   
r1c0, r1c1, r1c2, r1c3, +
   
r2c0, r2c1, r2c2, r2c3, +
   
r3c0, r3c1, r3c2, r3c3)
CoordinateFrameCF(r0c0, r0c1, r0c2, r0c3, +
   
r1c0, r1c1, r1c2, r1c3, +
   
r2c0, r2c1, r2c2, r2c3)
CoordinateFrameCF(V3(x, y, z), yaw deg, pitch deg, optional roll deg)
Array[element0, element1, ... , elementn-1]
Table{symbol0 = value0 +
 symbol1 = value1 +
 ... +
 symboln-1 = valuen-1}
+ + See also boost::any for a more general purpose but slightly harder to use + "any" for C++. + + The semantics of operator[] and the get() methods are slightly different; + operator[] acts more like a scripting language that automatically extends + arrays and tables instead of generating errors. get() has more strict semantics, + like a C++ class. + + AnyVal uses copy-on-mutate, so that AnyVal a = b semantically copies b (like int a = b would), although in practice + it delays the copy until one is mutated so that it is still fast to "copy" large arrays and tables. + + Reading example: +
+    AnyVal property = AnyVal::fromFile("c:/tmp/test.txt"));
+
+    Vector3 vel = property["angular velocity"]
+
+    Using defaults to handle errors:
+       If there was no "enabled" value, this will return the default instead of failing
+    bool enabled = property["enabled"].boolean(true);
+
+ 
+ + Writing to a file: +
+    AnyVal dict(AnyVal::TABLE);
+
+    dict["enabled"] = AnyVal(true);
+    dict["weight"] = 100;
+    dict["angular velocity"] = Vector3(1, -3, 4.5);
+
+    TextOutput t("c:/tmp/test.txt");
+    dict.serialize(t);
+    t.commit();
+  
+ + Example of a data file: +
+   {
+      heights = [1, 17, 32]
+      model = 
+        {
+           color = C3(1, 1, 1)
+           filename = "foo.md2"
+        }
+      position = V3(23, 14, 0)
+      name = "Elmer"
+   }
+  
+ +

+ What's the difference from boost::any? +
I think that AnyVal will be easier for novice C++ users. It addresses the problem that + even though G3D::TextInput makes reading configuration files extremely simple, many people + still don't use it. So AnyVal makes it ridiculously simple to read and write a tree of G3D + types to a file. + + AnyVal: +

+{
+AnyVal tree(TextInput("config.txt"));
+
+bool enabled = tree.get("enabled", false);
+Vector3 direction = tree.get("direction", Vector3::zero());
+...
+}
+
+ +boost: +
+{
+bool enabled = false;
+Vector3 direction;
+Table tree;
+
+ ...write lots of file parsing code...
+
+   if (tree.containsKey("enabled")) {
+      const boost::any& val = tree["enabled"];
+      try {
+        enabled = any_cast(val);
+      } catch(const boost::bad_any_cast &) {
+      }
+    }
+
+   if (tree.containsKey("direction")) {
+      const boost::any& val = tree["direction"];
+      try {
+        direction = any_cast(val);
+      } catch(const boost::bad_any_cast &) {
+      }
+    }
+   ...
+}
+
+ +\deprecated + */ +class AnyVal { +public: + + /** Array and table values are all Any.*/ + enum Type { + NIL, + NUMBER, + BOOLEAN, + STRING, + VECTOR2, + VECTOR3, + VECTOR4, + MATRIX2, + MATRIX3, + MATRIX4, + QUAT, + COORDINATEFRAME, + COORDINATEFRAME2D, + CFRAME = COORDINATEFRAME, + CFRAME2D = COORDINATEFRAME2D, + COLOR1, + COLOR3, + COLOR4, + RECT2D, + AABOX2D = RECT2D, + AABOX, + ARRAY, + TABLE}; + + /** Base class for all AnyVal exceptions.*/ + class Exception { + public: + virtual ~Exception() {} + }; + + /** Thrown when an inappropriate operation is performed (e.g., operator[] on a number) */ + class WrongType : public Exception { + public: + Type expected; + Type actual; + WrongType() : expected(NIL), actual(NIL) {} + WrongType(Type e, Type a) : expected(e), actual(a) {} + }; + + /** Thrown by operator[] when a key is not present. */ + class KeyNotFound : public Exception { + public: + std::string key; + KeyNotFound() {} + KeyNotFound(const std::string& k) : key(k) {} + }; + + class IndexOutOfBounds : public Exception { + public: + int index; + int size; + IndexOutOfBounds() : index(0), size(0) {} + IndexOutOfBounds(int i, int s) : index(i), size(s) {} + }; + + /** Thrown when deserialize() when the input is incorrectly formatted. */ + class CorruptText : public Exception { + public: + std::string message; + + /** Token where the problem occurred.*/ + G3D::Token token; + + CorruptText() {} + CorruptText(const std::string& s, const G3D::Token& t) : message(s), token(t) {} + }; + +private: + + Type m_type; + void* m_value; + + /** For table and array types, *m_value is shared between multiple + instances. Mutation is allowed only if the reference count is + exactly 1, otherwise the mutating instance must copy the + value. This is not used for other types. + */ + int* m_referenceCount; + + /** Decrements the reference count (if there is one). If the + reference count is zero or does not exist. Calls delete on @a + m_value and sets it to NULL. + */ + void deleteValue(); + + /** Returns a copy of the value. */ + void* copyValue() const; + + /** Assumes isSharedType. Ensures that this has a unique reference */ + void makeMutable(); + + /** True if this is a shared value between multiple instances. */ + inline bool isShared() const { + return m_referenceCount && (*m_referenceCount > 1); + } + + /** True when m_value is a double pointer */ + inline bool isSharedType() const { + return (m_type == TABLE) || (m_type == ARRAY); + } + +public: + + AnyVal(); + + /** Deserialize */ + explicit AnyVal(G3D::TextInput& t); + + static AnyVal fromFile(const std::string& filename); + + void load(const std::string& filename); + + void save(const std::string& filename) const; + + ///** Deserialize */ + //explicit AnyVal(G3D::BinaryInput& t); + + /** Construct a number */ + AnyVal(double); + AnyVal(int); + + // Explicit to avoid ambiguity with the 'double' constructor + // when an integer type is constructed + AnyVal(bool); + AnyVal(const G3D::Vector2&); + AnyVal(const G3D::Vector3&); + AnyVal(const G3D::Vector4&); + + AnyVal(const G3D::Color1&); + AnyVal(const G3D::Color3&); + AnyVal(const G3D::Color4&); + + AnyVal(const std::string&); + AnyVal(const char*); + + AnyVal(const G3D::Quat&); + + AnyVal(const G3D::Rect2D&); + AnyVal(const G3D::AABox&); + + AnyVal(const G3D::CoordinateFrame&); + AnyVal(const G3D::Matrix2&); + AnyVal(const G3D::Matrix3&); + AnyVal(const G3D::Matrix4&); + + AnyVal(const AnyVal&); + + AnyVal(Type arrayOrTable); + + AnyVal& operator=(const AnyVal&); + + /** Frees the underlying storage */ + ~AnyVal(); + + Type type() const; + + bool isNil() const { + return type() == NIL; + } + + void serialize(G3D::TextOutput& t) const; + //void serialize(G3D::BinaryOutput& t) const; + void deserialize(G3D::TextInput& t); + //void deserialize(G3D::BinaryInput& t); + + /** Array dereference. If the index is out of bounds, IndexOutOfBounds is thrown */ + const AnyVal& operator[](int) const; + + /** Extend this array by one element. */ + void append(const AnyVal&); + + /** If the index is out of bounds, the array is resized. If the index is negative, + IndexOutOfBounds is thrown.*/ + AnyVal& operator[](int); + + /** If @a i is out of bounds or this is not an ARRAY, defaultVal is returned.*/ + const AnyVal& get(int i, const AnyVal& defaultVal) const; + + /** If out of bounds, IndexOutOfBounds is thrown. */ + const AnyVal& get(int i) const; + + /** Returns defaultVal if this is not a TABLE or the key is not found. */ + const AnyVal& get(const std::string& key, const AnyVal& defaultVal) const; + + /** Throws KeyNotFound exception if the key is not present.*/ + const AnyVal& get(const std::string& key) const; + + /** Table reference */ + const AnyVal& operator[](const std::string&) const; + + /** Table reference. If the element does not exist, it is created. */ + AnyVal& operator[](const std::string&); + + /** Table reference */ + const AnyVal& operator[](const char*) const; + + /** Table reference. If the element does not exist, it is created. */ + AnyVal& operator[](const char*); + + /** If this value is not a number throws a WrongType exception. */ + double number() const; + + /** If this value is not a number, returns defaultVal. */ + double number(double defaultVal) const; + + operator double () const { + return number(); + } + + operator float () const { + return (float)number(); + } + + bool boolean() const; + bool boolean(bool b) const; + + operator bool() const { + return boolean(); + } + + const std::string& string() const; + const std::string& string(const std::string& defaultVal) const; + + operator const std::string& () const { + return string(); + } + + const G3D::Rect2D& rect2D() const; + const G3D::Rect2D& rect2D(const G3D::Rect2D& defaultVal) const; + + operator const Rect2D& () const { + return rect2D(); + } + + const G3D::AABox& aabox() const; + const G3D::AABox& aabox(const G3D::AABox& defaultVal) const; + + operator const AABox& () const { + return aabox(); + } + + const G3D::Vector2& vector2() const; + const G3D::Vector2& vector2(const G3D::Vector2& defaultVal) const; + + operator const Vector2& () const { + return vector2(); + } + + const G3D::Vector3& vector3() const; + const G3D::Vector3& vector3(const G3D::Vector3& defaultVal) const; + + operator const Vector3& () { + return vector3(); + } + + const G3D::Vector4& vector4() const; + const G3D::Vector4& vector4(const G3D::Vector4& defaultVal) const; + + operator const Vector4& () const { + return vector4(); + } + + const G3D::Color1& color1() const; + const G3D::Color1& color1(const G3D::Color1& defaultVal) const; + + const G3D::Color3& color3() const; + const G3D::Color3& color3(const G3D::Color3& defaultVal) const; + + operator const Color3& () const { + return color3(); + } + + const G3D::Color4& color4() const; + const G3D::Color4& color4(const G3D::Color4& defaultVal) const; + + operator const Color4& () const { + return color4(); + } + + const G3D::CoordinateFrame& coordinateFrame() const; + const G3D::CoordinateFrame& coordinateFrame(const G3D::CoordinateFrame& defaultVal) const; + + operator const CoordinateFrame& () const { + return coordinateFrame(); + } + + const G3D::Matrix2& matrix2() const; + const G3D::Matrix2& matrix2(const G3D::Matrix2& defaultVal) const; + + operator const Matrix2& () const { + return matrix2(); + } + + const G3D::Matrix3& matrix3() const; + const G3D::Matrix3& matrix3(const G3D::Matrix3& defaultVal) const; + + operator const Matrix3& () const { + return matrix3(); + } + + const G3D::Matrix4& matrix4() const; + const G3D::Matrix4& matrix4(const G3D::Matrix4& defaultVal) const; + + operator const Matrix4& () const { + return matrix4(); + } + + const G3D::Quat& quat() const; + const G3D::Quat& quat(const G3D::Quat& defaultVal) const; + + operator const Quat& () const { + return quat(); + } + + std::string toString() const; + + /** Number of elements for an array or table.*/ + int size() const; + + /** For a table, returns the keys. */ + void getKeys(G3D::Array&) const; +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/AreaMemoryManager.h b/externals/g3dlite/G3D/AreaMemoryManager.h new file mode 100644 index 00000000000..d8d8f710359 --- /dev/null +++ b/externals/g3dlite/G3D/AreaMemoryManager.h @@ -0,0 +1,93 @@ +/** + @file AreaMemoryManager.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2009-01-20 + @edited 2009-05-29 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + + +#ifndef G3D_AreaMemoryManager_h +#define G3D_AreaMemoryManager_h + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Array.h" +#include "G3D/MemoryManager.h" + +namespace G3D { + +/** + \brief Allocates memory in large blocks and then frees it as an area. + + Useful for ensuring cache coherence and for reducing the time cost of + multiple allocations and deallocations. + + Not threadsafe + */ +class AreaMemoryManager : public MemoryManager { +private: + + class Buffer { + private: + uint8* m_first; + size_t m_size; + size_t m_used; + + public: + + Buffer(size_t size); + + ~Buffer(); + + /** Returns NULL if out of space */ + void* alloc(size_t s); + }; + + size_t m_sizeHint; + + /** The underlying array is stored in regular MemoryManager heap memory */ + Array m_bufferArray; + + AreaMemoryManager(size_t sizeHint); + +public: + + typedef ReferenceCountedPointer Ref; + + /** + \param sizeHint Total amount of memory expected to be allocated. + The allocator will allocate memory from the system in increments + of this size. + */ + static AreaMemoryManager::Ref create(size_t sizeHint = 10 * 1024 * 1024); + + /** Invokes deallocateAll. */ + ~AreaMemoryManager(); + + size_t bytesAllocated() const; + + /** Allocates memory out of the buffer pool. + @param s must be no larger than sizeHint */ + virtual void* alloc(size_t s); + + /** Ignored. */ + virtual void free(void* x); + + virtual bool isThreadsafe() const; + + /** Deletes all previously allocated memory. Because delete is not + invoked on objects in this memory, it is not safe to simply + free memory containing C++ objects that expect their destructors + to be called. */ + void deallocateAll(); +}; + +typedef AreaMemoryManager CoherentAllocator; +} + +#endif diff --git a/externals/g3dlite/G3D/Array.h b/externals/g3dlite/G3D/Array.h new file mode 100644 index 00000000000..cc9e1d9dd01 --- /dev/null +++ b/externals/g3dlite/G3D/Array.h @@ -0,0 +1,1274 @@ +/** + @file Array.h + + @maintainer Morgan McGuire, graphics3d.com + @cite Portions written by Aaron Orenstein, a@orenstein.name + + @created 2001-03-11 + @edited 2009-05-29 + + Copyright 2000-2009, Morgan McGuire, http://graphics.cs.williams.edu + All rights reserved. + */ + +#ifndef G3D_Array_h +#define G3D_Array_h + +#include "G3D/platform.h" +#include "G3D/debug.h" +#include "G3D/System.h" +#include "G3D/MemoryManager.h" +#ifdef G3D_DEBUG +// For formatting error messages +# include "G3D/format.h" +#endif +#include +#include + +#ifdef _MSC_VER +# include + +# pragma warning (push) + // debug information too long +# pragma warning( disable : 4312) +# pragma warning( disable : 4786) +#endif + + +namespace G3D { + +/** + Constant for passing to Array::resize + */ +const bool DONT_SHRINK_UNDERLYING_ARRAY = false; + +/** Constant for Array::sort */ +const int SORT_INCREASING = 1; +/** Constant for Array::sort */ +const int SORT_DECREASING = -1; + +/** + \brief Dynamic 1D array tuned for performance. + + Objects must have a default constructor (constructor that + takes no arguments) in order to be used with this template. + You will get the error "no appropriate default constructor found" + if they do not. + + Do not use with objects that overload placement operator new, + since the speed of Array is partly due to pooled allocation. + + Array is highly optimized compared to std::vector. + Array operations are less expensive than on std::vector and for large + amounts of data, Array consumes only 1.5x the total size of the + data, while std::vector consumes 2.0x. The default + array takes up zero heap space. The first resize (or append) + operation grows it to a reasonable internal size so it is efficient + to append to small arrays. + + Then Array needs to copy + data internally on a resize operation it correctly invokes copy + constructors of the elements (the MSVC6 implementation of + std::vector uses realloc, which can create memory leaks for classes + containing references and pointers). Array provides a guaranteed + safe way to access the underlying data as a flat C array -- + Array::getCArray. Although (T*)std::vector::begin() can be used for + this purpose, it is not guaranteed to succeed on all platforms. + + To serialize an array, see G3D::serialize. + + The template parameter MIN_ELEMENTS indicates the smallest number of + elements that will be allocated. The default of 10 is designed to avoid + the overhead of repeatedly allocating the array as it grows from 1, to 2, and so on. + If you are creating a lot of small Arrays, however, you may want to set this smaller + to reduce the memory cost. Once the array has been allocated, it will never + deallocate the underlying array unless MIN_ELEMENTS is set to 0, MIN_BYTES is 0, and the array + is empty. + + Do not subclass an Array. + + \sa G3D::SmallArray + */ +template +class Array { +private: + /** 0...num-1 are initialized elements, num...numAllocated-1 are not */ + T* data; + + int num; + int numAllocated; + + MemoryManager::Ref m_memoryManager; + + /** \param n Number of elements + */ + void init(int n, const MemoryManager::Ref& m) { + m_memoryManager = m; + debugAssert(n >= 0); + this->num = 0; + this->numAllocated = 0; + data = NULL; + if (n > 0) { + resize(n); + } else { + data = NULL; + } + } + + void _copy(const Array &other) { + init(other.num, MemoryManager::create()); + for (int i = 0; i < num; i++) { + data[i] = other.data[i]; + } + } + + /** + Returns true iff address points to an element of this array. + Used by append. + */ + inline bool inArray(const T* address) { + return (address >= data) && (address < data + num); + } + + + /** Only compiled if you use the sort procedure. */ + static bool __cdecl compareGT(const T& a, const T& b) { + return a > b; + } + + + /** + Allocates a new array of size numAllocated (not a parameter to the method) + and then copies at most oldNum elements from the old array to it. Destructors are + called for oldNum elements of the old array. + */ + void realloc(int oldNum) { + T* oldData = data; + + // The allocation is separate from the constructor invocation because we don't want + // to pay for the cost of constructors until the newly allocated + // elements are actually revealed to the application. They + // will be constructed in the resize() method. + + data = (T*)m_memoryManager->alloc(sizeof(T) * numAllocated); + alwaysAssertM(data, "Memory manager returned NULL: out of memory?"); + + // Call the copy constructors + {const int N = G3D::min(oldNum, numAllocated); + const T* end = data + N; + T* oldPtr = oldData; + for (T* ptr = data; ptr < end; ++ptr, ++oldPtr) { + + // Use placement new to invoke the constructor at the location + // that we determined. Use the copy constructor to make the assignment. + const T* constructed = new (ptr) T(*oldPtr); + + (void)constructed; + debugAssertM(constructed == ptr, + "new returned a different address than the one provided by Array."); + }} + + // Call destructors on the old array (if there is no destructor, this will compile away) + {const T* end = oldData + oldNum; + for (T* ptr = oldData; ptr < end; ++ptr) { + ptr->~T(); + }} + + m_memoryManager->free(oldData); + } + +public: + + /** + G3D C++ STL style iterator variable. Call begin() to get + the first iterator, pre-increment (++i) the iterator to get to + the next value. Use dereference (*i) to access the element. + */ + typedef T* Iterator; + /** G3D C++ STL style const iterator in same style as Iterator. */ + typedef const T* ConstIterator; + + /** stl porting compatibility helper */ + typedef Iterator iterator; + /** stl porting compatibility helper */ + typedef ConstIterator const_iterator; + /** stl porting compatibility helper */ + typedef T value_type; + /** stl porting compatibility helper */ + typedef int size_type; + /** stl porting compatibility helper */ + typedef int difference_type; + + /** + C++ STL style iterator method. Returns the first iterator element. + Do not change the size of the array while iterating. + */ + Iterator begin() { + return data; + } + + ConstIterator begin() const { + return data; + } + /** + C++ STL style iterator method. Returns one after the last iterator + element. + */ + ConstIterator end() const { + return data + num; + } + + Iterator end() { + return data + num; + } + + /** + The array returned is only valid until the next append() or resize call, or + the Array is deallocated. + */ + T* getCArray() { + return data; + } + + /** + The array returned is only valid until the next append() or resize call, or + the Array is deallocated. + */ + const T* getCArray() const { + return data; + } + + /** Creates a zero length array (no heap allocation occurs until resize). */ + Array() : num(0) { + init(0, MemoryManager::create()); + debugAssert(num >= 0); + } + + + /** Creates an array containing v0. */ + Array(const T& v0) { + init(1, MemoryManager::create()); + (*this)[0] = v0; + } + + /** Creates an array containing v0 and v1. */ + Array(const T& v0, const T& v1) { + init(2, MemoryManager::create()); + (*this)[0] = v0; + (*this)[1] = v1; + } + + /** Creates an array containing v0...v2. */ + Array(const T& v0, const T& v1, const T& v2) { + init(3, MemoryManager::create()); + (*this)[0] = v0; + (*this)[1] = v1; + (*this)[2] = v2; + } + + /** Creates an array containing v0...v3. */ + Array(const T& v0, const T& v1, const T& v2, const T& v3) { + init(4, MemoryManager::create()); + (*this)[0] = v0; + (*this)[1] = v1; + (*this)[2] = v2; + (*this)[3] = v3; + } + + /** Creates an array containing v0...v4. */ + Array(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) { + init(5, MemoryManager::create()); + (*this)[0] = v0; + (*this)[1] = v1; + (*this)[2] = v2; + (*this)[3] = v3; + (*this)[4] = v4; + } + + + /** + Copy constructor + */ + Array(const Array& other) : num(0) { + _copy(other); + debugAssert(num >= 0); + } + + /** + Destructor does not delete() the objects if T is a pointer type + (e.g. T = int*) instead, it deletes the pointers themselves and + leaves the objects. Call deleteAll if you want to dealocate + the objects referenced. Do not call deleteAll if T is not a pointer + type (e.g. do call Array::deleteAll, do not call Array::deleteAll). + */ + ~Array() { + // Invoke the destructors on the elements + for (int i = 0; i < num; i++) { + (data + i)->~T(); + } + + m_memoryManager->free(data); + // Set to 0 in case this Array is global and gets referenced during app exit + data = NULL; + num = 0; + numAllocated = 0; + } + + /** + Removes all elements. Use resize(0, false) or fastClear if you want to + remove all elements without deallocating the underlying array + so that future append() calls will be faster. + */ + void clear(bool shrink = true) { + resize(0, shrink); + } + + void clearAndSetMemoryManager(const MemoryManager::Ref& m) { + clear(); + debugAssert(data == NULL); + m_memoryManager = m; + } + + /** resize(0, false) + @deprecated*/ + void fastClear() { + clear(false); + } + + /** + Assignment operator. + */ + Array& operator=(const Array& other) { + debugAssert(num >= 0); + resize(other.num); for (int i = 0; i < num; ++i) { + data[i] = other[i]; + } + debugAssert(num >= 0); + return *this; + } + + Array& operator=(const std::vector& other) { + resize((int)other.size()); + for (int i = 0; i < num; ++i) { + data[i] = other[i]; + } + return *this; + } + + inline MemoryManager::Ref memoryManager() const { + return m_memoryManager; + } + + /** + Number of elements in the array. + */ + inline int size() const { + return num; + } + + /** + Number of elements in the array. (Same as size; this is just + here for convenience). + */ + inline int length() const { + return size(); + } + + /** + Swaps element index with the last element in the array then + shrinks the array by one. + */ + void fastRemove(int index, bool shrinkIfNecessary = false) { + debugAssert(index >= 0); + debugAssert(index < num); + data[index] = data[num - 1]; + resize(size() - 1, shrinkIfNecessary); + } + + + /** + Inserts at the specified index and shifts all other elements up by one. + */ + void insert(int n, const T& value) { + // Add space for the extra element + resize(num + 1, false); + + for (int i = num - 1; i > n; --i) { + data[i] = data[i - 1]; + } + data[n] = value; + } + + /** @param shrinkIfNecessary if false, memory will never be + reallocated when the array shrinks. This makes resizing much + faster but can waste memory. + */ + void resize(int n, bool shrinkIfNecessary = true) { + debugAssert(n >= 0); + if (num == n) { + return; + } + + int oldNum = num; + num = n; + + // Call the destructors on newly hidden elements if there are any + for (int i = num; i < oldNum; ++i) { + (data + i)->~T(); + } + + // Once allocated, always maintain MIN_ELEMENTS elements or 32 bytes, whichever is higher. + const int minSize = std::max(MIN_ELEMENTS, (int)(MIN_BYTES / sizeof(T))); + + if ((MIN_ELEMENTS == 0) && (MIN_BYTES == 0) && (n == 0) && shrinkIfNecessary) { + // Deallocate the array completely + numAllocated = 0; + m_memoryManager->free(data); + data = NULL; + return; + } + + if (num > numAllocated) { + // Grow the underlying array + + if (numAllocated == 0) { + // First allocation; grow to exactly the size requested to avoid wasting space. + numAllocated = n; + debugAssert(oldNum == 0); + realloc(oldNum); + } else { + + if (num < minSize) { + // Grow to at least the minimum size + numAllocated = minSize; + + } else { + + // Increase the underlying size of the array. Grow aggressively + // up to 64k, less aggressively up to 400k, and then grow relatively + // slowly (1.5x per resize) to avoid excessive space consumption. + // + // These numbers are tweaked according to performance tests. + + float growFactor = 3.0; + + int oldSizeBytes = numAllocated * sizeof(T); + if (oldSizeBytes > 400000) { + // Avoid bloat + growFactor = 1.5; + } else if (oldSizeBytes > 64000) { + // This is what std:: uses at all times + growFactor = 2.0; + } + + numAllocated = (num - numAllocated) + (int)(numAllocated * growFactor); + + if (numAllocated < minSize) { + numAllocated = minSize; + } + } + + realloc(oldNum); + } + + } else if ((num <= numAllocated / 3) && shrinkIfNecessary && (num > minSize)) { + // Shrink the underlying array + + // Only copy over old elements that still remain after resizing + // (destructors were called for others if we're shrinking) + realloc(iMin(num, oldNum)); + + } + + // Call the constructors on newly revealed elements. + // Do not use parens because we don't want the intializer + // invoked for POD types. + for (int i = oldNum; i < num; ++i) { + new (data + i) T; + } + } + + /** + Add an element to the end of the array. Will not shrink the underlying array + under any circumstances. It is safe to append an element that is already + in the array. + */ + inline void append(const T& value) { + + if (num < numAllocated) { + // This is a simple situation; just stick it in the next free slot using + // the copy constructor. + new (data + num) T(value); + ++num; + } else if (inArray(&value)) { + // The value was in the original array; resizing + // is dangerous because it may move the value + // we have a reference to. + T tmp = value; + append(tmp); + } else { + // Here we run the empty initializer where we don't have to, but + // this simplifies the computation. + resize(num + 1, DONT_SHRINK_UNDERLYING_ARRAY); + data[num - 1] = value; + } + } + + + inline void append(const T& v1, const T& v2) { + if (inArray(&v1) || inArray(&v2)) { + // Copy into temporaries so that the references won't break when + // the array resizes. + T t1 = v1; + T t2 = v2; + append(t1, t2); + } else if (num + 1 < numAllocated) { + // This is a simple situation; just stick it in the next free slot using + // the copy constructor. + new (data + num) T(v1); + new (data + num + 1) T(v2); + num += 2; + } else { + // Resize the array. Note that neither value is already in the array. + resize(num + 2, DONT_SHRINK_UNDERLYING_ARRAY); + data[num - 2] = v1; + data[num - 1] = v2; + } + } + + + inline void append(const T& v1, const T& v2, const T& v3) { + if (inArray(&v1) || inArray(&v2) || inArray(&v3)) { + T t1 = v1; + T t2 = v2; + T t3 = v3; + append(t1, t2, t3); + } else if (num + 2 < numAllocated) { + // This is a simple situation; just stick it in the next free slot using + // the copy constructor. + new (data + num) T(v1); + new (data + num + 1) T(v2); + new (data + num + 2) T(v3); + num += 3; + } else { + resize(num + 3, DONT_SHRINK_UNDERLYING_ARRAY); + data[num - 3] = v1; + data[num - 2] = v2; + data[num - 1] = v3; + } + } + + + inline void append(const T& v1, const T& v2, const T& v3, const T& v4) { + if (inArray(&v1) || inArray(&v2) || inArray(&v3) || inArray(&v4)) { + T t1 = v1; + T t2 = v2; + T t3 = v3; + T t4 = v4; + append(t1, t2, t3, t4); + } else if (num + 3 < numAllocated) { + // This is a simple situation; just stick it in the next free slot using + // the copy constructor. + new (data + num) T(v1); + new (data + num + 1) T(v2); + new (data + num + 2) T(v3); + new (data + num + 3) T(v4); + num += 4; + } else { + resize(num + 4, DONT_SHRINK_UNDERLYING_ARRAY); + data[num - 4] = v1; + data[num - 3] = v2; + data[num - 2] = v3; + data[num - 1] = v4; + } + } + + /** + Returns true if the given element is in the array. + */ + bool contains(const T& e) const { + for (int i = 0; i < size(); ++i) { + if ((*this)[i] == e) { + return true; + } + } + + return false; + } + + /** + Append the elements of array. Cannot be called with this array + as an argument. + */ + void append(const Array& array) { + debugAssert(this != &array); + int oldNum = num; + int arrayLength = array.length(); + + resize(num + arrayLength, false); + + for (int i = 0; i < arrayLength; i++) { + data[oldNum + i] = array.data[i]; + } + } + + /** + Pushes a new element onto the end and returns its address. + This is the same as A.resize(A.size() + 1, false); A.last() + */ + inline T& next() { + resize(num + 1, false); + return last(); + } + + /** + Pushes an element onto the end (appends) + */ + inline void push(const T& value) { + append(value); + } + + inline void push(const Array& array) { + append(array); + } + + /** Alias to provide std::vector compatibility */ + inline void push_back(const T& v) { + push(v); + } + + /** "The member function removes the last element of the controlled sequence, which must be non-empty." + For compatibility with std::vector. */ + inline void pop_back() { + pop(); + } + + /** + "The member function returns the storage currently allocated to hold the controlled + sequence, a value at least as large as size()" + For compatibility with std::vector. + */ + int capacity() const { + return numAllocated; + } + + /** + "The member function returns a reference to the first element of the controlled sequence, + which must be non-empty." + For compatibility with std::vector. + */ + T& front() { + return (*this)[0]; + } + + /** + "The member function returns a reference to the first element of the controlled sequence, + which must be non-empty." + For compatibility with std::vector. + */ + const T& front() const { + return (*this)[0]; + } + + /** + "The member function returns a reference to the last element of the controlled sequence, + which must be non-empty." + For compatibility with std::vector. + */ + T& back() { + return (*this)[size()-1]; + } + + /** + "The member function returns a reference to the last element of the controlled sequence, + which must be non-empty." + For compatibility with std::vector. + */ + const T& back() const { + return (*this)[size()-1]; + } + + /** + Removes the last element and returns it. By default, shrinks the underlying array. + */ + inline T pop(bool shrinkUnderlyingArrayIfNecessary = true) { + debugAssert(num > 0); + T temp = data[num - 1]; + resize(num - 1, shrinkUnderlyingArrayIfNecessary); + return temp; + } + + /** Pops the last element and discards it without returning anything. Faster than pop. + By default, does not shrink the underlying array.*/ + inline void popDiscard(bool shrinkUnderlyingArrayIfNecessary = false) { + debugAssert(num > 0); + resize(num - 1, shrinkUnderlyingArrayIfNecessary); + } + + + /** + "The member function swaps the controlled sequences between *this and str." + Note that this is slower than the optimal std implementation. + + For compatibility with std::vector. + */ + void swap(Array& str) { + Array temp = str; + str = *this; + *this = temp; + } + + + /** + Performs bounds checks in debug mode + */ + inline T& operator[](int n) { + debugAssertM((n >= 0) && (n < num), format("Array index out of bounds. n = %d, size() = %d", n, num)); + debugAssert(data!=NULL); + return data[n]; + } + + inline T& operator[](unsigned int n) { + debugAssertM(n < (unsigned int)num, format("Array index out of bounds. n = %d, size() = %d", n, num)); + return data[n]; + } + + /** + Performs bounds checks in debug mode + */ + inline const T& operator[](int n) const { + debugAssert((n >= 0) && (n < num)); + debugAssert(data!=NULL); + return data[n]; + } + + inline const T& operator[](unsigned int n) const { + debugAssert((n < (unsigned int)num)); + debugAssert(data!=NULL); + return data[n]; + } + + inline T& randomElement() { + debugAssert(num > 0); + debugAssert(data!=NULL); + return data[iRandom(0, num - 1)]; + } + + inline const T& randomElement() const { + debugAssert(num > 0); + debugAssert(data!=NULL); + return data[iRandom(0, num - 1)]; + } + + /** + Returns the last element, performing a check in + debug mode that there is at least one element. + */ + inline const T& last() const { + debugAssert(num > 0); + debugAssert(data!=NULL); + return data[num - 1]; + } + + /** Returns element lastIndex() */ + inline T& last() { + debugAssert(num > 0); + debugAssert(data!=NULL); + return data[num - 1]; + } + + /** Returns size() - 1 */ + inline int lastIndex() const { + debugAssertM(num > 0, "Array is empty"); + return num - 1; + } + + inline int firstIndex() const { + debugAssertM(num > 0, "Array is empty"); + return 0; + } + + /** Returns element firstIndex(), performing a check in debug mode to ensure that there is at least one */ + inline T& first() { + debugAssertM(num > 0, "Array is empty"); + return data[0]; + } + + inline const T& first() const { + debugAssertM(num > 0, "Array is empty"); + return data[0]; + } + + /** Returns iFloor(size() / 2), throws an assertion in debug mode if the array is empty */ + inline int middleIndex() const { + debugAssertM(num > 0, "Array is empty"); + return num >> 1; + } + + /** Returns element middleIndex() */ + inline const T& middle() const { + debugAssertM(num > 0, "Array is empty"); + return data[num >> 1]; + } + + /** Returns element middleIndex() */ + inline T& middle() { + debugAssertM(num > 0, "Array is empty"); + return data[num >> 1]; + } + + /** + Calls delete on all objects[0...size-1] + and sets the size to zero. + */ + void deleteAll() { + for (int i = 0; i < num; i++) { + delete data[i]; + } + resize(0); + } + + /** + Returns the index of (the first occurance of) an index or -1 if + not found. Searches from the right. + */ + int rfindIndex(const T& value) const { + for (int i = num -1 ; i >= 0; --i) { + if (data[i] == value) { + return i; + } + } + return -1; + } + + /** + Returns the index of (the first occurance of) an index or -1 if + not found. + */ + int findIndex(const T& value) const { + for (int i = 0; i < num; ++i) { + if (data[i] == value) { + return i; + } + } + return -1; + } + + /** + Finds an element and returns the iterator to it. If the element + isn't found then returns end(). + */ + Iterator find(const T& value) { + for (int i = 0; i < num; ++i) { + if (data[i] == value) { + return data + i; + } + } + return end(); + } + + ConstIterator find(const T& value) const { + for (int i = 0; i < num; ++i) { + if (data[i] == value) { + return data + i; + } + } + return end(); + } + + /** + Removes count elements from the array + referenced either by index or Iterator. + */ + void remove(Iterator element, int count = 1) { + debugAssert((element >= begin()) && (element < end())); + debugAssert((count > 0) && (element + count) <= end()); + Iterator last = end() - count; + + while(element < last) { + element[0] = element[count]; + ++element; + } + + resize(num - count); + } + + void remove(int index, int count = 1) { + debugAssert((index >= 0) && (index < num)); + debugAssert((count > 0) && (index + count <= num)); + + remove(begin() + index, count); + } + + /** + Reverse the elements of the array in place. + */ + void reverse() { + T temp; + + int n2 = num / 2; + for (int i = 0; i < n2; ++i) { + temp = data[num - 1 - i]; + data[num - 1 - i] = data[i]; + data[i] = temp; + } + } + + /** + Sort using a specific less-than function, e.g.: + +
+    bool __cdecl myLT(const MyClass& elem1, const MyClass& elem2) {
+        return elem1.x < elem2.x;
+    }
+    
+ + Note that for pointer arrays, the const must come + after the class name, e.g., Array uses: + +
+    bool __cdecl myLT(MyClass*const& elem1, MyClass*const& elem2) {
+        return elem1->x < elem2->x;
+    }
+    
+ + or a functor, e.g., +
+bool
+less_than_functor::operator()( const double& lhs, const double& rhs ) const
+{
+return( lhs < rhs? true : false );
+}
+
+ */ + // void sort(bool (__cdecl *lessThan)(const T& elem1, const T& elem2)) { + // std::sort(data, data + num, lessThan); + //} + template + void sort(const LessThan& lessThan) { + // Using std::sort, which according to http://www.open-std.org/JTC1/SC22/WG21/docs/D_4.cpp + // was 2x faster than qsort for arrays around size 2000 on intel core2 with gcc + std::sort(data, data + num, lessThan); + } + + /** + Sorts the array in increasing order using the > or < operator. To + invoke this method on Array, T must override those operator. + You can overide these operators as follows: + + bool T::operator>(const T& other) const { + return ...; + } + bool T::operator<(const T& other) const { + return ...; + } + + */ + void sort(int direction = SORT_INCREASING) { + if (direction == SORT_INCREASING) { + std::sort(data, data + num); + } else { + std::sort(data, data + num, compareGT); + } + } + + /** + Sorts elements beginIndex through and including endIndex. + */ + void sortSubArray(int beginIndex, int endIndex, int direction = SORT_INCREASING) { + if (direction == SORT_INCREASING) { + std::sort(data + beginIndex, data + endIndex + 1); + } else { + std::sort(data + beginIndex, data + endIndex + 1, compareGT); + } + } + + void sortSubArray(int beginIndex, int endIndex, bool (__cdecl *lessThan)(const T& elem1, const T& elem2)) { + std::sort(data + beginIndex, data + endIndex + 1, lessThan); + } + + /** + The StrictWeakOrdering can be either a class that overloads the function call operator() or + a function pointer of the form bool (__cdecl *lessThan)(const T& elem1, const T& elem2) + */ + template + void sortSubArray(int beginIndex, int endIndex, StrictWeakOrdering& lessThan) { + std::sort(data + beginIndex, data + endIndex + 1, lessThan); + } + + /** Uses < and == to evaluate operator(); this is the default comparator for Array::partition. */ + class DefaultComparator { + public: + inline int operator()(const T& A, const T& B) const { + if (A < B) { + return 1; + } else if (A == B) { + return 0; + } else { + return -1; + } + } + }; + + /** The output arrays are resized with fastClear() so that if they are already of the same size + as this array no memory is allocated during partitioning. + + @param comparator A function, or class instance with an overloaded operator() that compares + two elements of type T and returns 0 if they are equal, -1 if the second is smaller, + and 1 if the first is smaller (i.e., following the conventions of std::string::compare). For example: + +
+        int compare(int A, int B) {
+            if (A < B) {
+                return 1;
+            } else if (A == B) {
+                return 0;
+            } else {
+                return -1;
+            }
+        }
+        
+ */ + template + void partition( + const T& partitionElement, + Array& ltArray, + Array& eqArray, + Array& gtArray, + const Comparator& comparator) const { + + // Make sure all arrays are independent + debugAssert(<Array != this); + debugAssert(&eqArray != this); + debugAssert(>Array != this); + debugAssert(<Array != &eqArray); + debugAssert(<Array != >Array); + debugAssert(&eqArray != >Array); + + // Clear the arrays + ltArray.fastClear(); + eqArray.fastClear(); + gtArray.fastClear(); + + // Form a table of buckets for lt, eq, and gt + Array* bucket[3] = {<Array, &eqArray, >Array}; + + for (int i = 0; i < num; ++i) { + int c = comparator(partitionElement, data[i]); + debugAssertM(c >= -1 && c <= 1, "Comparator returned an illegal value."); + + // Insert into the correct bucket, 0, 1, or 2 + bucket[c + 1]->append(data[i]); + } + } + + /** + Uses < and == on elements to perform a partition. See partition(). + */ + void partition( + const T& partitionElement, + Array& ltArray, + Array& eqArray, + Array& gtArray) const { + + partition(partitionElement, ltArray, eqArray, gtArray, typename Array::DefaultComparator()); + } + + /** + Paritions the array into those below the median, those above the median, and those elements + equal to the median in expected O(n) time using quickselect. If the array has an even + number of different elements, the median for partition purposes is the largest value + less than the median. + + @param tempArray used for working scratch space + @param comparator see parition() for a discussion.*/ + template + void medianPartition( + Array& ltMedian, + Array& eqMedian, + Array& gtMedian, + Array& tempArray, + const Comparator& comparator) const { + + ltMedian.fastClear(); + eqMedian.fastClear(); + gtMedian.fastClear(); + + // Handle trivial cases first + switch (size()) { + case 0: + // Array is empty; no parition is possible + return; + + case 1: + // One element + eqMedian.append(first()); + return; + + case 2: + { + // Two element array; median is the smaller + int c = comparator(first(), last()); + + switch (c) { + case -1: + // first was bigger + eqMedian.append(last()); + gtMedian.append(first()); + break; + + case 0: + // Both equal to the median + eqMedian.append(first(), last()); + break; + + case 1: + // Last was bigger + eqMedian.append(first()); + gtMedian.append(last()); + break; + } + } + return; + } + + // All other cases use a recursive randomized median + + // Number of values less than all in the current arrays + int ltBoost = 0; + + // Number of values greater than all in the current arrays + int gtBoost = 0; + + // For even length arrays, force the gt array to be one larger than the + // lt array: + // [1 2 3] size = 3, choose half = (s + 1) /2 + // + int lowerHalfSize, upperHalfSize; + if (isEven(size())) { + lowerHalfSize = size() / 2; + upperHalfSize = lowerHalfSize + 1; + } else { + lowerHalfSize = upperHalfSize = (size() + 1) / 2; + } + const T* xPtr = NULL; + + // Maintain pointers to the arrays; we'll switch these around during sorting + // to avoid copies. + const Array* source = this; + Array* lt = <Median; + Array* eq = &eqMedian; + Array* gt = >Median; + Array* extra = &tempArray; + + while (true) { + // Choose a random element -- choose the middle element; this is theoretically + // suboptimal, but for loosly sorted array is actually the best strategy + + xPtr = &(source->middle()); + if (source->size() == 1) { + // Done; there's only one element left + break; + } + const T& x = *xPtr; + + // Note: partition (fast) clears the arrays for us + source->partition(x, *lt, *eq, *gt, comparator); + + int L = lt->size() + ltBoost + eq->size(); + int U = gt->size() + gtBoost + eq->size(); + if ((L >= lowerHalfSize) && + (U >= upperHalfSize)) { + + // x must be the partition median + break; + + } else if (L < lowerHalfSize) { + + // x must be smaller than the median. Recurse into the 'gt' array. + ltBoost += lt->size() + eq->size(); + + // The new gt array will be the old source array, unless + // that was the this pointer (i.e., unless we are on the + // first iteration) + Array* newGt = (source == this) ? extra : const_cast*>(source); + + // Now set up the gt array as the new source + source = gt; + gt = newGt; + + } else { + + // x must be bigger than the median. Recurse into the 'lt' array. + gtBoost += gt->size() + eq->size(); + + // The new lt array will be the old source array, unless + // that was the this pointer (i.e., unless we are on the + // first iteration) + Array* newLt = (source == this) ? extra : const_cast*>(source); + + // Now set up the lt array as the new source + source = lt; + lt = newLt; + } + } + + // Now that we know the median, make a copy of it (since we're about to destroy the array that it + // points into). + T median = *xPtr; + xPtr = NULL; + + // Partition the original array (note that this fast clears for us) + partition(median, ltMedian, eqMedian, gtMedian, comparator); + } + + /** + Computes a median partition using the default comparator and a dynamically allocated temporary + working array. If the median is not in the array, it is chosen to be the largest value smaller + than the true median. + */ + void medianPartition( + Array& ltMedian, + Array& eqMedian, + Array& gtMedian) const { + + Array temp; + medianPartition(ltMedian, eqMedian, gtMedian, temp, DefaultComparator()); + } + + + /** Redistributes the elements so that the new order is statistically independent + of the original order. O(n) time.*/ + void randomize() { + T temp; + + for (int i = size() - 1; i >= 0; --i) { + int x = iRandom(0, i); + + temp = data[i]; + data[i] = data[x]; + data[x] = temp; + } + } + + +}; + + +/** Array::contains for C-arrays */ +template bool contains(const T* array, int len, const T& e) { + for (int i = len - 1; i >= 0; --i) { + if (array[i] == e) { + return true; + } + } + return false; +} + +} // namespace + +#ifdef _MSC_VER +# pragma warning (pop) +#endif + +#endif diff --git a/externals/g3dlite/G3D/AtomicInt32.h b/externals/g3dlite/G3D/AtomicInt32.h new file mode 100644 index 00000000000..2d63f998355 --- /dev/null +++ b/externals/g3dlite/G3D/AtomicInt32.h @@ -0,0 +1,164 @@ +/** + @file AtomicInt32.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2005-09-01 + @edited 2006-06-21 + */ +#ifndef G3D_ATOMICINT32_H +#define G3D_ATOMICINT32_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" + +#if defined(G3D_OSX) +# include +#endif + +namespace G3D { + +/** + An integer that may safely be used on different threads without + external locking. + + On Win32, Linux, FreeBSD, and Mac OS X this is implemented without locks. + + BETA API This is unsupported and may change + */ +class AtomicInt32 { +private: +# if defined(G3D_WIN32) + volatile long m_value; +# elif defined(G3D_OSX) + int32_t m_value; +# else + volatile int32 m_value; +# endif + + +public: + + /** Initial value is undefined. */ + AtomicInt32() {} + + /** Atomic set */ + explicit AtomicInt32(const int32 x) { + m_value = x; + } + + /** Atomic set */ + AtomicInt32(const AtomicInt32& x) { + m_value = x.m_value; + } + + /** Atomic set */ + const AtomicInt32& operator=(const int32 x) { + m_value = x; + return *this; + } + + /** Atomic set */ + void operator=(const AtomicInt32& x) { + m_value = x.m_value; + } + + /** Returns the current value */ + int32 value() const { + return m_value; + } + + /** Returns the old value, before the add. */ + int32 add(const int32 x) { +# if defined(G3D_WIN32) + + return InterlockedExchangeAdd(&m_value, x); + +# elif defined(G3D_LINUX) || defined(G3D_FREEBSD) + + int32 old; + asm volatile ("lock; xaddl %0,%1" + : "=r"(old), "=m"(m_value) /* outputs */ + : "0"(x), "m"(m_value) /* inputs */ + : "memory", "cc"); + return old; + +# elif defined(G3D_OSX) + + int32 old = m_value; + OSAtomicAdd32(x, &m_value); + return old; + +# endif + } + + /** Returns old value. */ + int32 sub(const int32 x) { + return add(-x); + } + + void increment() { +# if defined(G3D_WIN32) + // Note: returns the newly incremented value + InterlockedIncrement(&m_value); +# elif defined(G3D_LINUX) || defined(G3D_FREEBSD) + add(1); +# elif defined(G3D_OSX) + // Note: returns the newly incremented value + OSAtomicIncrement32(&m_value); +# endif + } + + /** Returns zero if the result is zero after decrement, non-zero otherwise.*/ + int32 decrement() { +# if defined(G3D_WIN32) + // Note: returns the newly decremented value + return InterlockedDecrement(&m_value); +# elif defined(G3D_LINUX) || defined(G3D_FREEBSD) + unsigned char nz; + + asm volatile ("lock; decl %1;\n\t" + "setnz %%al" + : "=a" (nz) + : "m" (m_value) + : "memory", "cc"); + return nz; +# elif defined(G3D_OSX) + // Note: returns the newly decremented value + return OSAtomicDecrement32(&m_value); +# endif + } + + + /** Atomic test-and-set: if *this == comperand then *this := exchange else do nothing. + In both cases, returns the old value of *this. + + Performs an atomic comparison of this with the Comperand value. + If this is equal to the Comperand value, the Exchange value is stored in this. + Otherwise, no operation is performed. + + Under VC6 the sign bit may be lost. + */ + int32 compareAndSet(const int32 comperand, const int32 exchange) { +# if defined(G3D_WIN32) + return InterlockedCompareExchange(&m_value, exchange, comperand); +# elif defined(G3D_LINUX) || defined(G3D_FREEBSD) || defined(G3D_OSX) + // Based on Apache Portable Runtime + // http://koders.com/c/fid3B6631EE94542CDBAA03E822CA780CBA1B024822.aspx + int32 ret; + asm volatile ("lock; cmpxchgl %1, %2" + : "=a" (ret) + : "r" (exchange), "m" (m_value), "0"(comperand) + : "memory", "cc"); + return ret; + + // Note that OSAtomicCompareAndSwap32 does not return a useful value for us + // so it can't satisfy the cmpxchgl contract. +# endif + } + +}; + +} // namespace + +#endif diff --git a/externals/g3dlite/G3D/BinaryFormat.h b/externals/g3dlite/G3D/BinaryFormat.h new file mode 100644 index 00000000000..f6719a1c540 --- /dev/null +++ b/externals/g3dlite/G3D/BinaryFormat.h @@ -0,0 +1,140 @@ +/** + @file BinaryFormat.h + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @author 2005-06-03 + @edited 2005-06-03 + + Copyright 2000-2005, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_BINARYFORMAT_H +#define G3D_BINARYFORMAT_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" + +namespace G3D { + +class Vector2; +class Vector2int16; +class Vector3; +class Vector3int16; +class Vector4; +class Vector4int16; +class Color3; +class Color3uint8; +class Color4; +class Color4uint8; + +/** + Some values like float16 and int128 have no current CPU data structure that implements them but are useful + for file formats and for GPUs. + + CHUNK_BINFMT data follows the protocol. + */ +// Must be packed int 16 bits for the chunk reader +// We can't name these just "INT8" etc. because some libraries #define names like that +enum BinaryFormat { + FIRST_BINFMT = 1000, + + BOOL8_BINFMT, + UINT8_BINFMT, INT8_BINFMT, UINT16_BINFMT, INT16_BINFMT, UINT32_BINFMT, INT32_BINFMT, UINT64_BINFMT, INT64_BINFMT, UINT128_BINFMT, INT128_BINFMT, + FLOAT16_BINFMT, FLOAT32_BINFMT, FLOAT64_BINFMT, + VECTOR2_BINFMT, VECTOR2INT16_BINFMT, + VECTOR3_BINFMT, VECTOR3INT16_BINFMT, + VECTOR4_BINFMT, VECTOR4INT16_BINFMT, + COLOR3_BINFMT, COLOR3UINT8_BINFMT, COLOR3INT16_BINFMT, + COLOR4_BINFMT, COLOR4UINT8_BINFMT, COLOR4INT16_BINFMT, + STRING_BINFMT, STRINGEVEN_BINFMT, STRING8_BINFMT, STRING16_BINFMT, STRING32_BINFMT, + + CHUNK_BINFMT, + + CUSTOM_BINFMT, + + LAST_BINFMT +}; + +} + +/** A macro that maps G3D types to format constants. + (e.g. binaryFormatOf(Vector3) == VECTOR3_BINFMT). +*/ +// This implementation is designed to meet the following constraints: +// 1. Work around the many MSVC++ partial template bugs +// 2. Work for primitive types (e.g. int) +#define binaryFormatOf(T) (G3D::_internal::_BinaryFormat::x()) + +namespace G3D { +namespace _internal { + + +template class _BinaryFormat { +public: + static BinaryFormat x() { + return CUSTOM_BINFMT; + } +}; +}} + + +/** + Macro to declare the underlying format (as will be returned by glFormatOf) + of a type. For example, + +
+    DECLARE_BINARYFORMATOF(Vector4, VECTOR4_BINFMT)
+  
+ + Use this so you can make vertex arrays of your own classes and not just + the standard ones. + */ +#define DECLARE_BINARYFORMATOF(CType, EnumType) \ +namespace G3D { \ + namespace _internal { \ + template<> class _BinaryFormat { \ + public: \ + static BinaryFormat x() { \ + return EnumType; \ + } \ + }; \ + } \ +} + +DECLARE_BINARYFORMATOF( bool, BOOL8_BINFMT ) + +DECLARE_BINARYFORMATOF( uint8, UINT8_BINFMT ) +DECLARE_BINARYFORMATOF( int8, INT8_BINFMT ) +DECLARE_BINARYFORMATOF( uint16, UINT16_BINFMT ) +DECLARE_BINARYFORMATOF( int16, INT16_BINFMT ) +DECLARE_BINARYFORMATOF( uint32, UINT32_BINFMT ) +DECLARE_BINARYFORMATOF( int32, INT32_BINFMT ) +DECLARE_BINARYFORMATOF( uint64, UINT64_BINFMT ) +DECLARE_BINARYFORMATOF( int64, INT64_BINFMT ) + +DECLARE_BINARYFORMATOF( float32, FLOAT32_BINFMT ) +DECLARE_BINARYFORMATOF( float64, FLOAT64_BINFMT ) + +DECLARE_BINARYFORMATOF( Vector2, VECTOR2_BINFMT ) +DECLARE_BINARYFORMATOF( Vector2int16, VECTOR2INT16_BINFMT ) +DECLARE_BINARYFORMATOF( Vector3, VECTOR3_BINFMT ) +DECLARE_BINARYFORMATOF( Vector3int16, VECTOR3INT16_BINFMT ) +DECLARE_BINARYFORMATOF( Vector4, VECTOR4_BINFMT ) +DECLARE_BINARYFORMATOF( Vector4int16, VECTOR4INT16_BINFMT ) + +DECLARE_BINARYFORMATOF( Color3, COLOR3_BINFMT ) +DECLARE_BINARYFORMATOF( Color3uint8, COLOR3UINT8_BINFMT ) +DECLARE_BINARYFORMATOF( Color4, COLOR4_BINFMT ) +DECLARE_BINARYFORMATOF( Color4uint8, COLOR4UINT8_BINFMT ) + +namespace G3D { + +/** Returns -1 if the format is custom, otherwise the byte size + of a single element in this format.*/ +int32 byteSize(BinaryFormat f); + + +} //G3D + +#endif diff --git a/externals/g3dlite/G3D/BinaryInput.h b/externals/g3dlite/G3D/BinaryInput.h new file mode 100644 index 00000000000..1dac93ea55e --- /dev/null +++ b/externals/g3dlite/G3D/BinaryInput.h @@ -0,0 +1,441 @@ +/** + @file BinaryInput.h + + @maintainer Morgan McGuire, graphics3d.com + + @created 2001-08-09 + @edited 2006-07-19 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_BinaryInput_h +#define G3D_BinaryInput_h + +#ifdef _MSC_VER +// Disable conditional expression is constant, which occurs incorrectly on inlined functions +# pragma warning(push) +# pragma warning( disable : 4127 ) +#endif + +#include +#include +#include +#include +#include +#include +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/Color4.h" +#include "G3D/Color3.h" +#include "G3D/Vector4.h" +#include "G3D/Vector3.h" +#include "G3D/Vector2.h" +#include "G3D/g3dmath.h" +#include "G3D/debug.h" +#include "G3D/System.h" + + +namespace G3D { + +#if defined(G3D_WIN32) || defined(G3D_LINUX) + // Allow writing of integers to non-word aligned locations. + // This is legal on x86, but not on other platforms. + #define G3D_ALLOW_UNALIGNED_WRITES +#endif + +/** + Sequential or random access byte-order independent binary file access. + Files compressed with zlib and beginning with an unsigned 32-bit int + size are transparently decompressed when the compressed = true flag is + specified to the constructor. + + For every readX method there are also versions that operate on a whole + Array, std::vector, or C-array. e.g. readFloat32(Array& array, n) + These methods resize the array or std::vector to the appropriate size + before reading. For a C-array, they require the pointer to reference + a memory block at least large enough to hold n elements. + + Most classes define serialize/deserialize methods that use BinaryInput, + BinaryOutput, TextInput, and TextOutput. There are text serializer + functions for primitive types (e.g. int, std::string, float, double) but not + binary serializers-- you must call the BinaryInput::readInt32 or + other appropriate function. This is because it would be very hard to + debug the error sequence: serialize(1.0, bo); ... float f; deserialize(f, bi); + in which a double is serialized and then deserialized as a float. + */ +class BinaryInput { +private: + + // The initial buffer will be no larger than this, but + // may grow if a large memory read occurs. 50 MB + enum {INITIAL_BUFFER_LENGTH = 50000000}; + + /** + is the file big or little endian + */ + G3DEndian m_fileEndian; + std::string m_filename; + + bool m_swapBytes; + + /** Next position to read from in bitString during readBits. */ + int m_bitPos; + + /** Bits currently being read by readBits. + Contains at most 8 (low) bits. Note that + beginBits/readBits actually consumes one extra byte, which + will be restored by writeBits.*/ + uint32 m_bitString; + + /** 1 when between beginBits and endBits, 0 otherwise. */ + int m_beginEndBits; + + /** When operating on huge files, we cannot load the whole file into memory. + This is the file position to which buffer[0] corresponds. + */ + int64 m_alreadyRead; + + /** + Length of the entire file, in bytes. + For the length of the buffer, see bufferLength + */ + int64 m_length; + + /** Length of the array referenced by buffer. May go past the end of the file!*/ + int64 m_bufferLength; + uint8* m_buffer; + + /** + Next byte in file, relative to buffer. + */ + int64 m_pos; + + /** + When true, the buffer is freed in the destructor. + */ + bool m_freeBuffer; + + /** Ensures that we are able to read at least minLength from startPosition (relative + to start of file). */ + void loadIntoMemory(int64 startPosition, int64 minLength = 0); + + /** Verifies that at least this number of bytes can be read.*/ + inline void prepareToRead(int64 nbytes) { + debugAssertM(m_length > 0, m_filename + " not found or corrupt."); + debugAssertM(m_pos + nbytes + m_alreadyRead <= m_length, "Read past end of file."); + + if (m_pos + nbytes > m_bufferLength) { + loadIntoMemory(m_pos + m_alreadyRead, nbytes); + } + } + + // Not implemented on purpose, don't use + BinaryInput(const BinaryInput&); + BinaryInput& operator=(const BinaryInput&); + bool operator==(const BinaryInput&); + + /** Buffer is compressed; replace it with a decompressed version */ + void decompress(); +public: + + /** false, constant to use with the copyMemory option */ + static const bool NO_COPY; + + /** + If the file cannot be opened, a zero length buffer is presented. + Automatically opens files that are inside zipfiles. + + @param compressed Set to true if and only if the file was + compressed using BinaryOutput's zlib compression. This has + nothing to do with whether the input is in a zipfile. + */ + BinaryInput( + const std::string& filename, + G3DEndian fileEndian, + bool compressed = false); + + /** + Creates input stream from an in memory source. + Unless you specify copyMemory = false, the data is copied + from the pointer, so you may deallocate it as soon as the + object is constructed. It is an error to specify copyMemory = false + and compressed = true. + + To decompress part of a file, you can follow the following paradigm: + +
+        BinaryInput master(...);
+
+        // read from master to point where compressed data exists.
+
+        BinaryInput subset(master.getCArray() + master.getPosition(), 
+                           master.length() - master.getPosition(),
+                           master.endian(), true, true);
+
+        // Now read from subset (it is ok for master to go out of scope)
+     
+ */ + BinaryInput( + const uint8* data, + int64 dataLen, + G3DEndian dataEndian, + bool compressed = false, + bool copyMemory = true); + + virtual ~BinaryInput(); + + /** Change the endian-ness of the file. This only changes the + interpretation of the file for future read calls; the + underlying data is unmodified.*/ + void setEndian(G3DEndian endian); + + G3DEndian endian() const { + return m_fileEndian; + } + + std::string getFilename() const { + return m_filename; + } + + /** + Returns a pointer to the internal memory buffer. + May throw an exception for huge files. + */ + const uint8* getCArray() const { + if (m_alreadyRead > 0) { + throw "Cannot getCArray for a huge file"; + } + return m_buffer; + } + + /** + Performs bounds checks in debug mode. [] are relative to + the start of the file, not the current position. + Seeks to the new position before reading (and leaves + that as the current position) + */ + inline uint8 operator[](int64 n) { + setPosition(n); + return readUInt8(); + } + + /** + Returns the length of the file in bytes. + */ + inline int64 getLength() const { + return m_length; + } + + inline int64 size() const { + return getLength(); + } + + /** + Returns the current byte position in the file, + where 0 is the beginning and getLength() - 1 is the end. + */ + inline int64 getPosition() const { + return m_pos + m_alreadyRead; + } + + /** + Sets the position. Cannot set past length. + May throw a char* when seeking backwards more than 10 MB on a huge file. + */ + inline void setPosition(int64 p) { + debugAssertM(p <= m_length, "Read past end of file"); + m_pos = p - m_alreadyRead; + if ((m_pos < 0) || (m_pos > m_bufferLength)) { + loadIntoMemory(m_pos + m_alreadyRead); + } + } + + /** + Goes back to the beginning of the file. + */ + inline void reset() { + setPosition(0); + } + + inline int8 readInt8() { + prepareToRead(1); + return m_buffer[m_pos++]; + } + + inline bool readBool8() { + return (readInt8() != 0); + } + + inline uint8 readUInt8() { + prepareToRead(1); + return ((uint8*)m_buffer)[m_pos++]; + } + + uint16 inline readUInt16() { + prepareToRead(2); + + m_pos += 2; + if (m_swapBytes) { + uint8 out[2]; + out[0] = m_buffer[m_pos - 1]; + out[1] = m_buffer[m_pos - 2]; + return *(uint16*)out; + } else { + #ifdef G3D_ALLOW_UNALIGNED_WRITES + return *(uint16*)(&m_buffer[m_pos - 2]); + #else + uint8 out[2]; + out[0] = m_buffer[m_pos - 2]; + out[1] = m_buffer[m_pos - 1]; + return *(uint16*)out; + #endif + } + + } + + inline int16 readInt16() { + uint16 a = readUInt16(); + return *(int16*)&a; + } + + inline uint32 readUInt32() { + prepareToRead(4); + + m_pos += 4; + if (m_swapBytes) { + uint8 out[4]; + out[0] = m_buffer[m_pos - 1]; + out[1] = m_buffer[m_pos - 2]; + out[2] = m_buffer[m_pos - 3]; + out[3] = m_buffer[m_pos - 4]; + return *(uint32*)out; + } else { + #ifdef G3D_ALLOW_UNALIGNED_WRITES + return *(uint32*)(&m_buffer[m_pos - 4]); + #else + uint8 out[4]; + out[0] = m_buffer[m_pos - 4]; + out[1] = m_buffer[m_pos - 3]; + out[2] = m_buffer[m_pos - 2]; + out[3] = m_buffer[m_pos - 1]; + return *(uint32*)out; + #endif + } + } + + + inline int32 readInt32() { + uint32 a = readUInt32(); + return *(int32*)&a; + } + + uint64 readUInt64(); + + inline int64 readInt64() { + uint64 a = readUInt64(); + return *(int64*)&a; + } + + inline float32 readFloat32() { + union { + uint32 a; + float32 b; + }; + a = readUInt32(); + return b; + } + + inline float64 readFloat64() { + union { + uint64 a; + float64 b; + }; + a = readUInt64(); + return b; + } + + void readBytes(void* bytes, int64 n); + + /** + Reads an n character string. The string is not + required to end in NULL in the file but will + always be a proper std::string when returned. + */ + std::string readString(int64 n); + + /** + Reads until NULL or the end of the file is encountered. + */ + std::string readString(); + + /** + Reads until NULL or the end of the file is encountered. + If the string has odd length (including NULL), reads + another byte. + */ + std::string readStringEven(); + + + std::string readString32(); + + Vector4 readVector4(); + Vector3 readVector3(); + Vector2 readVector2(); + + Color4 readColor4(); + Color3 readColor3(); + + /** + Skips ahead n bytes. + */ + inline void skip(int64 n) { + setPosition(m_pos + m_alreadyRead + n); + } + + /** + Returns true if the position is not at the end of the file + */ + inline bool hasMore() const { + return m_pos + m_alreadyRead < m_length; + } + + /** Prepares for bit reading via readBits. Only readBits can be + called between beginBits and endBits without corrupting the + data stream. */ + void beginBits(); + + /** Can only be called between beginBits and endBits */ + uint32 readBits(int numBits); + + /** Ends bit-reading. */ + void endBits(); + +# define DECLARE_READER(ucase, lcase)\ + void read##ucase(lcase* out, int64 n);\ + void read##ucase(std::vector& out, int64 n);\ + void read##ucase(Array& out, int64 n); + + DECLARE_READER(Bool8, bool) + DECLARE_READER(UInt8, uint8) + DECLARE_READER(Int8, int8) + DECLARE_READER(UInt16, uint16) + DECLARE_READER(Int16, int16) + DECLARE_READER(UInt32, uint32) + DECLARE_READER(Int32, int32) + DECLARE_READER(UInt64, uint64) + DECLARE_READER(Int64, int64) + DECLARE_READER(Float32, float32) + DECLARE_READER(Float64, float64) +# undef DECLARE_READER +}; + + +} + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif diff --git a/externals/g3dlite/G3D/BinaryOutput.h b/externals/g3dlite/G3D/BinaryOutput.h new file mode 100644 index 00000000000..d81ec56a67b --- /dev/null +++ b/externals/g3dlite/G3D/BinaryOutput.h @@ -0,0 +1,421 @@ +/** + @file BinaryOutput.h + + @maintainer Morgan McGuire, graphics3d.com + + @created 2001-08-09 + @edited 2008-01-24 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_BINARYOUTPUT_H +#define G3D_BINARYOUTPUT_H + +#include "G3D/platform.h" +#include +#include +#include +#include +#include +#include "G3D/Color4.h" +#include "G3D/Color3.h" +#include "G3D/Vector4.h" +#include "G3D/Vector3.h" +#include "G3D/Vector2.h" +#include "G3D/g3dmath.h" +#include "G3D/debug.h" +#include "G3D/BinaryInput.h" +#include "G3D/System.h" + +#ifdef _MSC_VER +# pragma warning (push) +// Conditional is constant (wrong in inline) +# pragma warning (disable : 4127) +#endif +namespace G3D { + +/** + Sequential or random access byte-order independent binary file access. + + The compress() call can be used to compress with zlib. + + Any method call can trigger an out of memory error (thrown as char*) + when writing to "" instead of a file. + + Compressed writing and seeking backwards is not supported for huge files + (i.e., BinaryOutput may have to dump the contents to disk if they + exceed available RAM). + */ +class BinaryOutput { +private: + std::string m_filename; + + bool m_committed; + + /** 0 outside of beginBits...endBits, 1 inside */ + int m_beginEndBits; + + /** The current string of bits being built up by beginBits...endBits. + This string is treated semantically, as if the lowest bit was + on the left and the highest was on the right.*/ + int8 m_bitString; + + /** Position (from the lowest bit) currently used in bitString.*/ + int m_bitPos; + + // True if the file endianess does not match the machine endian + bool m_swapBytes; + + G3DEndian m_fileEndian; + + uint8* m_buffer; + + /** Size of the elements used */ + int m_bufferLen; + + /** Underlying size of memory allocaded */ + int m_maxBufferLen; + + /** Next byte in file */ + int m_pos; + + /** is this initialized? */ + bool m_init; + + /** Number of bytes already written to the file.*/ + size_t m_alreadyWritten; + + bool m_ok; + + void reserveBytesWhenOutOfMemory(size_t bytes); + + void reallocBuffer(size_t bytes, size_t oldBufferLen); + + /** + Make sure at least bytes can be written, resizing if + necessary. + */ + inline void reserveBytes(int bytes) { + debugAssert(bytes > 0); + size_t oldBufferLen = (size_t)m_bufferLen; + + m_bufferLen = iMax(m_bufferLen, (m_pos + bytes)); + if (m_bufferLen > m_maxBufferLen) { + reallocBuffer(bytes, oldBufferLen); + } + } + + // Not implemented on purpose, don't use + BinaryOutput(const BinaryOutput&); + BinaryOutput& operator=(const BinaryOutput&); + bool operator==(const BinaryOutput&); + +public: + + /** + You must call setEndian() if you use this (memory) constructor. + */ + BinaryOutput(); + + /** + Doesn't actually open the file; commit() does that. + Use "" as the filename if you're going to commit + to memory. + */ + BinaryOutput( + const std::string& filename, + G3DEndian fileEndian); + + ~BinaryOutput(); + + /** Compresses the data in the buffer in place, + preceeding it with a little-endian uint32 indicating + the uncompressed size. + + Call immediately before commit(). + + Cannot be used for huge files (ones where the data + was already written to disk)-- will throw char*. + */ + void compress(); + + /** True if no errors have been encountered.*/ + bool ok() const; + + /** + Returns a pointer to the internal memory buffer. + */ + inline const uint8* getCArray() const { + return m_buffer; + } + + void setEndian(G3DEndian fileEndian); + + G3DEndian endian() const { + return m_fileEndian; + } + + std::string getFilename() const { + return m_filename; + } + + /** + Write the bytes to disk. It is ok to call this + multiple times; it will just overwrite the previous file. + + Parent directories are created as needed if they do + not exist. + + Not called from the destructor; you must call + it yourself. + + @param flush If true (default) the file is ready for reading when the method returns, otherwise + the method returns immediately and writes the file in the background. + */ + void commit(bool flush = true); + + /** + Write the bytes to memory (which must be of + at least size() bytes). + */ + void commit(uint8*); + + /** + A memory BinaryOutput may be reset so that it can be written to again + without allocating new memory. The underlying array will not be deallocated, + but the reset structure will act like a newly intialized one. + */ + void reset(); + + + inline int length() const { + return (int)m_bufferLen + (int)m_alreadyWritten; + } + + inline int size() const { + return length(); + } + + /** + Sets the length of the file to n, padding + with 0's past the current end. Does not + change the position of the next byte to be + written unless n < size(). + + Throws char* when resetting a huge file to be shorter + than its current length. + */ + inline void setLength(int n) { + n = n - (int)m_alreadyWritten; + + if (n < 0) { + throw "Cannot resize huge files to be shorter."; + } + + if (n < m_bufferLen) { + m_pos = n; + } + if (n > m_bufferLen) { + reserveBytes(n - m_bufferLen); + } + } + + /** + Returns the current byte position in the file, + where 0 is the beginning and getLength() - 1 is the end. + */ + inline int64 position() const { + return (int64)m_pos + (int64)m_alreadyWritten; + } + + + /** + Sets the position. Can set past length, in which case + the file is padded with zeros up to one byte before the + next to be written. + + May throw a char* exception when seeking backwards on a huge file. + */ + inline void setPosition(int64 p) { + p = p - (int64)m_alreadyWritten; + + if (p > m_bufferLen) { + setLength((int)(p + (int64)m_alreadyWritten)); + } + + if (p < 0) { + throw "Cannot seek more than 10 MB backwards on huge files."; + } + + m_pos = (int)p; + } + + + void writeBytes( + const void* b, + int count) { + + reserveBytes(count); + debugAssert(m_pos >= 0); + debugAssert(m_bufferLen >= count); + System::memcpy(m_buffer + m_pos, b, count); + m_pos += count; + } + + /** + Writes a signed 8-bit integer to the current position. + */ + inline void writeInt8(int8 i) { + reserveBytes(1); + m_buffer[m_pos] = *(uint8*)&i; + m_pos++; + } + + inline void writeBool8(bool b) { + writeInt8(b ? 1 : 0); + } + + inline void writeUInt8(uint8 i) { + reserveBytes(1); + m_buffer[m_pos] = i; + m_pos++; + } + + void writeUInt16(uint16 u); + + inline void writeInt16(int16 i) { + writeUInt16(*(uint16*)&i); + } + + void writeUInt32(uint32 u); + + inline void writeInt32(int32 i) { + debugAssert(m_beginEndBits == 0); + writeUInt32(*(uint32*)&i); + } + + void writeUInt64(uint64 u); + + inline void writeInt64(int64 i) { + writeUInt64(*(uint64*)&i); + } + + inline void writeFloat32(float32 f) { + debugAssert(m_beginEndBits == 0); + union { + float32 a; + uint32 b; + }; + a = f; + writeUInt32(b); + } + + inline void writeFloat64(float64 f) { + union { + float64 a; + uint64 b; + }; + a = f; + writeUInt64(b); + } + + /** + Write a string with NULL termination. + */ + inline void writeString(const std::string& s) { + writeString(s.c_str()); + } + + void writeString(const char* s); + + /** + Write a string, ensuring that the total length + including NULL is even. + */ + void writeStringEven(const std::string& s) { + writeStringEven(s.c_str()); + } + + void writeStringEven(const char* s); + + + void writeString32(const char* s); + + /** + Write a string with a 32-bit length field in front + of it. + */ + void writeString32(const std::string& s) { + writeString32(s.c_str()); + } + + void writeVector4(const Vector4& v); + + void writeVector3(const Vector3& v); + + void writeVector2(const Vector2& v); + + void writeColor4(const Color4& v); + + void writeColor3(const Color3& v); + + /** + Skips ahead n bytes. + */ + inline void skip(int n) { + if (m_pos + n > m_bufferLen) { + setLength((int)m_pos + (int)m_alreadyWritten + n); + } + m_pos += n; + } + + /** Call before a series of BinaryOutput::writeBits calls. Only writeBits + can be called between beginBits and endBits without corrupting the stream.*/ + void beginBits(); + + /** Write numBits from bitString to the output stream. Bits are numbered from + low to high. + + Can only be + called between beginBits and endBits. Bits written are semantically + little-endian, regardless of the actual endian-ness of the system. That is, + writeBits(0xABCD, 16) writes 0xCD to the first byte and + 0xAB to the second byte. However, if used with BinaryInput::readBits, the ordering + is transparent to the caller. + */ + void writeBits(uint32 bitString, int numBits); + + /** Call after a series of BinaryOutput::writeBits calls. This will + finish out with zeros the last byte into which bits were written.*/ + void endBits(); + + +# define DECLARE_WRITER(ucase, lcase)\ + void write##ucase(const lcase* out, int n);\ + void write##ucase(const std::vector& out, int n);\ + void write##ucase(const Array& out, int n); + + DECLARE_WRITER(Bool8, bool) + DECLARE_WRITER(UInt8, uint8) + DECLARE_WRITER(Int8, int8) + DECLARE_WRITER(UInt16, uint16) + DECLARE_WRITER(Int16, int16) + DECLARE_WRITER(UInt32, uint32) + DECLARE_WRITER(Int32, int32) + DECLARE_WRITER(UInt64, uint64) + DECLARE_WRITER(Int64, int64) + DECLARE_WRITER(Float32, float32) + DECLARE_WRITER(Float64, float64) +# undef DECLARE_WRITER + +}; + +} + +#ifdef _MSC_VER +# pragma warning (pop) +#endif + +#endif diff --git a/externals/g3dlite/G3D/BoundsTrait.h b/externals/g3dlite/G3D/BoundsTrait.h new file mode 100644 index 00000000000..15e1418010c --- /dev/null +++ b/externals/g3dlite/G3D/BoundsTrait.h @@ -0,0 +1,20 @@ +/** + @file BoundsTrait.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @created 2008-10-01 + @edited 2008-10-01 + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_BOUNDSTRAIT_H +#define G3D_BOUNDSTRAIT_H + +#include "G3D/platform.h" + +template +struct BoundsTrait{}; + +#endif + diff --git a/externals/g3dlite/G3D/Box.h b/externals/g3dlite/G3D/Box.h new file mode 100644 index 00000000000..82af9125b05 --- /dev/null +++ b/externals/g3dlite/G3D/Box.h @@ -0,0 +1,195 @@ +/** + @file Box.h + + Box class + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com + @created 2001-06-02 + @edited 2007-06-05 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_BOX_H +#define G3D_BOX_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Array.h" +#include "G3D/Plane.h" + +namespace G3D { + +class CoordinateFrame; + +/** + An arbitrary 3D box, useful as a bounding box. + + + To construct a box from a coordinate frame, center and extent, use the idiom: + + Box box = cframe.toObjectSpace(Box(center - extent/2, center + extent/2)); + */ +class Box { +private: + + static int32 dummy; + + friend class CoordinateFrame; + + /** +
+       3    2       7    6
+    
+       0    1       4    5
+
+       front    back (seen through front)
+      
+ */ + Vector3 _corner[8]; + + /** + Unit axes. + */ + Vector3 _axis[3]; + + Vector3 _center; + + /** + Extent along each axis. + */ + Vector3 _extent; + + float _area; + float _volume; + + void init( + const Vector3& min, + const Vector3& max); + +public: + + /** + Does not initialize the fields. + */ + Box(); + + /** + Constructs a box from two opposite corners. + */ + Box( + const Vector3& min, + const Vector3& max); + + static Box inf(); + + Box(class BinaryInput& b); + + Box(const class AABox& b); + + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + + /** + Returns the object to world transformation for + this box. localFrame().worldToObject(...) takes + objects into the space where the box axes are + (1,0,0), (0,1,0), (0,0,1). Note that there + is no scaling in this transformation. + */ + CoordinateFrame localFrame() const; + + void getLocalFrame(CoordinateFrame& frame) const; + + /** + Returns the centroid of the box. + */ + inline Vector3 center() const { + return _center; + } + + + inline Vector3 corner(int i) const { + debugAssert(i < 8); + return _corner[i]; + } + + /** + Unit length. + */ + inline Vector3 axis(int a) const { + debugAssert(a < 3); + return _axis[a]; + } + + /** + Distance from corner(0) to the next corner + along the box's local axis a. + */ + inline float extent(int a) const { + debugAssert(a < 3); + return (float)_extent[a]; + } + + inline Vector3 extent() const { + return _extent; + } + + /** + Returns the four corners of a face (0 <= f < 6). + The corners are returned to form a counter clockwise quad facing outwards. + */ + void getFaceCorners( + int f, + Vector3& v0, + Vector3& v1, + Vector3& v2, + Vector3& v3) const; + + + /** + See AABox::culledBy + */ + bool culledBy + ( + const Array& plane, + int32& cullingPlaneIndex, + const uint32 testMask, + uint32& childMask) const; + + /** + Conservative culling test that does not produce a mask for children. + */ + bool culledBy + ( + const Array& plane, + int32& cullingPlaneIndex = dummy, + const uint32 testMask = -1) const; + + bool contains( + const Vector3& point) const; + + float area() const; + + float volume() const; + + void getRandomSurfacePoint(Vector3& P, Vector3& N = Vector3::ignore()) const; + + /** + Uniformly distributed on the interior (includes surface) + */ + Vector3 randomInteriorPoint() const; + + void getBounds(class AABox&) const; + + bool isFinite() const { + return G3D::isFinite(_volume); + } +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/Box2D.h b/externals/g3dlite/G3D/Box2D.h new file mode 100644 index 00000000000..80accad89dd --- /dev/null +++ b/externals/g3dlite/G3D/Box2D.h @@ -0,0 +1,121 @@ +/** + @file Box2D.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2001-06-02 + @edited 2008-12-27 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_Box2D_h +#define G3D_Box2D_h + +#include "G3D/platform.h" +#include "G3D/Vector2.h" + +namespace G3D { + +class CoordinateFrame; +typedef class CoordinateFrame CFrame; +class Rect2D; +typedef class Rect2D AABox2D; + +/** + 2D oriented box + @cite http://www.flipcode.com/archives/2D_OBB_Intersection.shtml + */ +class Box2D { +private: + /** Corners of the box, where 0 is the lower left. */ + Vector2 m_corner[4]; + + /** Two edges of the box extended away from corner[0], with length + = 1 / extentSquared */ + Vector2 m_axisin[2]; + + /** Two edges of the box extended away from corner[0], with unit length */ + Vector2 m_axis[2]; + + /** Centroid of the box */ + Vector2 m_center; + + /** origin[a] = m_corner[0].dot(m_axisin[a]); */ + float origin[2]; + + /** Surface area */ + float m_area; + + Vector2 m_extent; + + /** Returns true if other overlaps one dimension of this. */ + bool overlaps1Way(const Box2D& other) const; + + + /** Updates the axes after the m_corners move. Assumes the + m_corners actually form a rectangle. */ + void computeAxes(); + +public: + + /** + @param center World-space center + @param w Width along object-space x-axis + @param h Height along object-space y-axis + @param angle Counter-clockwise angle from object-space x-axis in radians + */ + Box2D(const Vector2& center = Vector2(0, 0), float w = 0, float h = 0, float angle = 0); + + Box2D(const AABox2D& b); + + Box2D(const Vector2& min, const Vector2& max); + + /** Transform @a b by @a frame, discarding the Z components, and + compute the new box.*/ + Box2D(const CFrame& frame, Box2D& b); + + inline bool contains(const Vector2& v) const { + // Take to object space: + const Vector2& p = v - m_center; + float x = p.dot(m_axisin[0]); + float y = p.dot(m_axisin[1]); + + // Must be within extent/2 on both axes in object space + return (abs(x) <= 0.5f) && (abs(y) <= 0.5f); + } + + /** @brief Distance from corner(0) to the next corner along the box's local axis a. */ + inline const Vector2& extent() const { + return m_extent; + } + + /** @brief Unit length vector along axis @a a */ + inline const Vector2& axis(int a) const { + debugAssert(a == 0 || a == 1); + return m_axis[a]; + } + + /** @brief Surface area */ + inline float area() const { + return m_area; + } + + inline const Vector2& corner(int i) const { + debugAssert(i >=0 && i <= 3); + return m_corner[i]; + } + + inline const Vector2& center() const { + return m_center; + } + + /** Returns true if the intersection of the boxes is non-empty. */ + inline bool overlaps(const Box2D& other) const { + return overlaps1Way(other) && other.overlaps1Way(*this); + } +}; + +} // G3D +#endif diff --git a/externals/g3dlite/G3D/BumpMapPreprocess.h b/externals/g3dlite/G3D/BumpMapPreprocess.h new file mode 100644 index 00000000000..955f99e61b2 --- /dev/null +++ b/externals/g3dlite/G3D/BumpMapPreprocess.h @@ -0,0 +1,61 @@ +/** + \file BumpMapPreprocess.h + + \maintainer Morgan McGuire, http://graphics.cs.williams.edu + + \created 2010-01-28 + \edited 2010-01-28 + + Copyright 2000-2010, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_BumpMapPreprocess_h +#define G3D_BumpMapPreprocess_h + +#include "G3D/platform.h" + +namespace G3D { +class Any; + +/** +Not in the BumpMap class to avoid a circular dependency between Texture and BumpMap. +G3D::GImage::computeNormalMap(). +*/ +class BumpMapPreprocess { +public: + + /** If true, the elevations are box filtered after computing normals + and before uploading, which produces better results for parallax offset mapping + Defaults to false. */ + bool lowPassFilter; + + /** Height of the maximum ("white") value, in pixels, for the purpose of computing normals. + A value of 255 means that a 255 x 255 bump image with a full black-to-white gradient + will produce a 45-degree ramp (this also results in "cubic" voxels). + A negative value means to set zExtentPixels to -zExtentPixels * max(width, height). + The default is -0.02. + */ + float zExtentPixels; + + /** After computing normals, scale the height by |N.z|, a trick that reduces texture swim in steep areas for parallax offset + mapping. Defaults to false.*/ + bool scaleZByNz; + + BumpMapPreprocess() : lowPassFilter(false), zExtentPixels(-0.02f), scaleZByNz(false) {} + + BumpMapPreprocess(const Any& any); + + operator Any() const; + + bool operator==(const BumpMapPreprocess& other) const { + return + (lowPassFilter == other.lowPassFilter) && + (zExtentPixels == other.zExtentPixels) && + (scaleZByNz == other.scaleZByNz); + } +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/Capsule.h b/externals/g3dlite/G3D/Capsule.h new file mode 100644 index 00000000000..baeea3aa82b --- /dev/null +++ b/externals/g3dlite/G3D/Capsule.h @@ -0,0 +1,90 @@ +/** + @file Capsule.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2003-02-07 + @edited 2005-08-20 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_CAPSULE_H +#define G3D_CAPSULE_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Vector3.h" + +namespace G3D { + +class Line; +class AABox; +/** + A shape formed by extruding a sphere along a line segment. + */ +class Capsule { +private: + Vector3 p1; + Vector3 p2; + + float _radius; +public: + + + /** Uninitialized */ + Capsule(); + Capsule(class BinaryInput& b); + Capsule(const Vector3& _p1, const Vector3& _p2, float _r); + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + + /** The line down the center of the capsule */ + Line axis() const; + + inline float radius() const { + return _radius; + } + + /** Argument may be 0 or 1 */ + inline Vector3 point(int i) const { + debugAssert(i == 0 || i == 1); + return (i == 0) ? p1 : p2; + } + + /** Distance between the sphere centers. The total extent of the cylinder is + 2r + h. */ + inline float height() const { + return (p1 - p2).magnitude(); + } + + inline Vector3 center() const { + return (p1 + p2) / 2.0; + } + + /** Get a reference frame in which the center of mass is the origin and Y is the axis of the capsule.*/ + void getReferenceFrame(class CoordinateFrame& cframe) const; + + /** + Returns true if the point is inside the capsule or on its surface. + */ + bool contains(const Vector3& p) const; + + float volume() const; + + float area() const; + + /** Get axis aligned bounding box */ + void getBounds(AABox& out) const; + + /** Random world space point with outward facing normal. */ + void getRandomSurfacePoint(Vector3& P, Vector3& N) const; + + /** Point selected uniformly at random over the volume. */ + Vector3 randomInteriorPoint() const; +}; + +} // namespace + +#endif diff --git a/externals/g3dlite/G3D/CollisionDetection.h b/externals/g3dlite/G3D/CollisionDetection.h new file mode 100644 index 00000000000..c8fcf5534c2 --- /dev/null +++ b/externals/g3dlite/G3D/CollisionDetection.h @@ -0,0 +1,1205 @@ +/** + @file CollisionDetection.h + + + Moving collision detection for simple primitives. + + @author Morgan McGuire, http://graphics.cs.williams.edu + @cite Spherical collision based on Paul Nettle's + ftp://ftp.3dmaileffects.com/pub/FluidStudios/CollisionDetection/Fluid_Studios_Generic_Collision_Detection_for_Games_Using_Ellipsoids.pdf + and comments by Max McGuire. Ray-sphere intersection by Eric Haines. + Box-Box intersection written by Kevin Egan. + Thanks to Max McGuire of Iron Lore for various bug fixes. + Box-Triangle by Tomas Akenine-Moller + + @created 2001-11-19 + @edited 2008-12-19 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_COLLISIONDETECTION_H +#define G3D_COLLISIONDETECTION_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Plane.h" +#include "G3D/Box.h" +#include "G3D/Triangle.h" +#include "G3D/Array.h" +#include "G3D/Ray.h" +#include "G3D/Line.h" + +namespace G3D { + + +/** + Collision detection primitives and tools for building + higher order collision detection schemes. + + These routines provide moving and static collision detection. + Moving collision detection allows the calculation of collisions that + occur during a period of time -- as opposed to the intersection of + two static bodies. + + Moving collision detection routines detect collisions between + only static primitives and moving spheres or points. Since the + reference frame can be user defined, these functions can be used to + detect the collision between two moving bodies by subtracting + the velocity vector of one object from the velocity vector of the + sphere or point the detection is to occur with. This unified + velocity vector will act as if both objects are moving simultaneously. + + Collisions are detected for single-sided objects only. That is, + no collision is detected when leaving a primitive or passing + through a plane or triangle opposite the normal... except for the + point-sphere calculation or when otherwise noted. + + For a sphere, the collision location returned is the point in world + space where the surface of the sphere and the fixed object meet. + It is not the position of the center of the sphere at + the time of the collision. + + The collision normal returned is the surface normal to the fixed + object at the collision location. + +

+ Static Collision Detection: (Neither object is moving) + + + + + + + + + + + + + + +
Vector3LineSegmentRay *LinePlaneTriangleSphereCylinderCapsuleAABoxBox
Vector3\link Vector3::operator== V3::==\endlink \link Vector3::fuzzyEq V3::fuzzy \endlink \link G3D::distance distance \endlink
LineSegment\link LineSegment::closestPoint LS::closestPoint\endlink \link LineSegment::distance LS::distance\endlink \link CollisionDetection::closestPointOnLineSegment CD\endlink
Ray *Ray::closestPoint Ray::distance
LineLine::closestPoint Line::distance\link CollisionDetection::closestPointsBetweenLineAndLine CD\endlink
Plane
Triangle
SphereSphere::contains\link CollisionDetection::collisionTimeForMovingPointFixedSphere CD \endlink, \link Ray::intersectionTime R::time\endlink
CylinderCylinder::contains
CapsuleCapsule::contains
AABoxAABox::contains\link CollisionDetection::fixedSolidBoxIntersectsFixedTriangle CD\endlink
BoxBox::contains(treat as Ray)\link CollisionDetection::collisionTimeForMovingPointFixedBox CD\endlink(treat as Ray)\link CollisionDetection::penetrationDepthForFixedBoxFixedPlane CD \endlink\link CollisionDetection::penetrationDepthForFixedBoxFixedPlane CD\endlink\link CollisionDetection::penetrationDepthForFixedSphereFixedBox CD\endlinkNone (use OPCODE)\link CollisionDetection::movingSpherePassesThroughFixedBox CD \endlink\link CollisionDetection::penetrationDepthForFixedBoxFixedBox CD\endlink\link CollisionDetection::penetrationDepthForFixedBoxFixedBox CD\endlink
+ +

+ Moving Collision Detection: + + * Note: Moving collision detection against certain primitives is equivalent to static collision + detection against a bigger primitive. Ray, Line Segment == ``moving Point''; Capsule ==``moving Sphere''; Plane == ``moving Line'' + + @deprecated Routines moving to the G3D::Intersect class in G3D 8.0 + */ +class CollisionDetection { +private: + + /** + Default parameter if value passed to a function as reference is + not to be calculated. Must be explicitly supported by function. + */ + static Vector3 ignore; + + /** + Default parameter if value passed to a function as reference is + not to be calculated. Must be explicitly supported by function. + */ + static bool ignoreBool; + + /** + Default parameter if value passed to a function as reference is + not to be calculated. Must be explicitly supported by function. + */ + static Array ignoreArray; + + + // Static class! + CollisionDetection() {} + virtual ~CollisionDetection() {} + +public: + + /** + Converts an index [0, 15] to the corresponding separating axis. + Does not return normalized vector in the edge-edge case + (indices 6 through 15). + + @param separatingAxisIndex Separating axis. + @param box1 Box 1. + @param box2 Box 2. + + @return Axis that separates the two boxes. + */ + static Vector3 separatingAxisForSolidBoxSolidBox( + const int separatingAxisIndex, + const Box & box1, + const Box & box2); + + /** + Tests whether two boxes have axes that are parallel to + each other. If they are, axis1 and axis2 are set to be + the parallel axes for both box1 and box2 respectively. + + @param ca Dot products of each of the boxes axes + @param epsilon Fudge factor (small unit by which the dot + products may vary and still be considered + zero). + @param axis1 Parallel Axis 1. [Post Condition] + @param axis2 Parallel Axis 2. [Post Condition] + + @return true - If boxes have a parallel axis + @return false - otherwise. + */ + static bool parallelAxisForSolidBoxSolidBox( + const double* ca, + const double epsilon, + int & axis1, + int & axis2); + + /** + Calculates the projected distance between the two boxes along + the specified separating axis, negative distances correspond + to an overlap along that separating axis. The distance is not + divided by denominator dot(L, L), see + penetrationDepthForFixedSphereFixedBox() for more details + + @param separatingAxisIndex + @param a Box 1's bounding sphere vector + @param b Box 2's bounding sphere vector + @param D Vector between Box 1 and Box 2's center points + @param c Pointer to array of dot products of the axes of Box 1 + and Box 2. + @param ca Pointer to array of unsigned dot products of the axes + of Box 1 and Box 2. + @param ad Pointer to array of dot products of Box 1 axes and D. + @param bd Pointer to array of dot products of Box 2 axes and D. + + @return Projected distance between the two boxes along the + specified separating axis. + */ + static float projectedDistanceForSolidBoxSolidBox( + const int separatingAxisIndex, + const Vector3 & a, + const Vector3 & b, + const Vector3 & D, + const double* c, + const double* ca, + const double* ad, + const double* bd); + + + /** + Creates a set of standard information about two boxes in order to + solve for their collision. This information includes a vector to + the radius of the bounding sphere for each box, the vector between + each boxes' center and a series of dot products between differing + important vectors. These dot products include those between the axes + of both boxes (signed and unsigned values), and the dot products + between all the axes of box1 and the boxes' center vector and box2 + and the boxes' center vector. + + @pre The following space requirements must be met: + - c[] 9 elements + - ca[] 9 elements + - ad[] 3 elements + - bd[] 3 elements + + @cite dobted from David Eberly's papers, variables used in this function + correspond to variables used in pages 6 and 7 in the pdf + http://www.magic-software.com/Intersection.html + http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf + + @note Links are out-dated. (Kept to preserve origin and authorship) + + @param box1 Box 1 + @param box2 Box 2 + @param a Box 1's bounding sphere vector + @param b Box 2's bounding sphere vector + @param D Vector between Box 1 and Box 2's center points + @param c Pointer to array of dot products of the axes of Box 1 + and Box 2. + @param ca Pointer to array of unsigned dot products of the axes + of Box 1 and Box 2. + @param ad Pointer to array of dot products of Box 1 axes and D. + @param bd Pointer to array of dot products of Box 2 axes and D. + */ + static void fillSolidBoxSolidBoxInfo( + const Box & box1, + const Box & box2, + Vector3 & a, + Vector3 & b, + Vector3 & D, + double* c, + double* ca, + double* ad, + double* bd); + + /** + Performs a simple bounding sphere check between two boxes to determine + whether these boxes could possibly intersect. This is a very + cheap operation (three dot products, two sqrts and a few others). If + it returns true, an intersection is possible, but not necessarily + guaranteed. + + @param a Vector from box A's center to an outer vertex + @param b Vector from box B's center to an outer vertex + @param D Distance between the centers of the two boxes + + @return true - if possible intersection + @return false - otherwise (This does not guarantee an intersection) + */ + static bool conservativeBoxBoxTest( + const Vector3 & a, + const Vector3 & b, + const Vector3 & D); + + /** + Determines whether two fixed solid boxes intersect. + + @note To speed up collision detection, the lastSeparatingAxis from + the previous time step can be passed in and that plane can be + checked first. If the separating axis was not saved, or if the + two boxes intersected then lastSeparatingAxis should equal -1. + + @cite Adobted from David Eberly's papers, variables used in this function + correspond to variables used in pages 6 and 7 in the pdf + http://www.magic-software.com/Intersection.html + http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf + + @param box1 Box 1. + @param box2 Box 2. + @param lastSeparatingAxis Last separating axis. + (optimization - see note) + + @return true - Intersection. + @return false - otherwise. + */ + static bool fixedSolidBoxIntersectsFixedSolidBox( + const Box& box1, + const Box& box2, + const int lastSeparatingAxis = -1); + + /** + Calculates the closest points on two lines with each other. If the + lines are parallel then using the starting point, else calculate the + closest point on each line to the other. + + @note This is very similiar to calculating the intersection of two lines. + Logically then, the two points calculated would be identical if calculated + with inifinite precision, but with the finite precision of floating point + calculations, these values could (will) differ as the line slope approaches + zero or inifinity. + + @cite variables and algorithm based on derivation at the following website: + http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm + + @param line1 Line 1. + @param line2 Line 2. + @param closest1 Closest point on line 1. + @param closest2 Closest point on line 2. + */ + static void closestPointsBetweenLineAndLine( + const Line & line1, + const Line & line2, + Vector3 & closest1, + Vector3 & closest2); + + /** + Calculates the depth of penetration between two fixed boxes. + Contact normal faces away from box1 and into box2. If there is + contact, only one contact point is returned. The minimally + violated separating plane is computed + - if the separating axis corresponds to a face + the contact point is half way between the deepest vertex + and the face + - if the separating axis corresponds to two edges + the contact point is the midpoint of the smallest line + segment between the two edge lines + + @note This is very similiar to calculating the intersection of two lines. + Logically then, the two points calculated would be identical if calculated + with inifinite precision, but with the finite precision of floating point + calculations, these values could (will) differ as the line slope approaches + zero or inifinity. + + @cite adobted from David Eberly's papers, variables used in this function + correspond to variables used in pages 6 and 7 in the pdf + http://www.magic-software.com/Intersection.html + http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf + + @param box1 Box 1 + @param box2 Box 2 + @param contactPoints Contact point between boxes. [Post Condition] + @param contactNormals Surface normal at contact point. [Post Condition] + @param lastSeparatingAxis Last separating axis. (Used for optimization) + + @return Depth of penetration between the two boxes. If there is no + intersection between the boxes, then a negative value is returned. + */ + static float penetrationDepthForFixedBoxFixedBox( + const Box& box1, + const Box& box2, + Array& contactPoints, + Array& contactNormals, + const int lastSeparatingAxis = -1); + + /** + Calculates the depth of penetration between two fixed spheres as well + as the deepest point of Sphere A that penetrates Sphere B. The normal + returned points away from the object A, although it may + represent a perpendicular to either the faces of object B or object A + depending on their relative orientations. + + @param sphereA Fixed Sphere A. + @param sphereB Fixed Sphere B. + @param contactPoints Sphere A's deepest point that penetrates Sphere B. + [Post Condition] + @param contactNormals Normal at penetration point. [Post Condition] + + @return Depth of penetration. If there is no intersection between the + objects then the depth will be a negative value. + */ + static float penetrationDepthForFixedSphereFixedSphere( + const class Sphere& sphereA, + const Sphere& sphereB, + Array& contactPoints, + Array& contactNormals = ignoreArray); + + /** + Calculates the depth of penetration between a fixed sphere and a fixed + box as well as the deepest point of the sphere that penetrates the box + and the normal at that intersection. + + @note There are three possible intersections between a sphere and box. + - Sphere completely contained in the box + - Sphere intersects one edge + - Sphere intersects one vertex + + The contact point and contact normal vary for each of these situations. + - Sphere contained in Box: + - Normal is based on side of least penetration (as is the depth calculation). + - Point is based on center of sphere + - Sphere intersects one edge + - Normal is based on vector from the box center to the point of depth. + - Point is closest point to the sphere on the line + - Sphere intersects one vertex + - Normal is based on vector from the box center to the vertex of penetration. + - Point is vertex of penetration. + + @cite Adapted from Jim Arvo's method in Graphics Gems + See also http://www.win.tue.nl/~gino/solid/gdc2001depth.pdf + + @param sphere Fixed Sphere. + @param box Fixed Box. + @param contactPoints Sphere point that penetrates the box. [Post Condition] + @param contactNormals Normal at the penetration point. [Post Condition] + + @return Depth of penetration. If there is no intersection between the + objects then the depth will be a negative value. + */ + static float penetrationDepthForFixedSphereFixedBox( + const Sphere& sphere, + const Box& box, + Array& contactPoints, + Array& contactNormals = ignoreArray); + + /** + Calculates the depth of penetration between a Fixed Sphere and a Fixed + Plane as well as the deepest point of the sphere that penetrates the plane + and the plane normal at that intersection. + + @param sphereA Fixed Sphere. + @param planeB Fixed Plane. + @param contactPoints Sphere point that penetrates the plane. + [Post Condition] + @param contactNormals Normal at penetration point. [Post Condition] + + @return Depth of penetration. If there is no intersection between the + objects then the depth will be a negative value. + */ + static float penetrationDepthForFixedSphereFixedPlane( + const Sphere& sphereA, + const class Plane& planeB, + Array& contactPoints, + Array& contactNormals = ignoreArray); + + /** + Calculates the depth of penetration between a fixed box and a fixed + plane as well as the vertexes of the box that penetrate the plane + and the plane normals at those intersections. + + @param box Fixed Box. + @param plane Fixed Plane. + @param contactPoints Box points that penetrate the plane. + [Post Condition] + @param contactNormals Normals at penetration points [Post Condition] + + @return Depth of penetration. If there is no intersection between the + objects then the depth will be a negative value. + */ + static float penetrationDepthForFixedBoxFixedPlane( + const Box& box, + const Plane& plane, + Array& contactPoints, + Array& contactNormals = ignoreArray); + + /** + Calculates time between the intersection of a moving point and a fixed + plane. + + @note This is only a one sided collision test. The side defined by + the plane's surface normal is the only one tested. For a two sided + collision, call the function once for each side's surface normal. + + @param point Moving point. + @param velocity Point's velocity. + @param plane Fixed plane. + @param location Location of collision. [Post Condition] + (Infinite vector on no collision) + @param outNormal Plane's surface normal. [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingPointFixedPlane( + const Vector3& point, + const Vector3& velocity, + const class Plane& plane, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving point and a fixed + triangle. + + @note This is only a one sided collision test. The side defined by + the triangle's surface normal is the only one tested. For a two sided + collision, call the function once for each side's surface normal. + + @param orig Moving point. + @param dir Point's velocity. + @param v0 Triangle vertex 1. + @param v1 Triangle vertex 2. + @param v2 Triangle vertex 3 + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + inline static float collisionTimeForMovingPointFixedTriangle( + const Vector3& orig, + const Vector3& dir, + const Vector3& v0, + const Vector3& v1, + const Vector3& v2) { + return Ray::fromOriginAndDirection(orig, dir).intersectionTime(v0, v1, v2); + } + + /** + Calculates time between the intersection of a moving point and a fixed + triangle. + + @note This is only a one sided collision test. The side defined by + the triangle's surface normal is the only one tested. For a two sided + collision, call the function once for each side's surface normal. + + @param orig Moving point. + @param dir Point's velocity. + @param v0 Triangle vertex 1. + @param v1 Triangle vertex 2. + @param v2 Triangle vertex 3 + @param location Location of collision. [Post Condition] + (Infinite vector on no collision) + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + inline static float collisionTimeForMovingPointFixedTriangle( + const Vector3& orig, + const Vector3& dir, + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + Vector3& location) { + float t = collisionTimeForMovingPointFixedTriangle(orig, dir, v0, v1, v2); + if (t < finf()) { + location = orig + dir * t; + } + return t; + } + + /** + Calculates time between the intersection of a moving point and a fixed + triangle. + + @note This is only a one sided collision test. The side defined by + the triangle's surface normal is the only one tested. For a two sided + collision, call the function once for each side's surface normal. + + @param orig Moving point. + @param dir Point's velocity. + @param tri Fixed triangle. + @param location Location of collision. [Post Condition] + (Infinite vector on no collision) + @param normal Triangle's surface normal. [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + inline static float collisionTimeForMovingPointFixedTriangle( + const Vector3& orig, + const Vector3& dir, + const Triangle& tri, + Vector3& location = ignore, + Vector3& normal = ignore) { + + float t = collisionTimeForMovingPointFixedTriangle( + orig, dir, tri.vertex(0), tri.vertex(1), tri.vertex(2)); + + if ((t < finf()) && (&location != &ignore)) { + location = orig + dir * t; + normal = tri.normal(); + } + return t; + } + + /** + Calculates time between the intersection of a moving point and a fixed + triangle. + + @note This is only a one sided collision test. The side defined by + the triangle's surface normal is the only one tested. For a two sided + collision, call the function once for each side's surface normal. + + @param orig Moving point. + @param dir Point's velocity. + @param v0 Triangle vertex 1. + @param v1 Triangle vertex 2. + @param v2 Triangle vertex 3 + @param location Location of collision. [Post Condition] + (Infinite vector on no collision) + @param normal Triangle's surface normal. [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + inline static float collisionTimeForMovingPointFixedTriangle( + const Vector3& orig, + const Vector3& dir, + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + Vector3& location, + Vector3& normal) { + float t = collisionTimeForMovingPointFixedTriangle(orig, dir, v0, v1, v2); + if (t < finf()) { + location = orig + dir * t; + normal = (v1 - v0).cross(v2 - v0).direction(); + } + return t; + } + + /** + If the ray origin is inside the box, returns inf() but inside + is set to true. + Beta API + + @cite Andrew Woo, from "Graphics Gems", Academic Press, 1990 + @cite Optimized code by Pierre Terdiman, 2000 (~20-30% faster on Celeron 500) + @cite Epsilon value added by Klaus Hartmann + @cite http://www.codercorner.com/RayAABB.cpp + */ + static float collisionTimeForMovingPointFixedAABox( + const Vector3& point, + const Vector3& velocity, + const class AABox& box, + Vector3& outLocation, + bool& inside = ignoreBool, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving point and a fixed + Axis-Aligned Box (AABox). + + @note Avoids the sqrt from collisionTimeForMovingPointFixedAABox. + + @param point Moving point. + @param velocity Sphere's velocity. + @param box Fixed AAbox. + @param location Location of collision. [Post Condition] + @param Inside Does the ray originate inside the box? [Post Condition] + @param normal Box's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static bool collisionLocationForMovingPointFixedAABox( + const Vector3& point, + const Vector3& velocity, + const class AABox& box, + Vector3& outLocation, + bool& inside = ignoreBool, + Vector3& normal = ignore); + + + /** + @brief Calculates intersection of a ray and a static + Axis-Aligned Box (AABox). + + @note Avoids the sqrt from collisionTimeForMovingPointFixedAABox; + early-out branches and operations optimized for Intel Core2 architecture. + + @param invDir 1/dir + @param location Location of collision. [Post Condition] + @param inside Does the ray originate inside the box? [Post Condition] + + @return True if the ray hits the box + */ + static bool __fastcall rayAABox( + const Ray& ray, + const Vector3& invDir, + const AABox& box, + const Vector3& boxCenter, + float boundingRadiusSquared, + Vector3& location, + bool& inside); + + /** + Calculates time between the intersection of a moving point and a fixed + sphere. + + @note When ray is starts inside the rectangle, the exiting intersection + is detected. + + @param point Moving point. + @param velocity Point's velocity. + @param sphere Fixed Sphere. + @param outLocation Location of collision. [Post Condition] + @param outNormal Sphere's surface normal to collision [Post Condition] + \param solid If true, rays inside the sphere immediately intersect (good for collision detection). If false, they hit the opposite side of the sphere (good for ray tracing). + + @return Time until collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingPointFixedSphere( + const Vector3& point, + const Vector3& velocity, + const class Sphere& sphere, + Vector3& outLocation, + Vector3& outNormal = ignore, + bool solid = false); + + /** + Calculates time between the intersection of a moving point and a fixed + box. + + @note If the point is already inside the box, no collision: inf is returned. + + @param point Moving point. + @param velocity Sphere's velocity. + @param box Fixed box. + @param location Position of collision. [Post Condition] + @param outNormal Box's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingPointFixedBox( + const Vector3& point, + const Vector3& velocity, + const class Box& box, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving point and a fixed + rectangle defined by the points v0, v1, v2, & v3. + + @note This is only a one sided collision test. The side defined by + the rectangle's surface normal is the only one tested. For a two sided + collision, call the function once for each side's surface normal. + + @param point Moving point. + @param velocity Sphere's velocity. + @param v0 Rectangle vertex 1. + @param v1 Rectangle vertex 2. + @param v2 Rectangle vertex 3 + @param v3 Rectangle vertex 4. + @param location Location of collision [Post Condition] + @param outNormal Rectangle's surface normal. [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingPointFixedRectangle( + const Vector3& point, + const Vector3& velocity, + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& v3, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving point and a fixed + capsule. + + @param point Moving point. + @param velocity Point's velocity. + @param capsule Fixed capsule. + @param outLocation Location of collision. [Post Condition] + @param outNormal Capsule's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingPointFixedCapsule( + const Vector3& point, + const Vector3& velocity, + const class Capsule& capsule, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving sphere and a fixed + triangle. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param plane Fixed Plane. + @param outLocation Location of collision -- not center position of sphere + at the collision time. [Post Condition] + @param outNormal Box's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingSphereFixedPlane( + const class Sphere& sphere, + const Vector3& velocity, + const class Plane& plane, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving sphere and a fixed + triangle. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param triangle Fixed Triangle. (collisions can happen on the back side of the triangle) + @param outLocation Location of collision, if collision occurs -- not center position of sphere + at the collision time. If there is interpenetration at the start, this point may be inside + the sphere. + @param b Barycentric coordinates. These are not valid unless collision occurs. + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingSphereFixedTriangle( + const class Sphere& sphere, + const Vector3& velocity, + const Triangle& triangle, + Vector3& outLocation, + float b[3] = (float*)&ignore); + + /** + Calculates time between the intersection of a moving sphere and a fixed + rectangle defined by the points v0, v1, v2, & v3. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param v0 Rectangle vertex 1. + @param v1 Rectangle vertex 2. + @param v2 Rectangle vertex 3 + @param v3 Rectangle vertex 4. + @param outLocation Location of collision -- not center position of sphere + at the collision time. [Post Condition] + @param outNormal Box's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingSphereFixedRectangle( + const class Sphere& sphere, + const Vector3& velocity, + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& v3, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving sphere and a fixed + box. + + @note This function will not detect an intersection between a moving object + that is already interpenetrating the fixed object. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param box Fixed box. + @param location Location of collision -- not center position of sphere + at the collision time. [Post Condition] + @param outNormal Box's surface normal to collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingSphereFixedBox( + const class Sphere& sphere, + const Vector3& velocity, + const class Box& box, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** Calculates time between the intersection of a moving sphere + and a fixed sphere. + + If they are already interpenetrating, returns 0 and @a + location is the closest point on the surface of the fixed sphere + to the center of the moving sphere. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param fixedSphere Fixed Sphere. + @param outLocation Location of collision -- not center position of sphere + at the collision time. [Post Condition] + @param outNormal Moving sphere's surface normal to collision [Post Condition] + + @return Time until collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingSphereFixedSphere( + const Sphere& sphere, + const Vector3& velocity, + const Sphere& fixedSphere, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Calculates time between the intersection of a moving sphere and a fixed + capsule. + + @note This won't detect a collision if the sphere is already + interpenetrating the capsule. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param capsule Fixed capsule. + @param location Location of collision -- not center position of sphere + at the collision time. [Post Condition] + @param outNormal Capsule's surface normal to the collision [Post Condition] + + @return Time til collision. If there is no collision then the return + value will be inf(). + */ + static float collisionTimeForMovingSphereFixedCapsule( + const class Sphere& sphere, + const Vector3& velocity, + const class Capsule& capsule, + Vector3& outLocation, + Vector3& outNormal = ignore); + + /** + Finds the direction of bounce that a sphere would have when it + intersects an object with the given time of collision, the + collision location and the collision normal. + + @note This function works like a pong style ball bounce. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param collisionTime Time of collision. + @param collisionLocation Collision location. + @param collisionNormal Surface collision normal. + + @return Direction of bounce. + */ + static Vector3 bounceDirection( + const class Sphere& sphere, + const Vector3& velocity, + const float collisionTime, + const Vector3& collisionLocation, + const Vector3& collisionNormal); + + /** + Finds the direction of slide given a moving sphere, its velocity, the + time of collision and the collision location. This function works as + if the sphere intersects the surface and continues to hug it. + + @note The result will work well for calculating the movement of a player + who collides with an object and continues moving along the object instead + of just bouncing off it. + + @param sphere Moving sphere. + @param velocity Sphere's velocity. + @param collisionTime Time of collision + @param collisionLocation Collision location. + + @return Direction of slide. + */ + static Vector3 slideDirection( + const class Sphere& sphere, + const Vector3& velocity, + const float collisionTime, + const Vector3& collisionLocation); + + /** + Finds the closest point on a line segment to a given point. + + @param v0 line vertex 1. + @param v1 line vertex 2. + @param point External point. + + @return Closests point to point on the line segment. + */ + static Vector3 closestPointOnLineSegment( + const Vector3& v0, + const Vector3& v1, + const Vector3& point); + + /** + Finds the closest point on a line segment to a given point. + + @note This is an optimization to closestPointOnLineSegment. Edge length + and direction can be used in this function if already pre-calculated. This + prevents doing the same work twice. + + @param v0 line vertex 0. + @param v1 line vertex 1. + @param edgeDirection The direction of the segment (unit length). + @param edgeLength The length of the segment. + @param point External point. + + @return Closests point to point on the line segment. + */ + static Vector3 closestPointOnLineSegment( + const Vector3& v0, + const Vector3& v1, + const Vector3& edgeDirection, + float edgeLength, + const Vector3& point); + + /** + Finds the closest point on the perimeter of the triangle to an external point; + given a triangle defined by three points v0, v1, & v2, and the external point. + + @param v0 Triangle vertex 0. + @param v1 Triangle vertex 1. + @param v2 Triangle vertex 2. + @param point External point. + + @return Closests point to point on the perimeter of the + triangle. + */ + static Vector3 closestPointOnTrianglePerimeter( + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& point); + + /** + Finds the closest point on the perimeter of the triangle to an external point; + given a triangle defined by the array of points v, its edge directions and + their lengths, as well as the external point. + + @note This is an optimization to closestPointToTrianglePerimeter. Edge length + and direction can be used in this function if already pre-calculated. This + prevents doing the same work twice. + + @param v Triangle vertices. + @param point External point. + @param edgeIndex The point lies on the edge between v[edgeIndex] and v[(edgeIndex + 1) % 3] + + @return Closest point to point on the perimeter of the + triangle. + */ + static Vector3 closestPointOnTrianglePerimeter( + const Vector3 v[3], + const Vector3 edgeDirection[3], + const float edgeLength[3], + const Vector3& point, + int& edgeIndex); + + /** + Tests whether a point is contained within the triangle defined by + v0, v1, and v2 and its plane's normal. + + @param v0 Triangle vertex 0. + @param v1 Triangle vertex 1. + @param v2 Triangle vertex 2. + @param normal Normal to triangle's plane. + @param point The point in question. + @param primaryAxis Primary axis of triangle. This will be detected + if not given. This parameter is provided as an optimization. + @param b Barycentric coordinates; b[i] is the weight on v[i] + + @return true - if point is inside the triangle. + @return false - otherwise + */ + static bool isPointInsideTriangle( + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& normal, + const Vector3& point, + float b[3], + Vector3::Axis primaryAxis = Vector3::DETECT_AXIS); + + inline static bool isPointInsideTriangle( + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& normal, + const Vector3& point, + Vector3::Axis primaryAxis = Vector3::DETECT_AXIS) { + + float b[3]; + return isPointInsideTriangle(v0, v1, v2, normal, point, b, primaryAxis); + } + + /** + Tests for the intersection of a moving sphere and a fixed box in a + given time limit. + + @note Returns true if any part of the sphere is inside the box + during the time period (inf means "ever"). Useful for + performing bounding-box collision detection. + + @param sphere Moving sphere. + @param velocity Velocity of moving sphere. + @param box Fixed box. + @param timeLimit Time limit for intersection test. + + @return true - if the two objects will touch. + @return false - if there is no intersection. + */ + static bool movingSpherePassesThroughFixedBox( + const Sphere& sphere, + const Vector3& velocity, + const Box& box, + double timeLimit = inf()); + + /** + Tests for the intersection of a moving sphere and a fixed sphere in a + given time limit. + + @note This function will not detect an intersection between a moving object + that is already interpenetrating the fixed object. + + @param sphere Moving sphere. + @param velocity Velocity of moving sphere. + @param fixedSphere Fixed sphere. + @param timeLimit Time limit for intersection test. + + @return true - if the two spheres will touch. + @return false - if there is no intersection. + */ + static bool movingSpherePassesThroughFixedSphere( + const Sphere& sphere, + const Vector3& velocity, + const Sphere& fixedSphere, + double timeLimit = inf()); + + /** + Tests for the intersection of two fixed spheres. + + @param sphere1 Fixed sphere 1. + @param sphere2 Fixed sphere 2. + + @return true - if the two spheres touch. + @return false - if there is no intersection. + */ + static bool fixedSolidSphereIntersectsFixedSolidSphere( + const Sphere& sphere1, + const Sphere& sphere2); + + /** + Tests for the intersection of a fixed sphere and a fixed box. + + @param sphere Fixed sphere. + @param box Fixed box. + + @return true - if the two objects touch. + @return false - if there is no intersection. + */ + static bool fixedSolidSphereIntersectsFixedSolidBox( + const Sphere& sphere, + const Box& box); + + static bool fixedSolidSphereIntersectsFixedTriangle( + const Sphere& sphere, + const Triangle& triangle); + + static bool fixedSolidBoxIntersectsFixedTriangle( + const AABox& box, + const Triangle& triangle); + + /** + Tests whether a point is inside a rectangle defined by the vertexes + v0, v1, v2, & v3, and the rectangle's plane normal. + + @param v0 Rectangle vertex 1. + @param v1 Rectangle vertex 2. + @param v2 Rectangle vertex 3. + @param v3 Rectangle vertex 4. + @param normal Normal to rectangle's plane. + @param point The point in question. + + @return true - if point is inside the rectangle. + @return false - otherwise + */ + static bool isPointInsideRectangle( + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& v3, + const Vector3& normal, + const Vector3& point); + + /** + Finds the closest point on the perimeter of the rectangle to an + external point; given a rectangle defined by four points v0, v1, + v2, & v3, and the external point. + + @param v0 Rectangle vertex 1. + @param v1 Rectangle vertex 2. + @param v2 Rectangle vertex 3. + @param v3 Rectangle vertex 4. + @param point External point. + + @return Closests point to point on the perimeter of the + rectangle. + */ + static Vector3 closestPointToRectanglePerimeter( + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& v3, + const Vector3& point); + + /** + Finds the closest point in the rectangle to an external point; Given + a rectangle defined by four points v0, v1, v2, & v3, and the external + point. + + @param v0 Rectangle vertex 1. + @param v1 Rectangle vertex 2. + @param v2 Rectangle vertex 3 + @param v3 Rectangle vertex 4. + @param point External point. + + @return Closet point in the rectangle to the external point. + */ + static Vector3 closestPointToRectangle( + const Vector3& v0, + const Vector3& v1, + const Vector3& v2, + const Vector3& v3, + const Vector3& point); +}; + +} // namespace + +#endif // G3D_COLLISIONDETECTION_H diff --git a/externals/g3dlite/G3D/Color1.h b/externals/g3dlite/G3D/Color1.h new file mode 100644 index 00000000000..0f68c84b363 --- /dev/null +++ b/externals/g3dlite/G3D/Color1.h @@ -0,0 +1,144 @@ +/** + @file Color1.h + + Monochrome Color class + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @created 2007-01-31 + @edited 2009-03-20 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_COLOR1_H +#define G3D_COLOR1_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/HashTrait.h" +#include + +namespace G3D { + +/** + Monochrome color. This is just a float, but it has nice semantics + because a scaling by 255 automatically occurs when switching between + fixed point (Color1uint8) and floating point (Color1) formats. + */ +class Color1 { +private: + // Hidden operators + bool operator<(const Color1&) const; + bool operator>(const Color1&) const; + bool operator<=(const Color1&) const; + bool operator>=(const Color1&) const; + +public: + float value; + + /** + Initializes to 0 + */ + inline Color1() : value(0) {} + + Color1(class BinaryInput& bi); + + inline explicit Color1(float v) : value(v) { + } + + inline bool isZero() const { + return value == 0.0f; + } + + inline bool isOne() const { + return value == 1.0f; + } + + static const Color1& one(); + + static const Color1& zero(); + + /** Returns the value three times */ + class Color3 rgb() const; + + Color1 (const class Color1uint8& other); + + void serialize(class BinaryOutput& bo) const; + void deserialize(class BinaryInput& bi); + + Color1 operator+ (const Color1& other) const { + return Color1(value + other.value); + } + + Color1 operator+ (const float other) const { + return Color1(value + other); + } + + Color1& operator+= (const Color1 other) { + value += other.value; + return *this; + } + + Color1& operator-= (const Color1 other) { + value -= other.value; + return *this; + } + + Color1 operator- (const Color1& other) const { + return Color1(value - other.value); + } + + Color1 operator- (const float other) const { + return Color1(value - other); + } + + Color1 operator- () const { + return Color1(-value); + } + + Color1 operator* (const Color1& other) const { + return Color1(value * other.value); + } + + Color1 operator* (const float other) const { + return Color1(value * other); + } + + Color1 operator/ (const Color1& other) const { + return Color1(value / other.value); + } + + Color1 operator/ (const float other) const { + return Color1(value / other); + } + + inline Color1 max(const Color1& other) const { + return Color1(G3D::max(value, other.value)); + } + + inline Color1 min(const Color1& other) const { + return Color1(G3D::min(value, other.value)); + } + + inline Color1 lerp(const Color1& other, float a) const { + return Color1(value + (other.value - value) * a); + + } + + inline size_t hashCode() const { + return (size_t)(value * 0xFFFFFF); + } +}; + +} + +template <> +struct HashTrait { + static size_t hashCode(const G3D::Color1& key) { + return key.hashCode(); + } +}; + + +#endif diff --git a/externals/g3dlite/G3D/Color1uint8.h b/externals/g3dlite/G3D/Color1uint8.h new file mode 100644 index 00000000000..092099d0d17 --- /dev/null +++ b/externals/g3dlite/G3D/Color1uint8.h @@ -0,0 +1,91 @@ +/** + @file Color1uint8.h + + @maintainer Morgan McGuire, graphics3d.com + + @created 2007-01-30 + @edited 2007-01-30 + + Copyright 2000-2007, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_COLOR1UINT8_H +#define G3D_COLOR1UINT8_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" + +namespace G3D { + +/** + Represents a Color1 as a packed integer. Convenient + for creating unsigned int vertex arrays. + + WARNING: Integer color formats are different than + integer vertex formats. The color channels are automatically + scaled by 255 (because OpenGL automatically scales integer + colors back by this factor). So Color3(1,1,1) == Color3uint8(255,255,255) + but Vector3(1,1,1) == Vector3int16(1,1,1). + + Note: + Conversion of a float32 to uint8 is accomplished by min(iFloor(f * 256)) and + back to float32 by u / 255.0f. This gives equal size intervals. +Consider a number line from 0 to 1 and a corresponding one from 0 to 255. If we use iRound(x * 255), then the mapping for three critical intervals are: + +

+let s = 0.5/255
+  float             int       size
+[0, s)           -> 0          s
+[s, s * 3)       -> 1         2*s
+(1 - s, 1]       -> 255        s
+
+ +If we use max(floor(x * 256), 255), then we get: + +
+let s = 1/256
+  float             int           size
+[0, s)           -> 0               s
+[s, 2 * s)       -> 1               s
+(1 - s, 1]       -> 255             s
+
+and the intervals are all the same size, thus giving equal precision to all values. + */ +G3D_BEGIN_PACKED_CLASS(1) +class Color1uint8 { +private: + // Hidden operators + bool operator<(const Color1uint8&) const; + bool operator>(const Color1uint8&) const; + bool operator<=(const Color1uint8&) const; + bool operator>=(const Color1uint8&) const; + +public: + + uint8 value; + + Color1uint8() : value(0) {} + + explicit Color1uint8(const uint8 _v) : value(_v) {} + + Color1uint8(const class Color1& c); + + Color1uint8(class BinaryInput& bi); + + void serialize(class BinaryOutput& bo) const; + + void deserialize(class BinaryInput& bi); + + inline bool operator==(const Color1uint8& other) const { + return value == other.value; + } + + inline bool operator!=(const Color1uint8& other) const { + return value != other.value; + } + +} +G3D_END_PACKED_CLASS(1) +} +#endif diff --git a/externals/g3dlite/G3D/Color3.h b/externals/g3dlite/G3D/Color3.h new file mode 100644 index 00000000000..bffe434fc27 --- /dev/null +++ b/externals/g3dlite/G3D/Color3.h @@ -0,0 +1,432 @@ +/** + @file Color3.h + + Color class + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @cite Portions based on Dave Eberly's Magic Software Library + at http://www.magic-software.com + + @created 2001-06-02 + @edited 2009-04-28 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_Color3_h +#define G3D_Color3_h + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/HashTrait.h" +#include "G3D/Color1.h" +#include + +namespace G3D { +class Any; + +/** + Do not subclass-- this implementation makes assumptions about the + memory layout. + */ +class Color3 { +private: + // Hidden operators + bool operator<(const Color3&) const; + bool operator>(const Color3&) const; + bool operator<=(const Color3&) const; + bool operator>=(const Color3&) const; + +public: + /** + Does not initialize fields. + */ + Color3(); + + /** \param any Must be in one of the following forms: + - Color3(#, #, #) + - Color3::fromARGB(#) + - Color3{r = #, g = #, b = #) + - Color3::one() + - Color3::zero() + */ + Color3(const Any& any); + + /** Converts the Color3 to an Any. */ + operator Any() const; + + explicit Color3(class BinaryInput& bi); + + Color3(float r, float g, float b); + Color3(float v) : r(v), g(v), b(v) {} + + explicit Color3(const class Vector3& v); + + explicit Color3(const float value[3]); + + /** Returns this color */ + const Color3& rgb() const { + return *this; + } + + /** + Initialize from another color. + */ + Color3 (const Color3& other); + + Color3 (const class Color3uint8& other); + + inline bool isZero() const { + return (r == 0.0f) && (g == 0.0f) && (b == 0.0f); + } + + inline bool isOne() const { + return (r == 1.0f) && (g == 1.0f) && (b == 1.0f); + } + + bool isFinite() const; + + /** + Initialize from an HTML-style color (e.g. 0xFF0000 == RED) + */ + static Color3 fromARGB(uint32); + + /** Returns one of the color wheel colors (e.g. RED, GREEN, CYAN). + Does not include white, black, or gray. */ + static const Color3& wheelRandom(); + + /** Generate colors according to the ANSI color set, mod 16. + \sa pastelMap */ + static Color3 ansiMap(uint32 i); + + /** + Generate colors using a hash such that adjacent values + are unlikely to have similar colors. + + Useful for rendering with + stable but arbitrary colors, e.g., when debugging a mesh + algorithm. + + \sa ansiMap + */ + static Color3 pastelMap(uint32 i); + + /** + * Channel value. + */ + float r, g, b; + + void serialize(class BinaryOutput& bo) const; + void deserialize(class BinaryInput& bi); + + // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b + // + // WARNING. These member functions rely on + // (1) Color3 not having virtual functions + // (2) the data packed in a 3*sizeof(float) memory block + const float& operator[] (int i) const; + float& operator[] (int i); + + // assignment and comparison + Color3& operator= (const Color3& rkVector); + bool operator== (const Color3& rkVector) const; + bool operator!= (const Color3& rkVector) const; + size_t hashCode() const; + + // arithmetic operations + Color3 operator+ (const Color3& rkVector) const; + Color3 operator- (const Color3& rkVector) const; + inline Color3 operator* (float s) const { + return Color3(r * s, g * s, b * s); + } + Color3 operator* (const Color3& rkVector) const; + inline Color3 operator/ (float fScalar) const { + return (*this) * (1.0f / fScalar); + } + Color3 operator- () const; + + // arithmetic updates + Color3& operator+= (const Color3& rkVector); + Color3& operator-= (const Color3& rkVector); + Color3& operator*= (const Color3& rkVector); + Color3& operator*= (float fScalar); + Color3& operator/= (float fScalar); + + bool fuzzyEq(const Color3& other) const; + bool fuzzyNe(const Color3& other) const; + + // vector operations + float length () const; + Color3 direction() const; + float squaredLength () const; + float dot (const Color3& rkVector) const; + float unitize (float fTolerance = 1e-06); + Color3 cross (const Color3& rkVector) const; + Color3 unitCross (const Color3& rkVector) const; + + inline Color3 pow(const Color3& other) const { + return Color3(::pow(r, other.r), ::pow(g, other.g), ::pow(b, other.b)); + } + + inline Color3 pow(float other) const { + return Color3(::pow(r, other), ::pow(g, other), ::pow(b, other)); + } + + inline Color3 max(const Color3& other) const { + return Color3(G3D::max(r, other.r), G3D::max(g, other.g), G3D::max(b, other.b)); + } + + inline Color3 min(const Color3& other) const { + return Color3(G3D::min(r, other.r), G3D::min(g, other.g), G3D::min(b, other.b)); + } + + /** Smallest element */ + inline float min() const { + return G3D::min(G3D::min(r, g), b); + } + + /** Largest element */ + inline float max() const { + return G3D::max(G3D::max(r, g), b); + } + + inline Color3 lerp(const Color3& other, float a) const { + return (*this) + (other - *this) * a; + + } + + inline float sum() const { + return r + g + b; + } + + inline float average() const { + return sum() / 3.0f; + } + + + /** + * Converts from HSV to RGB , note: toHSV(fromHSV(_hsv)) may not be _hsv, if it is at a grey point or black point. + * The components of _hsv should lie in the unit interval. + * @cite Alvy Ray Smith SIGGRAPH 1978 "Color Gamut Transform Pairs" + **/ + static Color3 fromHSV(const Vector3& _hsv); + static Vector3 toHSV(const Color3& _rgb); + + /** Duplicates the matlab jet colormap maps [0,1] --> (r,g,b) where blue is close to 0 and red is close to 1. */ + static Color3 jetColorMap(const float& val); + + /** Returns colors with maximum saturation and value @param hue [0, 1]*/ + static Color3 rainbowColorMap(float hue); + + std::string toString() const; + + /** Random unit vector */ + static Color3 random(); + + // Special values. + // Intentionally not inlined: see Matrix3::identity() for details. + static const Color3& red(); + static const Color3& green(); + static const Color3& blue(); + static const Color3& purple(); + static const Color3& cyan(); + static const Color3& yellow(); + static const Color3& brown(); + static const Color3& orange(); + static const Color3& black(); + static const Color3& gray(); + static const Color3& white(); + + static const Color3& zero(); + static const Color3& one(); + + inline Color3 bgr() const { + return Color3(b, g, r); + } +}; + +inline G3D::Color3 operator* (float s, const G3D::Color3& c) { + return c * s; +} + +inline G3D::Color3 operator* (G3D::Color1& s, const G3D::Color3& c) { + return c * s.value; +} + +inline G3D::Color3 operator* (const G3D::Color3& c, G3D::Color1& s) { + return c * s.value; +} + + +//---------------------------------------------------------------------------- +inline Color3::Color3 () { +} + +//---------------------------------------------------------------------------- + +inline Color3::Color3(float fX, float fY, float fZ) { + r = fX; + g = fY; + b = fZ; +} + +//---------------------------------------------------------------------------- +inline Color3::Color3(const float afCoordinate[3]) { + r = afCoordinate[0]; + g = afCoordinate[1]; + b = afCoordinate[2]; +} + +//---------------------------------------------------------------------------- +inline Color3::Color3 (const Color3& rkVector) { + r = rkVector.r; + g = rkVector.g; + b = rkVector.b; +} + +//---------------------------------------------------------------------------- +inline float& Color3::operator[] (int i) { + return ((float*)this)[i]; +} + +//---------------------------------------------------------------------------- + +inline const float& Color3::operator[] (int i) const { + return ((float*)this)[i]; +} + +//---------------------------------------------------------------------------- + +inline bool Color3::fuzzyEq(const Color3& other) const { + return G3D::fuzzyEq((*this - other).squaredLength(), 0); +} + +//---------------------------------------------------------------------------- + +inline bool Color3::fuzzyNe(const Color3& other) const { + return G3D::fuzzyNe((*this - other).squaredLength(), 0); +} + + +//---------------------------------------------------------------------------- +inline Color3& Color3::operator= (const Color3& rkVector) { + r = rkVector.r; + g = rkVector.g; + b = rkVector.b; + return *this; +} + +//---------------------------------------------------------------------------- +inline bool Color3::operator== (const Color3& rkVector) const { + return ( r == rkVector.r && g == rkVector.g && b == rkVector.b ); +} + +//---------------------------------------------------------------------------- +inline bool Color3::operator!= (const Color3& rkVector) const { + return ( r != rkVector.r || g != rkVector.g || b != rkVector.b ); +} + +//---------------------------------------------------------------------------- +inline Color3 Color3::operator+ (const Color3& rkVector) const { + return Color3(r + rkVector.r, g + rkVector.g, b + rkVector.b); +} + +//---------------------------------------------------------------------------- +inline Color3 Color3::operator- (const Color3& rkVector) const { + return Color3(r -rkVector.r, g - rkVector.g, b - rkVector.b); +} + +//---------------------------------------------------------------------------- +inline Color3 Color3::operator* (const Color3& rkVector) const { + return Color3(r * rkVector.r, g * rkVector.g, b * rkVector.b); +} + +//---------------------------------------------------------------------------- +inline Color3 Color3::operator- () const { + return Color3( -r, -g, -b); +} + +//---------------------------------------------------------------------------- +inline Color3& Color3::operator+= (const Color3& rkVector) { + r += rkVector.r; + g += rkVector.g; + b += rkVector.b; + return *this; +} + +//---------------------------------------------------------------------------- +inline Color3& Color3::operator-= (const Color3& rkVector) { + r -= rkVector.r; + g -= rkVector.g; + b -= rkVector.b; + return *this; +} + +//---------------------------------------------------------------------------- +inline Color3& Color3::operator*= (float fScalar) { + r *= fScalar; + g *= fScalar; + b *= fScalar; + return *this; +} + +//---------------------------------------------------------------------------- +inline Color3& Color3::operator*= (const Color3& rkVector) { + r *= rkVector.r; + g *= rkVector.g; + b *= rkVector.b; + return *this; +} +//---------------------------------------------------------------------------- +inline float Color3::squaredLength () const { + return r*r + g*g + b*b; +} + +//---------------------------------------------------------------------------- +inline float Color3::length () const { + return sqrtf(r*r + g*g + b*b); +} + +//---------------------------------------------------------------------------- +inline Color3 Color3::direction () const { + float lenSquared = r * r + g * g + b * b; + + if (lenSquared != 1.0f) { + return *this / sqrtf(lenSquared); + } else { + return *this; + } +} + +//---------------------------------------------------------------------------- +inline float Color3::dot (const Color3& rkVector) const { + return r*rkVector.r + g*rkVector.g + b*rkVector.b; +} + +//---------------------------------------------------------------------------- +inline Color3 Color3::cross (const Color3& rkVector) const { + return Color3(g*rkVector.b - b*rkVector.g, b*rkVector.r - r*rkVector.b, + r*rkVector.g - g*rkVector.r); +} + +//---------------------------------------------------------------------------- +inline Color3 Color3::unitCross (const Color3& rkVector) const { + Color3 kCross(g*rkVector.b - b*rkVector.g, b*rkVector.r - r*rkVector.b, + r*rkVector.g - g*rkVector.r); + kCross.unitize(); + return kCross; +} + + +} // namespace + + +template <> struct HashTrait { + static size_t hashCode(const G3D::Color3& key) { + return key.hashCode(); + } +}; + + +#endif diff --git a/externals/g3dlite/G3D/Color3uint8.h b/externals/g3dlite/G3D/Color3uint8.h new file mode 100644 index 00000000000..bd4b00d7fd6 --- /dev/null +++ b/externals/g3dlite/G3D/Color3uint8.h @@ -0,0 +1,110 @@ +/** + @file Color3uint8.h + + @maintainer Morgan McGuire, graphics3d.com + + @created 2003-04-07 + @edited 2006-06-24 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_COLOR3UINT8_H +#define G3D_COLOR3UINT8_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" + +namespace G3D { + +/** + Represents a Color3 as a packed integer. Convenient + for creating unsigned int vertex arrays. Used by + G3D::GImage as the underlying format. + + WARNING: Integer color formats are different than + integer vertex formats. The color channels are automatically + scaled by 255 (because OpenGL automatically scales integer + colors back by this factor). So Color3(1,1,1) == Color3uint8(255,255,255) + but Vector3(1,1,1) == Vector3int16(1,1,1). + */ + +G3D_BEGIN_PACKED_CLASS(1) + +class Color3uint8 { +private: + // Hidden operators + bool operator<(const Color3uint8&) const; + bool operator>(const Color3uint8&) const; + bool operator<=(const Color3uint8&) const; + bool operator>=(const Color3uint8&) const; + +public: + uint8 r; + uint8 g; + uint8 b; + + Color3uint8() : r(0), g(0), b(0) {} + + Color3uint8(const uint8 _r, const uint8 _g, const uint8 _b) : r(_r), g(_g), b(_b) {} + + Color3uint8(const class Color3& c); + + Color3uint8(class BinaryInput& bi); + + inline static Color3uint8 fromARGB(uint32 i) { + Color3uint8 c; + c.r = (i >> 16) & 0xFF; + c.g = (i >> 8) & 0xFF; + c.b = i & 0xFF; + return c; + } + + inline Color3uint8 bgr() const { + return Color3uint8(b, g, r); + } + + /** + Returns the color packed into a uint32 + (the upper byte is 0xFF) + */ + inline uint32 asUInt32() const { + return (0xFF << 24) + ((uint32)r << 16) + ((uint32)g << 8) + b; + } + + void serialize(class BinaryOutput& bo) const; + + void deserialize(class BinaryInput& bi); + + // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b + // + // WARNING. These member functions rely on + // (1) Color3 not having virtual functions + // (2) the data packed in a 3*sizeof(uint8) memory block + uint8& operator[] (int i) const { + debugAssert((unsigned int)i < 3); + return ((uint8*)this)[i]; + } + + operator uint8* () { + return (G3D::uint8*)this; + } + + operator const uint8* () const { + return (uint8*)this; + } + + bool operator==(const Color3uint8& other) const { + return (other.r == r) && (other.g == g) && (other.b == b); + } + + bool operator!=(const Color3uint8& other) const { + return (other.r != r) && (other.g != g) && (other.b != b); + } +} +G3D_END_PACKED_CLASS(1) + +} // namespace G3D + +#endif diff --git a/externals/g3dlite/G3D/Color4.h b/externals/g3dlite/G3D/Color4.h new file mode 100644 index 00000000000..d8858abbce2 --- /dev/null +++ b/externals/g3dlite/G3D/Color4.h @@ -0,0 +1,338 @@ +/** + @file Color4.h + + Color class + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @cite Portions based on Dave Eberly's Magic Software Library + at http://www.magic-software.com + + @created 2002-06-25 + @edited 2009-11-15 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_Color4_h +#define G3D_Color4_h + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Color3.h" +#include + +namespace G3D { + +class Any; + +/** + Do not subclass-- this implementation makes assumptions about the + memory layout. + */ +class Color4 { +private: + // Hidden operators + bool operator<(const Color4&) const; + bool operator>(const Color4&) const; + bool operator<=(const Color4&) const; + bool operator>=(const Color4&) const; + +public: + + /** \param any Must be in one of the following forms: + - Color4(#, #, #, #) + - Color4::fromARGB(#) + - Color4{r = #, g = #, b = #, a = #) + */ + Color4(const Any& any); + + /** Converts the Color4 to an Any. */ + operator Any() const; + + /** + * Does not initialize fields. + */ + Color4 (); + + Color4(const Color3& c3, float a = 1.0); + + Color4(const class Color4uint8& c); + + Color4(class BinaryInput& bi); + + Color4(const class Vector4& v); + + Color4(float r, float g, float b, float a = 1.0); + + static const Color4& one(); + + Color4(float value[4]); + + /** + * Initialize from another color. + */ + Color4(const Color4& other); + + + inline bool isZero() const { + return (r == 0.0f) && (g == 0.0f) && (b == 0.0f) && (a == 0.0f); + } + + inline bool isOne() const { + return (r == 1.0f) && (g == 1.0f) && (b == 1.0f) && (a == 1.0f); + } + + void serialize(class BinaryOutput& bo) const; + void deserialize(class BinaryInput& bi); + + /** + Initialize from an HTML-style color (e.g. 0xFFFF0000 == RED) + */ + static Color4 fromARGB(uint32); + + /** + * Channel values. + */ + float r, g, b, a; + + inline Color3 rgb() const { + return Color3(r, g, b); + } + + // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b, v[3] = V.a + // + // WARNING. These member functions rely on + // (1) Color4 not having virtual functions + // (2) the data packed in a 3*sizeof(float) memory block + float& operator[] (int i) const; + + // assignment and comparison + Color4& operator= (const Color4& rkVector); + bool operator== (const Color4& rkVector) const; + bool operator!= (const Color4& rkVector) const; + size_t hashCode() const; + + // arithmetic operations + Color4 operator+ (const Color4& rkVector) const; + Color4 operator- (const Color4& rkVector) const; + Color4 operator* (float fScalar) const; + inline Color4 operator* (const Color4& k) const { + return Color4(r*k.r, g*k.g, b*k.b, a * k.a); + } + Color4 operator/ (float fScalar) const; + Color4 operator- () const; + friend Color4 operator* (double fScalar, const Color4& rkVector); + + // arithmetic updates + Color4& operator+= (const Color4& rkVector); + Color4& operator-= (const Color4& rkVector); + Color4& operator*= (float fScalar); + Color4& operator/= (float fScalar); + + bool fuzzyEq(const Color4& other) const; + bool fuzzyNe(const Color4& other) const; + + std::string toString() const; + + inline Color4 max(const Color4& other) const { + return Color4(G3D::max(r, other.r), G3D::max(g, other.g), G3D::max(b, other.b), G3D::max(a, other.a)); + } + + inline Color4 min(const Color4& other) const { + return Color4(G3D::min(r, other.r), G3D::min(g, other.g), G3D::min(b, other.b), G3D::min(a, other.a)); + } + + /** r + g + b + a */ + inline float sum() const { + return r + g + b + a; + } + + inline Color4 lerp(const Color4& other, float a) const { + return (*this) + (other - *this) * a; + + } + + // Special values. + // Intentionally not inlined: see Matrix3::identity() for details. + static const Color4& zero(); + static const Color4& clear(); + + static const Color4& inf(); + static const Color4& nan(); + + inline bool isFinite() const { + return G3D::isFinite(r) && G3D::isFinite(g) && G3D::isFinite(b) && G3D::isFinite(a); + } + + inline Color3 bgr() const { + return Color3(b, g, r); + } +}; + +/** + Extends the c3 with alpha = 1.0 + */ +Color4 operator*(const Color3& c3, const Color4& c4); + + +inline Color4 operator*(const Color3& c3, const Color4& c4) { + return Color4(c3.r * c4.r, c3.g * c4.g, c3.b * c4.b, c4.a); +} + +//---------------------------------------------------------------------------- + +inline Color4::Color4 () { + // For efficiency in construction of large arrays of vectors, the + // default constructor does not initialize the vector. +} + +//---------------------------------------------------------------------------- + +inline Color4::Color4(const Color3& c3, float a) { + r = c3.r; + g = c3.g; + b = c3.b; + this->a = a; +} + +//---------------------------------------------------------------------------- + +inline Color4::Color4( + float r, + float g, + float b, + float a) : + r(r), g(g), b(b), a(a) { +} + +//---------------------------------------------------------------------------- +inline Color4::Color4 (float afCoordinate[4]) { + r = afCoordinate[0]; + g = afCoordinate[1]; + b = afCoordinate[2]; + a = afCoordinate[3]; +} + +//---------------------------------------------------------------------------- + +inline Color4::Color4( + const Color4& other) { + + r = other.r; + g = other.g; + b = other.b; + a = other.a; +} + +//---------------------------------------------------------------------------- + +inline float& Color4::operator[] (int i) const { + return ((float*)this)[i]; +} + +//---------------------------------------------------------------------------- + +inline bool Color4::fuzzyEq(const Color4& other) const { + Color4 dif = (*this - other); + return G3D::fuzzyEq(dif.r * dif.r + dif.g * dif.g + dif.b * dif.b + dif.a * dif.a, 0); +} + +//---------------------------------------------------------------------------- + +inline bool Color4::fuzzyNe(const Color4& other) const { + Color4 dif = (*this - other); + return G3D::fuzzyNe(dif.r * dif.r + dif.g * dif.g + dif.b * dif.b + dif.a * dif.a, 0); +} + + +//---------------------------------------------------------------------------- +inline Color4& Color4::operator= (const Color4& other) { + r = other.r; + g = other.g; + b = other.b; + a = other.a; + return *this; +} + +//---------------------------------------------------------------------------- + +inline bool Color4::operator== (const Color4& other) const { + return ( r == other.r && g == other.g && b == other.b && a == other.a); +} + +//---------------------------------------------------------------------------- + +inline bool Color4::operator!= (const Color4& other) const { + return ( r != other.r || g != other.g || b != other.b || a != other.a); +} + +//---------------------------------------------------------------------------- +inline Color4 Color4::operator+ (const Color4& other) const { + return Color4(r + other.r, g + other.g, b + other.b, a + other.a); +} + +//---------------------------------------------------------------------------- +inline Color4 Color4::operator- (const Color4& other) const { + return Color4(r - other.r, g - other.g, b - other.b, a - other.a); +} + +//---------------------------------------------------------------------------- + +inline Color4 Color4::operator* (float fScalar) const { + return Color4(fScalar * r, fScalar * g, fScalar * b, fScalar * a); +} + +//---------------------------------------------------------------------------- + +inline Color4 Color4::operator- () const { + return Color4(-r, -g, -b, -a); +} + +//---------------------------------------------------------------------------- + +inline Color4 operator* (float fScalar, const Color4& other) { + return Color4(fScalar * other.r, fScalar * other.g, + fScalar * other.b, fScalar * other.a); +} + +//---------------------------------------------------------------------------- + +inline Color4& Color4::operator+= (const Color4& other) { + r += other.r; + g += other.g; + b += other.b; + a += other.a; + return *this; +} + +//---------------------------------------------------------------------------- + +inline Color4& Color4::operator-= (const Color4& other) { + r -= other.r; + g -= other.g; + b -= other.b; + a -= other.a; + return *this; +} + +//---------------------------------------------------------------------------- + +inline Color4& Color4::operator*= (float fScalar) { + r *= fScalar; + g *= fScalar; + b *= fScalar; + a *= fScalar; + return *this; +} + +} // namespace + +template <> +struct HashTrait { + static size_t hashCode(const G3D::Color4& key) { + return key.hashCode(); + } +}; + +#endif diff --git a/externals/g3dlite/G3D/Color4uint8.h b/externals/g3dlite/G3D/Color4uint8.h new file mode 100644 index 00000000000..ab8c0729276 --- /dev/null +++ b/externals/g3dlite/G3D/Color4uint8.h @@ -0,0 +1,115 @@ +/** + @file Color4uint8.h + + @maintainer Morgan McGuire, graphics3d.com + + @created 2003-04-07 + @edited 2006-03-24 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef COLOR4UINT8_H +#define COLOR4UINT8_H + +#include "G3D/g3dmath.h" +#include "G3D/platform.h" +#include "G3D/Color3uint8.h" + +namespace G3D { + +/** + Represents a Color4 as a packed integer. Convenient + for creating unsigned int vertex arrays. Used by + G3D::GImage as the underlying format. + + WARNING: Integer color formats are different than + integer vertex formats. The color channels are automatically + scaled by 255 (because OpenGL automatically scales integer + colors back by this factor). So Color4(1,1,1) == Color4uint8(255,255,255) + but Vector3(1,1,1) == Vector3int16(1,1,1). + + */ +G3D_BEGIN_PACKED_CLASS(1) +class Color4uint8 { +private: + // Hidden operators + bool operator<(const Color4uint8&) const; + bool operator>(const Color4uint8&) const; + bool operator<=(const Color4uint8&) const; + bool operator>=(const Color4uint8&) const; + +public: + uint8 r; + uint8 g; + uint8 b; + uint8 a; + + Color4uint8() : r(0), g(0), b(0), a(0) {} + + Color4uint8(const class Color4& c); + + Color4uint8(const uint8 _r, const uint8 _g, const uint8 _b, const uint8 _a) : r(_r), g(_g), b(_b), a(_a) {} + + Color4uint8(const Color3uint8& c, const uint8 _a) : r(c.r), g(c.g), b(c.b), a(_a) {} + + Color4uint8(class BinaryInput& bi); + + inline static Color4uint8 fromARGB(uint32 i) { + Color4uint8 c; + c.a = (i >> 24) & 0xFF; + c.r = (i >> 16) & 0xFF; + c.g = (i >> 8) & 0xFF; + c.b = i & 0xFF; + return c; + } + + inline uint32 asUInt32() const { + return ((uint32)a << 24) + ((uint32)r << 16) + ((uint32)g << 8) + b; + } + + // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b + // + // WARNING. These member functions rely on + // (1) Color4uint8 not having virtual functions + // (2) the data packed in a 3*sizeof(uint8) memory block + uint8& operator[] (int i) const { + return ((uint8*)this)[i]; + } + + operator uint8* () { + return (uint8*)this; + } + + operator const uint8* () const { + return (uint8*)this; + } + + + inline Color3uint8 bgr() const { + return Color3uint8(b, g, r); + } + + void serialize(class BinaryOutput& bo) const; + + void deserialize(class BinaryInput& bi); + + inline Color3uint8 rgb() const { + return Color3uint8(r, g, b); + } + + bool operator==(const Color4uint8& other) const { + return *reinterpret_cast(this) == *reinterpret_cast(&other); + } + + bool operator!=(const Color4uint8& other) const { + return *reinterpret_cast(this) != *reinterpret_cast(&other); + } + +} +G3D_END_PACKED_CLASS(1) + +} // namespace G3D + +#endif diff --git a/externals/g3dlite/G3D/Cone.h b/externals/g3dlite/G3D/Cone.h new file mode 100644 index 00000000000..d801a9b348f --- /dev/null +++ b/externals/g3dlite/G3D/Cone.h @@ -0,0 +1,68 @@ +/** + @file Cone.h + + Cone class + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com + + @created 2001-06-02 + @edited 2006-02-23 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_CONE_H +#define G3D_CONE_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Vector3.h" + +namespace G3D { + +/** + An infinite cone. + */ +class Cone { + +private: + Vector3 tip; + Vector3 direction; + + /** Angle from the center line to the edge. */ + float angle; + +public: + + /** + @param angle Angle from the center line to the edge, in radians + */ + Cone(const Vector3& tip, const Vector3& direction, float angle); + + /** + Forms the smallest cone that contains the box. Undefined if + the tip is inside or on the box. + */ + Cone(const Vector3& tip, const class Box& box); + + virtual ~Cone() {} + + /** + Returns true if the cone touches, intersects, or contains b. + + If c.intersects(s) and c.intersects(Sphere(s.center, s.radius * 2) + then the sphere s is entirely within cone c. + */ + bool intersects(const class Sphere& s) const; + + /** + True if v is a point inside the cone. + */ + bool contains(const class Vector3& v) const; +}; + +} // namespace + +#endif diff --git a/externals/g3dlite/G3D/ConvexPolyhedron.h b/externals/g3dlite/G3D/ConvexPolyhedron.h new file mode 100644 index 00000000000..a6fdd62cf90 --- /dev/null +++ b/externals/g3dlite/G3D/ConvexPolyhedron.h @@ -0,0 +1,180 @@ +/** + @file ConvexPolyhedron.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2001-11-11 + @edited 2006-04-10 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_CONVEXPOLYHEDRON_H +#define G3D_CONVEXPOLYHEDRON_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Vector2.h" +#include "G3D/CoordinateFrame.h" +#include "G3D/Plane.h" +#include "G3D/Line.h" +#include "G3D/Array.h" + +namespace G3D { + +class DirectedEdge { +public: + Vector3 start; + Vector3 stop; +}; + +class ConvexPolygon { +private: + + friend class ConvexPolyhedron; + + Array _vertex; + +public: + + ConvexPolygon() {} + ConvexPolygon(const Vector3& v0, const Vector3& v1, const Vector3& v2); + ConvexPolygon(const Array& __vertex); + virtual ~ConvexPolygon() {} + + /** + Counter clockwise winding order. + */ + inline const Vector3& vertex(int i) const { + return _vertex[i]; + } + + inline void setVertex(int i, const Vector3& v) { + _vertex[i] = v; + } + + /** + Zero vertices indicates an empty polygon (zero area). + */ + inline int numVertices() const { + return _vertex.size(); + } + + inline void setNumVertices(int n) { + _vertex.resize(n); + } + + /** + O(n) in the number of edges + */ + bool isEmpty() const; + + /** + Cuts the polygon at the plane. If the polygon is entirely above or below + the plane, one of the returned polygons will be empty. + + @param above The part of the polygon above (on the side the + normal points to or in the plane) the plane + @param below The part of the polygon below the plane. + @param newEdge If a new edge was introduced, this is that edge (on the above portion; the below portion is the opposite winding. + */ + void cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon &below, DirectedEdge& newEdge); + void cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon &below); + + /** + When a cut plane grazes a vertex in the polygon, two near-identical vertices may be created. + The closeness of these two points can cause a number of problems, such as ConvexPolygon::normal() + returning an infinite vector. It should be noted, however, that not all applications are + sensitive to near-identical vertices. + + removeDuplicateVertices() detects and eliminates redundant vertices. + */ + void removeDuplicateVertices(); + + /** + O(n) in the number of edges + */ + float getArea() const; + + inline Vector3 normal() const { + debugAssert(_vertex.length() >= 3); + return (_vertex[1] - _vertex[0]).cross(_vertex[2] - _vertex[0]).direction(); + } + + /** + Returns the same polygon with inverse winding. + */ + ConvexPolygon inverse() const; +}; + + + +class ConvexPolyhedron { +public: + /** + Zero faces indicates an empty polyhedron + */ + Array face; + + ConvexPolyhedron() {} + ConvexPolyhedron(const Array& _face); + + /** + O(n) in the number of edges + */ + bool isEmpty() const; + + /** + O(n) in the number of edges + */ + float getVolume() const; + + /** + Cuts the polyhedron at the plane. If the polyhedron is entirely above or below + the plane, one of the returned polyhedra will be empty. + + @param above The part of the polyhedron above (on the side the + normal points to or in the plane) the plane + @param below The part of the polyhedron below the plane. + */ + void cut(const Plane& plane, ConvexPolyhedron &above, ConvexPolyhedron &below); +}; + +/** + + */ +class ConvexPolygon2D { +private: + + Array m_vertex; + +public: + + ConvexPolygon2D() {} + + /** + Points are counter-clockwise in a Y = down, X = right coordinate + system. + + @param reverse If true, the points are reversed (i.e. winding direction is changed) + before the polygon is created. + */ + ConvexPolygon2D(const Array& pts, bool reverse = false); + + inline int numVertices() const { + return m_vertex.size(); + } + + inline const Vector2& vertex(int index) const { + debugAssert((index >= 0) && (index <= m_vertex.size())); + return m_vertex[index]; + } + + /** @param reverseWinding If true, the winding direction of the polygon is reversed for this test.*/ + bool contains(const Vector2& p, bool reverseWinding = false) const; +}; + + +} // namespace +#endif diff --git a/externals/g3dlite/G3D/CoordinateFrame.h b/externals/g3dlite/G3D/CoordinateFrame.h new file mode 100644 index 00000000000..7ed4d0acc65 --- /dev/null +++ b/externals/g3dlite/G3D/CoordinateFrame.h @@ -0,0 +1,331 @@ +/** + @file CoordinateFrame.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2001-03-04 + @edited 2009-04-29 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. +*/ + +#ifndef G3D_CFrame_h +#define G3D_CFrame_h + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Vector4.h" +#include "G3D/Matrix3.h" +#include "G3D/Array.h" +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +// Turn off "conditional expression is constant" warning; MSVC generates this +// for debug assertions in inlined methods. +# pragma warning (disable : 4127) +#endif + + +namespace G3D { +class Any; + +/** + A rigid body RT (rotation-translation) transformation. + +CoordinateFrame abstracts a 4x4 matrix that maps object space to world space: + + v_world = C * v_object + +CoordinateFrame::rotation is the upper 3x3 submatrix, CoordinateFrame::translation +is the right 3x1 column. The 4th row is always [0 0 0 1], so it isn't stored. +So you don't have to remember which way the multiplication and transformation work, +it provides explicit toWorldSpace and toObjectSpace methods. Also, points, vectors +(directions), and surface normals transform differently, so they have separate methods. + +Some helper functions transform whole primitives like boxes in and out of object space. + +Convert to Matrix4 using CoordinateFrame::toMatrix4. You can construct a CoordinateFrame +from a Matrix4 using Matrix4::approxCoordinateFrame, however, because a Matrix4 is more +general than a CoordinateFrame, some information may be lost. + +@sa G3D::UprightFrame, G3D::PhysicsFrame, G3D::Matrix4, G3D::Quat +*/ +class CoordinateFrame { +public: + + /** Takes object space points to world space. */ + Matrix3 rotation; + + /** Takes object space points to world space. */ + Vector3 translation; + + /** \param any Must be in one of the following forms: + - CFrame((matrix3 expr), (vector3 expr)) + - CFrame::fromXYZYPRDegrees(#, #, #, #, #, #) + - CFrame { rotation = (matrix3 expr), translation = (vector3 expr) } + */ + CoordinateFrame(const Any& any); + + /** Converts the CFrame to an Any. */ + operator Any() const; + + inline bool operator==(const CoordinateFrame& other) const { + return (translation == other.translation) && (rotation == other.rotation); + } + + inline bool operator!=(const CoordinateFrame& other) const { + return !(*this == other); + } + + bool fuzzyEq(const CoordinateFrame& other) const; + + bool fuzzyIsIdentity() const; + + bool isIdentity() const; + + /** + Initializes to the identity coordinate frame. + */ + CoordinateFrame(); + + CoordinateFrame(const Vector3& _translation) : + rotation(Matrix3::identity()), translation(_translation) { + } + + CoordinateFrame(const Matrix3 &rotation, const Vector3 &translation) : + rotation(rotation), translation(translation) { + } + + CoordinateFrame(const Matrix3 &rotation) : + rotation(rotation), translation(Vector3::zero()) { + } + + CoordinateFrame(const class UprightFrame& f); + + static CoordinateFrame fromXYZYPRRadians(float x, float y, float z, float yaw = 0.0f, float pitch = 0.0f, float roll = 0.0f); + + /** Construct a coordinate frame from translation = (x,y,z) and + rotations (in that order) about Y, object space X, object space + Z. Note that because object-space axes are used, these are not + equivalent to Euler angles; they are known as Tait-Bryan + rotations and are more convenient for intuitive positioning.*/ + static CoordinateFrame fromXYZYPRDegrees(float x, float y, float z, float yaw = 0.0f, float pitch = 0.0f, float roll = 0.0f); + + CoordinateFrame(class BinaryInput& b); + + void deserialize(class BinaryInput& b); + + void serialize(class BinaryOutput& b) const; + + CoordinateFrame(const CoordinateFrame &other) : + rotation(other.rotation), translation(other.translation) {} + + /** + Computes the inverse of this coordinate frame. + */ + inline CoordinateFrame inverse() const { + CoordinateFrame out; + out.rotation = rotation.transpose(); + out.translation = -out.rotation * translation; + return out; + } + + inline ~CoordinateFrame() {} + + /** See also Matrix4::approxCoordinateFrame */ + class Matrix4 toMatrix4() const; + + void getXYZYPRRadians(float& x, float& y, float& z, float& yaw, float& pitch, float& roll) const; + void getXYZYPRDegrees(float& x, float& y, float& z, float& yaw, float& pitch, float& roll) const; + + + /** + Produces an XML serialization of this coordinate frame. + @deprecated + */ + std::string toXML() const; + + /** + Returns the heading of the lookVector as an angle in radians relative to + the world -z axis. That is, a counter-clockwise heading where north (-z) + is 0 and west (-x) is PI/2. + + Note that the heading ignores the Y axis, so an inverted + object has an inverted heading. + */ + inline float getHeading() const { + Vector3 look = rotation.column(2); + float angle = -(float) atan2(-look.x, look.z); + return angle; + } + + /** + Takes the coordinate frame into object space. + this->inverse() * c + */ + inline CoordinateFrame toObjectSpace(const CoordinateFrame& c) const { + return this->inverse() * c; + } + + inline Vector4 toObjectSpace(const Vector4& v) const { + return this->inverse().toWorldSpace(v); + } + + inline Vector4 toWorldSpace(const Vector4& v) const { + return Vector4(rotation * Vector3(v.x, v.y, v.z) + translation * v.w, v.w); + } + + /** + Transforms the point into world space. + */ + inline Vector3 pointToWorldSpace(const Vector3& v) const { + return Vector3( + rotation[0][0] * v[0] + rotation[0][1] * v[1] + rotation[0][2] * v[2] + translation[0], + rotation[1][0] * v[0] + rotation[1][1] * v[1] + rotation[1][2] * v[2] + translation[1], + rotation[2][0] * v[0] + rotation[2][1] * v[1] + rotation[2][2] * v[2] + translation[2]); + } + + /** + Transforms the point into object space. Assumes that the rotation matrix is orthonormal. + */ + inline Vector3 pointToObjectSpace(const Vector3& v) const { + float p[3]; + p[0] = v[0] - translation[0]; + p[1] = v[1] - translation[1]; + p[2] = v[2] - translation[2]; + debugAssert(G3D::fuzzyEq(rotation.determinant(), 1.0f)); + return Vector3( + rotation[0][0] * p[0] + rotation[1][0] * p[1] + rotation[2][0] * p[2], + rotation[0][1] * p[0] + rotation[1][1] * p[1] + rotation[2][1] * p[2], + rotation[0][2] * p[0] + rotation[1][2] * p[1] + rotation[2][2] * p[2]); + } + + /** + Transforms the vector into world space (no translation). + */ + inline Vector3 vectorToWorldSpace(const Vector3& v) const { + return rotation * v; + } + + inline Vector3 normalToWorldSpace(const Vector3& v) const { + return rotation * v; + } + + class Ray toObjectSpace(const Ray& r) const; + + Ray toWorldSpace(const Ray& r) const; + + /** + Transforms the vector into object space (no translation). + */ + inline Vector3 vectorToObjectSpace(const Vector3 &v) const { + // Multiply on the left (same as rotation.transpose() * v) + return v * rotation; + } + + inline Vector3 normalToObjectSpace(const Vector3 &v) const { + // Multiply on the left (same as rotation.transpose() * v) + return v * rotation; + } + + void pointToWorldSpace(const Array& v, Array& vout) const; + + void normalToWorldSpace(const Array& v, Array& vout) const; + + void vectorToWorldSpace(const Array& v, Array& vout) const; + + void pointToObjectSpace(const Array& v, Array& vout) const; + + void normalToObjectSpace(const Array& v, Array& vout) const; + + void vectorToObjectSpace(const Array& v, Array& vout) const; + + class Box toWorldSpace(const class AABox& b) const; + + class Box toWorldSpace(const class Box& b) const; + + class Cylinder toWorldSpace(const class Cylinder& b) const; + + class Capsule toWorldSpace(const class Capsule& b) const; + + class Plane toWorldSpace(const class Plane& p) const; + + class Sphere toWorldSpace(const class Sphere& b) const; + + class Triangle toWorldSpace(const class Triangle& t) const; + + class Box toObjectSpace(const AABox& b) const; + + class Box toObjectSpace(const Box& b) const; + + class Plane toObjectSpace(const Plane& p) const; + + class Sphere toObjectSpace(const Sphere& b) const; + + Triangle toObjectSpace(const Triangle& t) const; + + /** Compose: create the transformation that is other followed by this.*/ + CoordinateFrame operator*(const CoordinateFrame &other) const { + return CoordinateFrame(rotation * other.rotation, + pointToWorldSpace(other.translation)); + } + + CoordinateFrame operator+(const Vector3& v) const { + return CoordinateFrame(rotation, translation + v); + } + + CoordinateFrame operator-(const Vector3& v) const { + return CoordinateFrame(rotation, translation - v); + } + + void lookAt(const Vector3& target); + + void lookAt( + const Vector3& target, + Vector3 up); + + /** The direction this camera is looking (its negative z axis)*/ + inline Vector3 lookVector() const { + return -rotation.column(2); + } + + /** Returns the ray starting at the camera origin travelling in direction CoordinateFrame::lookVector. */ + class Ray lookRay() const; + + /** Up direction for this camera (its y axis). */ + inline Vector3 upVector() const { + return rotation.column(1); + } + + inline Vector3 rightVector() const { + return rotation.column(0); + } + + /** + If a viewer looks along the look vector, this is the viewer's "left". + Useful for strafing motions and building alternative coordinate frames. + */ + inline Vector3 leftVector() const { + return -rotation.column(0); + } + + /** + Linearly interpolates between two coordinate frames, using + Quat::slerp for the rotations. + */ + CoordinateFrame lerp( + const CoordinateFrame& other, + float alpha) const; + +}; + +typedef CoordinateFrame CFrame; + +} // namespace + +#endif diff --git a/externals/g3dlite/G3D/Crypto.h b/externals/g3dlite/G3D/Crypto.h new file mode 100644 index 00000000000..56c816a4977 --- /dev/null +++ b/externals/g3dlite/G3D/Crypto.h @@ -0,0 +1,96 @@ +/** + @file Crypto.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + + @created 2006-03-29 + @edited 2006-04-06 + */ + +#ifndef G3D_CRYPTO_H +#define G3D_CRYPTO_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include + +namespace G3D { + +/** See G3D::Crypto::md5 */ +class MD5Hash { +private: + + uint8 value[16]; + +public: + + MD5Hash() { + for (int i = 0; i < 16; ++i) { + value[i] = 0; + } + } + + explicit MD5Hash(class BinaryInput& b); + + uint8& operator[](int i) { + return value[i]; + } + + const uint8& operator[](int i) const { + return value[i]; + } + + bool operator==(const MD5Hash& other) const { + bool match = true; + for (int i = 0; i < 16; ++i) { + match = match && (other.value[i] == value[i]); + } + return match; + } + + inline bool operator!=(const MD5Hash& other) const { + return !(*this == other); + } + + void deserialize(class BinaryInput& b); + + void serialize(class BinaryOutput& b) const; +}; + + +/** Cryptography and hashing helper functions */ +class Crypto { +public: + + /** + Computes the CRC32 value of a byte array. CRC32 is designed to be a hash + function that produces different values for similar strings. + + This implementation is compatible with PKZIP and GZIP. + + Based on http://www.gamedev.net/reference/programming/features/crc32/ + */ + static uint32 crc32(const void* bytes, size_t numBytes); + + /** + Computes the MD5 hash (message digest) of a byte stream, as defined by + http://www.ietf.org/rfc/rfc1321.txt. + + @cite Based on implementation by L. Peter Deutsch, ghost@aladdin.com + */ + MD5Hash md5(const void* bytes, size_t numBytes); + + /** + Returns the nth prime less than 2000 in constant time. The first prime has index + 0 and is the number 2. + */ + static int smallPrime(int n); + + /** Returns 1 + the largest value that can be passed to smallPrime. */ + static int numSmallPrimes(); +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/Cylinder.h b/externals/g3dlite/G3D/Cylinder.h new file mode 100644 index 00000000000..85eba77b794 --- /dev/null +++ b/externals/g3dlite/G3D/Cylinder.h @@ -0,0 +1,92 @@ +/** + @file Cylinder.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2003-02-07 + @edited 2005-09-26 + + Copyright 2000-2005, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_Cylinder_H +#define G3D_Cylinder_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Vector3.h" + +namespace G3D { + +class Line; +class AABox; +/** + Right cylinder + */ +class Cylinder { +private: + Vector3 p1; + Vector3 p2; + + float mRadius; + +public: + + /** Uninitialized */ + Cylinder(); + Cylinder(class BinaryInput& b); + Cylinder(const Vector3& _p1, const Vector3& _p2, float _r); + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + + /** The line down the center of the Cylinder */ + Line axis() const; + + /** + A reference frame in which the center of mass is at the origin and + the Y-axis is the cylinder's axis. If the cylinder is transformed, this reference frame + may freely rotate around its axis.*/ + void getReferenceFrame(class CoordinateFrame& cframe) const; + + /** Returns point 0 or 1 */ + inline const Vector3& point(int i) const { + debugAssert(i >= 0 && i <= 1); + return (i == 0) ? p1 : p2; + } + + /** + Returns true if the point is inside the Cylinder or on its surface. + */ + bool contains(const Vector3& p) const; + + float area() const; + + float volume() const; + + float radius() const; + + /** Center of mass */ + inline Vector3 center() const { + return (p1 + p2) / 2.0f; + } + + inline float height() const { + return (p1 - p2).magnitude(); + } + + /** + Get close axis aligned bounding box. + With vertical world orientation, the top and bottom might not be very tight. */ + void getBounds(AABox& out) const; + + /** Random world space point with outward facing normal. */ + void getRandomSurfacePoint(Vector3& P, Vector3& N) const; + + /** Point selected uniformly at random over the volume. */ + Vector3 randomInteriorPoint() const; +}; + +} // namespace + +#endif diff --git a/externals/g3dlite/G3D/EqualsTrait.h b/externals/g3dlite/G3D/EqualsTrait.h new file mode 100644 index 00000000000..349cb5088fb --- /dev/null +++ b/externals/g3dlite/G3D/EqualsTrait.h @@ -0,0 +1,26 @@ +/** + @file EqualsTrait.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @created 2008-10-01 + @edited 2008-10-01 + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_EQUALSTRAIT_H +#define G3D_EQUALSTRAIT_H + +#include "G3D/platform.h" + +/** Default implementation of EqualsTrait. + @see G3D::Table for specialization requirements. +*/ +template struct EqualsTrait { + static bool equals(const Key& a, const Key& b) { + return a == b; + } +}; + +#endif + diff --git a/externals/g3dlite/G3D/G3D.h b/externals/g3dlite/G3D/G3D.h new file mode 100644 index 00000000000..5b56b9c71dc --- /dev/null +++ b/externals/g3dlite/G3D/G3D.h @@ -0,0 +1,162 @@ +/** + @file G3D.h + + This header includes all of the G3D libraries in + appropriate namespaces. + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2001-08-25 + @edited 2010-01-30 + + Copyright 2000-2010, Morgan McGuire. + All rights reserved. +*/ + +#ifndef G3D_G3D_h +#define G3D_G3D_h + +#define NOMINMAX 1 +#ifdef min + #undef min +#endif +#ifdef max + #undef max +#endif + +#include "G3D/platform.h" +#include "G3D/units.h" +#include "G3D/ParseError.h" +#include "G3D/Random.h" +#include "G3D/Array.h" +#include "G3D/SmallArray.h" +#include "G3D/Queue.h" +#include "G3D/Crypto.h" +#include "G3D/format.h" +#include "G3D/Vector2.h" +#include "G3D/Vector3.h" +#include "G3D/Vector4.h" +#include "G3D/Color1.h" +#include "G3D/Color3.h" +#include "G3D/Color4.h" +#include "G3D/Matrix2.h" +#include "G3D/Matrix3.h" +#include "G3D/Matrix4.h" +#include "G3D/CoordinateFrame.h" +#include "G3D/PhysicsFrame.h" +#include "G3D/Plane.h" +#include "G3D/Line.h" +#include "G3D/Ray.h" +#include "G3D/Sphere.h" +#include "G3D/Box.h" +#include "G3D/Box2D.h" +#include "G3D/AABox.h" +#include "G3D/WrapMode.h" +#include "G3D/Cone.h" +#include "G3D/Quat.h" +#include "G3D/stringutils.h" +#include "G3D/prompt.h" +#include "G3D/Table.h" +#include "G3D/Set.h" +#include "G3D/GUniqueID.h" +#include "G3D/BinaryFormat.h" +#include "G3D/BinaryInput.h" +#include "G3D/BinaryOutput.h" +#include "G3D/debug.h" +#include "G3D/g3dfnmatch.h" +#include "G3D/G3DGameUnits.h" +#include "G3D/g3dmath.h" +#include "G3D/uint128.h" +#include "G3D/fileutils.h" +#include "G3D/ReferenceCount.h" +#include "G3D/Welder.h" +#include "G3D/GMutex.h" +#include "G3D/PrecomputedRandom.h" +#include "G3D/MemoryManager.h" +#include "G3D/AreaMemoryManager.h" +#include "G3D/BumpMapPreprocess.h" + +template struct HashTrait< G3D::ReferenceCountedPointer > { + static size_t hashCode(G3D::ReferenceCountedPointer key) { return reinterpret_cast( key.pointer() ); } +}; + +#include "G3D/GImage.h" +#include "G3D/CollisionDetection.h" +#include "G3D/Intersect.h" +#include "G3D/Log.h" +#include "G3D/serialize.h" +#include "G3D/TextInput.h" +#include "G3D/NetAddress.h" +#include "G3D/NetworkDevice.h" +#include "G3D/System.h" +#include "G3D/splinefunc.h" +#include "G3D/Spline.h" +#include "G3D/UprightFrame.h" +#include "G3D/LineSegment.h" +#include "G3D/Capsule.h" +#include "G3D/Cylinder.h" +#include "G3D/Triangle.h" +#include "G3D/Color3uint8.h" +#include "G3D/Color4uint8.h" +#include "G3D/Vector2int16.h" +#include "G3D/Vector3int16.h" +#include "G3D/Vector3int32.h" +#include "G3D/Vector4int8.h" +#include "G3D/ConvexPolyhedron.h" +#include "G3D/MeshAlg.h" +#include "G3D/vectorMath.h" +#include "G3D/Rect2D.h" +#include "G3D/GCamera.h" +#include "G3D/GLight.h" +#include "G3D/KDTree.h" +#include "G3D/PointKDTree.h" +#include "G3D/TextOutput.h" +#include "G3D/MeshBuilder.h" +#include "G3D/Stopwatch.h" +#include "G3D/AtomicInt32.h" +#include "G3D/GThread.h" +#include "G3D/ThreadSet.h" +#include "G3D/RegistryUtil.h" +#include "G3D/Any.h" +#include "G3D/PointHashGrid.h" +#include "G3D/Map2D.h" +#include "G3D/Image1.h" +#include "G3D/Image1uint8.h" +#include "G3D/Image3.h" +#include "G3D/Image3uint8.h" +#include "G3D/Image4.h" +#include "G3D/Image4uint8.h" +#include "G3D/filter.h" +#include "G3D/WeakCache.h" +#include "G3D/Pointer.h" +#include "G3D/Matrix.h" +#include "G3D/ImageFormat.h" + +#ifdef _MSC_VER +# pragma comment(lib, "zlib") +# pragma comment(lib, "ws2_32") +# pragma comment(lib, "winmm") +# pragma comment(lib, "imagehlp") +# pragma comment(lib, "gdi32") +# pragma comment(lib, "user32") +# pragma comment(lib, "kernel32") +# pragma comment(lib, "version") +# pragma comment(lib, "advapi32") +# pragma comment(lib, "png") +# pragma comment(lib, "jpeg") +# pragma comment(lib, "zip") +# ifdef _DEBUG + // Don't link against G3D when building G3D itself. +# ifndef G3D_BUILDING_LIBRARY_DLL +# pragma comment(lib, "G3Dd.lib") +# endif +# else + // Don't link against G3D when building G3D itself. +# ifndef G3D_BUILDING_LIBRARY_DLL +# pragma comment(lib, "G3D.lib") +# endif +# endif +#endif + +#endif + diff --git a/externals/g3dlite/G3D/G3DAll.h b/externals/g3dlite/G3D/G3DAll.h new file mode 100644 index 00000000000..1176fe742e7 --- /dev/null +++ b/externals/g3dlite/G3D/G3DAll.h @@ -0,0 +1,26 @@ +/** + @file G3DAll.h + + Includes all G3D and GLG3D files and uses the G3D namespace. + + This requires OpenGL and SDL headers. If you don't want all of this, + \#include separately. + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2002-01-01 + @edited 2006-08-13 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_G3DALL_H +#define G3D_G3DALL_H + +#include "G3D/G3D.h" +#include "GLG3D/GLG3D.h" + +using namespace G3D; + +#endif diff --git a/externals/g3dlite/G3D/G3DGameUnits.h b/externals/g3dlite/G3D/G3DGameUnits.h new file mode 100644 index 00000000000..e2bc2c811e8 --- /dev/null +++ b/externals/g3dlite/G3D/G3DGameUnits.h @@ -0,0 +1,42 @@ +/** + @file G3DGameUnits.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @created 2002-10-05 + @edited 2006-11-10 + */ + +#ifndef G3D_GAMEUNITS_H +#define G3D_GAMEUNITS_H + +#include "G3D/platform.h" + +namespace G3D { +/** + Time, in seconds. + */ +typedef double GameTime; +typedef double SimTime; + +/** + Actual wall clock time in seconds. + */ +typedef double RealTime; + +enum AMPM {AM, PM}; + +/** \deprecated */ +enum {SECOND=1, MINUTE=60, HOUR = 60*60, DAY=24*60*60, SUNRISE=24*60*60/4, SUNSET=24*60*60*3/4, MIDNIGHT=0, METER=1, KILOMETER=1000}; + +/** + Converts a 12 hour clock time into the number of seconds since + midnight. Note that 12:00 PM is noon and 12:00 AM is midnight. + + Example: toSeconds(10, 00, AM) + */ +SimTime toSeconds(int hour, int minute, double seconds, AMPM ap); +SimTime toSeconds(int hour, int minute, AMPM ap); + +} + +#endif diff --git a/externals/g3dlite/G3D/GCamera.h b/externals/g3dlite/G3D/GCamera.h new file mode 100644 index 00000000000..018fbc85d59 --- /dev/null +++ b/externals/g3dlite/G3D/GCamera.h @@ -0,0 +1,337 @@ +/** + @file GCamera.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2005-07-20 + @edited 2009-04-20 +*/ + +#ifndef G3D_GCamera_H +#define G3D_GCamera_H + +#include "G3D/platform.h" +#include "G3D/CoordinateFrame.h" +#include "G3D/Vector3.h" +#include "G3D/Plane.h" +#include "G3D/debugAssert.h" + +namespace G3D { + +class Matrix4; +class Rect2D; +class Any; + +/** + Abstraction of a pinhole camera. + + The area a camera sees is called a frustum. It is bounded by the + near plane, the far plane, and the sides of the view frame projected + into the scene. It has the shape of a pyramid with the top cut off. + + Cameras can project points from 3D to 2D. The "unit" projection + matches OpenGL. It maps the entire view frustum to a cube of unit + radius (i.e., edges of length 2) centered at the origin. The + non-unit projection then maps that cube to the specified pixel + viewport in X and Y and the range [0, 1] in Z. The projection is + reversable as long as the projected Z value is known. + + All viewport arguments are the pixel bounds of the viewport-- e.g., + RenderDevice::viewport(). + */ +class GCamera { + +public: + /** + Stores the direction of the field of view + */ + enum FOVDirection {HORIZONTAL, VERTICAL}; + +private: + + /** Full field of view (in radians) */ + float m_fieldOfView; + + /** Clipping plane, *not* imaging plane. Negative numbers. */ + float m_nearPlaneZ; + + /** Negative */ + float m_farPlaneZ; + + /** Stores the camera's location and orientation */ + CoordinateFrame m_cframe; + + /** Horizontal or Vertical */ + FOVDirection m_direction; + +public: + + /** Must be of the format produced by the Any cast, e.g., + +
+        GCamera {
+            coordinateFrame = CFrame::fromXYZYPRDegrees(-13.3f, 8.0f, -1.9f, 246.6f, -3),
+            nearPlaneZ = -0.5,
+            farPlaneZ = -50,
+            fovDirection = "HORIZONTAL",
+            fovAngleDegrees = 90
+        }
+ + Missing fields are filled from the default GCamera constructor. + */ + GCamera(const Any& any); + + operator Any() const; + + class Frustum { + public: + class Face { + public: + /** Counter clockwise indices into vertexPos */ + int vertexIndex[4]; + + /** The plane containing the face. */ + Plane plane; + }; + + /** The vertices, in homogeneous space. If w == 0, + a vertex is at infinity. */ + Array vertexPos; + + /** The faces in the frustum. When the + far plane is at infinity, there are 5 faces, + otherwise there are 6. The faces are in the order + N,R,L,B,T,[F]. + */ + Array faceArray; + }; + + GCamera(); + + GCamera(const Matrix4& proj, const CFrame& frame); + + virtual ~GCamera(); + + /** Returns the current coordinate frame */ + const CoordinateFrame& coordinateFrame() const { + return m_cframe; + } + + /** Sets c to the camera's coordinate frame */ + void getCoordinateFrame(CoordinateFrame& c) const; + + /** Sets a new coordinate frame for the camera */ + void setCoordinateFrame(const CoordinateFrame& c); + + /** Sets \a P equal to the camera's projection matrix. This is the + matrix that maps points to the homogeneous clip cube that + varies from -1 to 1 on all axes. The projection matrix does + not include the camera transform. + + This is the matrix that a RenderDevice (or OpenGL) uses as the projection matrix. + @sa RenderDevice::setProjectionAndCameraMatrix, RenderDevice::setProjectionMatrix, Matrix4::perspectiveProjection + */ + void getProjectUnitMatrix(const Rect2D& viewport, Matrix4& P) const; + + /** Sets \a P equal to the matrix that transforms points to pixel + coordinates on the given viewport. A point correspoinding to + the top-left corner of the viewport in camera space will + transform to viewport.x0y0() and the bottom-right to viewport.x1y1(). */ + void getProjectPixelMatrix(const Rect2D& viewport, Matrix4& P) const; + + /** Converts projected points from OpenGL standards + (-1, 1) to normal 3D coordinate standards (0, 1) + + \deprecated + */ // TODO: Remove + Vector3 convertFromUnitToNormal(const Vector3& in, const Rect2D& viewport) const; + + /** + Sets the field of view, in radians. The + initial angle is toRadians(55). Must specify + the direction of the angle. + + This is the full angle, i.e., from the left side of the + viewport to the right side. + */ + void setFieldOfView(float angle, FOVDirection direction); + + /** Returns the current full field of view angle (from the left side of the + viewport to the right side) and direction */ + inline void getFieldOfView(float& angle, FOVDirection& direction) const { + angle = m_fieldOfView; + direction = m_direction; + } + + /** + Projects a world space point onto a width x height screen. The + returned coordinate uses pixmap addressing: x = right and y = + down. The resulting z value is 0 at the near plane, 1 at the far plane, + and is a linear compression of unit cube projection. + + If the point is behind the camera, Vector3::inf() is returned. + */ + Vector3 project(const G3D::Vector3& point, + const class Rect2D& viewport) const; + + /** + Projects a world space point onto a unit cube. The resulting + x,y,z values range between -1 and 1, where z is -1 + at the near plane and 1 at the far plane and varies hyperbolically in between. + + If the point is behind the camera, Vector3::inf() is returned. + */ + Vector3 projectUnit(const G3D::Vector3& point, + const class Rect2D& viewport) const; + + /** + Gives the world-space coordinates of screen space point v, where + v.x is in pixels from the left, v.y is in pixels from + the top, and v.z is on the range 0 (near plane) to 1 (far plane). + */ + Vector3 unproject(const Vector3& v, const Rect2D& viewport) const; + + /** + Gives the world-space coordinates of unit cube point v, where + v varies from -1 to 1 on all axes. The unproject first + transforms the point into a pixel location for the viewport, then calls unproject + */ + Vector3 unprojectUnit(const Vector3& v, const Rect2D& viewport) const; + + /** + Returns the pixel area covered by a shape of the given + world space area at the given z value (z must be negative). + */ + float worldToScreenSpaceArea(float area, float z, const class Rect2D& viewport) const; + + /** + Returns the world space 3D viewport corners. These + are at the near clipping plane. The corners are constructed + from the nearPlaneZ, viewportWidth, and viewportHeight. + "left" and "right" are from the GCamera's perspective. + */ + void getNearViewportCorners(const class Rect2D& viewport, + Vector3& outUR, Vector3& outUL, + Vector3& outLL, Vector3& outLR) const; + + /** + Returns the world space 3D viewport corners. These + are at the Far clipping plane. The corners are constructed + from the nearPlaneZ, farPlaneZ, viewportWidth, and viewportHeight. + "left" and "right" are from the GCamera's perspective. + */ + void getFarViewportCorners(const class Rect2D& viewport, + Vector3& outUR, Vector3& outUL, + Vector3& outLL, Vector3& outLR) const; + + /** + Returns the image plane depth, assumes imagePlane + is the same as the near clipping plane. + returns a positive number. + */ + float imagePlaneDepth() const; + + /** + Returns the world space ray passing through the center of pixel + (x, y) on the image plane. The pixel x and y axes are opposite + the 3D object space axes: (0,0) is the upper left corner of the screen. + They are in viewport coordinates, not screen coordinates. + + The ray origin is at the origin. To start it at the image plane, + move it forward by imagePlaneDepth/ray.direction.z + + Integer (x, y) values correspond to + the upper left corners of pixels. If you want to cast rays + through pixel centers, add 0.5 to x and y. + */ + Ray worldRay( + float x, + float y, + const class Rect2D& viewport) const; + + /** + Returns a negative z-value. + */ + inline float nearPlaneZ() const { + return m_nearPlaneZ; + } + + /** + Returns a negative z-value. + */ + inline float farPlaneZ() const { + return m_farPlaneZ; + } + + /** + Sets a new value for the far clipping plane + Expects a negative value + */ + inline void setFarPlaneZ(float z) { + debugAssert(z < 0); + m_farPlaneZ = z; + } + + /** + Sets a new value for the near clipping plane + Expects a negative value + */ + inline void setNearPlaneZ(float z) { + debugAssert(z < 0); + m_nearPlaneZ = z; + } + + /** + Returns the camera space width of the viewport at the near plane. + */ + float viewportWidth(const class Rect2D& viewport) const; + + /** + Returns the camera space height of the viewport at the near plane. + */ + float viewportHeight(const class Rect2D& viewport) const; + + void setPosition(const Vector3& t); + + /** Rotate the camera in place to look at the target. Does not + persistently look at that location when the camera moves; + i.e., if you move the camera and still want it to look at the + old target, you must call lookAt again after moving the + camera.)*/ + void lookAt(const Vector3& position, const Vector3& up = Vector3::unitY()); + + /** + Returns the clipping planes of the frustum, in world space. + The planes have normals facing into the view frustum. + + The plane order is guaranteed to be: + Near, Right, Left, Top, Bottom, [Far] + + If the far plane is at infinity, the resulting array will have + 5 planes, otherwise there will be 6. + + The viewport is used only to determine the aspect ratio of the screen; the + absolute dimensions and xy values don't matter. + */ + void getClipPlanes + ( + const Rect2D& viewport, + Array& outClip) const; + + /** + Returns the world space view frustum, which is a truncated pyramid describing + the volume of space seen by this camera. + */ + void frustum(const Rect2D& viewport, GCamera::Frustum& f) const; + + GCamera::Frustum frustum(const Rect2D& viewport) const; + + /** Read and Write camera parameters */ + void serialize(class BinaryOutput& bo) const; + void deserialize(class BinaryInput& bi); + +}; + +} // namespace G3D + +#endif diff --git a/externals/g3dlite/G3D/GImage.h b/externals/g3dlite/G3D/GImage.h new file mode 100644 index 00000000000..8ae11134fc9 --- /dev/null +++ b/externals/g3dlite/G3D/GImage.h @@ -0,0 +1,607 @@ +/** + \file GImage.h + + See G3D::GImage for details. + + @cite JPEG compress/decompressor is the IJG library, used in accordance with their license. + @cite JPG code by John Chisholm, using the IJG Library + @cite TGA code by Morgan McGuire + @cite BMP code by John Chisholm, based on code by Edward "CGameProgrammer" Resnick mailto:cgp@gdnmail.net at ftp://ftp.flipcode.com/cotd/LoadPicture.txt + @cite PCX format described in the ZSOFT PCX manual http://www.nist.fss.ru/hr/doc/spec/pcx.htm#2 + @cite PNG compress/decompressor is the libpng library, used in accordance with their license. + @cite PPM code by Morgan McGuire based on http://netpbm.sourceforge.net/doc/ppm.html + + \maintainer Morgan McGuire, http://graphics.cs.williams.edu + + \created 2002-05-27 + \edited 2010-01-04 + + Copyright 2000-2010, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_GImage_h +#define G3D_GImage_h + +#include "G3D/platform.h" +#include +#include "G3D/Array.h" +#include "G3D/g3dmath.h" +#include "G3D/stringutils.h" +#include "G3D/Color1uint8.h" +#include "G3D/Color3uint8.h" +#include "G3D/Color4uint8.h" +#include "G3D/MemoryManager.h" +#include "G3D/BumpMapPreprocess.h" + +namespace G3D { +class BinaryInput; +class BinaryOutput; + + +/** + Interface to image compression & file formats. + + Supported formats (decode and encode): Color JPEG, PNG, + (Uncompressed)TGA 24, (Uncompressed)TGA 32, BMP 1, BMP 4, BMP 8, BMP + 24, PPM (P6), and PPM ASCII (P1, P2, P3), which includes PPM, PGM, + and PBM. 8-bit paletted PCX, 24-bit PCX, and ICO are supported for + decoding only. + + Sample usage: + + \verbatim + // Loading from disk: + G3D::GImage im1("test.jpg"); + + // Loading from memory: + G3D::GImage im2(data, length); + + // im.pixel is a pointer to RGB color data. If you want + // an alpha channel, call RGBtoRGBA or RGBtoARGB for + // conversion. + + // Saving to memory: + G3D::GImage im3(width, height); + // (Set the pixels of im3...) + uint8* data2; + int len2; + im3.encode(G3D::GImage::JPEG, data2, len2); + + // Saving to disk + im3.save("out.jpg"); + \endverbatim + + The free Image Magick Magick Wand API + (http://www.imagemagick.org/www/api/magick_wand.html) provides a more powerful + API for image manipulation and wider set of image load/save formats. It is + recommended over GImage (we don't include it directly in G3D because their license + is more restrictive than the BSD one). + + */ +class GImage { +private: + + /** Used exclusively for allocating m_byte; this may be an + implementation that allocates directly on a GPU.*/ + MemoryManager::Ref m_memMan; + uint8* m_byte; + + int m_channels; + int m_width; + int m_height; + +public: + + class Error { + public: + Error( + const std::string& reason, + const std::string& filename = "") : + reason(reason), filename(filename) {} + + std::string reason; + std::string filename; + }; + + /** PGM, PPM, and PBM all come in two versions and are classified as PPM_* files */ + enum Format {JPEG, BMP, TGA, PCX, ICO, PNG, + PPM_BINARY, PGM_BINARY = PPM_BINARY, + PPM_ASCII, PGM_ASCII = PPM_ASCII, + AUTODETECT, UNKNOWN}; + + + /** + The number of channels; either 3 (RGB) or 4 (RGBA) + */ + inline int channels() const { + return m_channels; + } + + inline int width() const { + return m_width; + } + + inline int height() const { + return m_height; + } + + inline const uint8* byte() const { + return m_byte; + } + + /** Returns a pointer to the underlying data, which is stored + in row-major order without row padding. + e.g., uint8* ptr = image.rawData(); + */ + template + inline const Type* rawData() const { + return (Type*)m_byte; + } + + /** \copybrief GImage::rawData() const */ + template + inline Type* rawData() { + return (Type*)m_byte; + } + + inline const Color1uint8* pixel1() const { + debugAssertM(m_channels == 1, format("Tried to call GImage::pixel1 on an image with %d channels", m_channels)); + return (Color1uint8*)m_byte; + } + + inline Color1uint8* pixel1() { + debugAssertM(m_channels == 1, format("Tried to call GImage::pixel1 on an image with %d channels", m_channels)); + return (Color1uint8*)m_byte; + } + + /** Returns a pointer to the upper left pixel + as Color4uint8. + */ + inline const Color4uint8* pixel4() const { + debugAssertM(m_channels == 4, format("Tried to call GImage::pixel4 on an image with %d channels", m_channels)); + return (Color4uint8*)m_byte; + } + + inline Color4uint8* pixel4() { + debugAssert(m_channels == 4); + return (Color4uint8*)m_byte; + } + + /** Returns a pointer to the upper left pixel + as Color3uint8. + */ + inline const Color3uint8* pixel3() const { + debugAssertM(m_channels == 3, format("Tried to call GImage::pixel3 on an image with %d channels", m_channels)); + return (Color3uint8*)m_byte; + } + + inline Color3uint8* pixel3() { + debugAssert(m_channels == 3); + return (Color3uint8*)m_byte; + } + + /** Returns the pixel at (x, y), where (0,0) is the upper left. */ + inline const Color1uint8& pixel1(int x, int y) const { + debugAssert(x >= 0 && x < m_width); + debugAssert(y >= 0 && y < m_height); + return pixel1()[x + y * m_width]; + } + + /** Returns the pixel at (x, y), where (0,0) is the upper left. */ + inline Color1uint8& pixel1(int x, int y) { + debugAssert(x >= 0 && x < m_width); + debugAssert(y >= 0 && y < m_height); + return pixel1()[x + y * m_width]; + } + + /** Returns the pixel at (x, y), where (0,0) is the upper left. */ + inline const Color3uint8& pixel3(int x, int y) const { + debugAssert(x >= 0 && x < m_width); + debugAssert(y >= 0 && y < m_height); + return pixel3()[x + y * m_width]; + } + + inline Color3uint8& pixel3(int x, int y) { + debugAssert(x >= 0 && x < m_width); + debugAssert(y >= 0 && y < m_height); + return pixel3()[x + y * m_width]; + } + + /** Returns the pixel at (x, y), where (0,0) is the upper left. */ + inline const Color4uint8& pixel4(int x, int y) const { + debugAssert(x >= 0 && x < m_width); + debugAssert(y >= 0 && y < m_height); + return pixel4()[x + y * m_width]; + } + + inline Color4uint8& pixel4(int x, int y) { + debugAssert(x >= 0 && x < m_width); + debugAssert(y >= 0 && y < m_height); + return pixel4()[x + y * m_width]; + } + + inline uint8* byte() { + return m_byte; + } + +private: + + void encodeBMP( + BinaryOutput& out) const; + + /** + The TGA file will be either 24- or 32-bit depending + on the number of channels. + */ + void encodeTGA( + BinaryOutput& out) const; + + /** + Converts this image into a JPEG + */ + void encodeJPEG( + BinaryOutput& out) const; + + /** + Converts this image into a JPEG + */ + void encodePNG( + BinaryOutput& out) const; + + void encodePPM( + BinaryOutput& out) const; + + void encodePPMASCII( + BinaryOutput& out) const; + + void decodeTGA( + BinaryInput& input); + + void decodeBMP( + BinaryInput& input); + + void decodeJPEG( + BinaryInput& input); + + void decodePCX( + BinaryInput& input); + + void decodeICO( + BinaryInput& input); + + void decodePNG( + BinaryInput& input); + + void decodePPM( + BinaryInput& input); + + void decodePPMASCII( + BinaryInput& input); + + /** + Given [maybe] a filename, memory buffer, and [maybe] a format, + returns the most likely format of this file. + */ + static Format resolveFormat( + const std::string& filename, + const uint8* data, + int dataLen, + Format maybeFormat); + + void _copy( + const GImage& other); + +public: + + /** Predicts the image file format of \a filename */ + static Format resolveFormat(const std::string& filename); + + void flipHorizontal(); + void flipVertical(); + void rotate90CW(int numTimes = 1); + + /** + Create an empty image of the given size. + \sa load() + */ + GImage( + int width = 0, + int height = 0, + int channels = 3, + const MemoryManager::Ref& m = MemoryManager::create()); + + /** + Load an encoded image from disk and decode it. + Throws GImage::Error if something goes wrong. + */ + GImage( + const std::string& filename, + Format format = AUTODETECT, + const MemoryManager::Ref& m = MemoryManager::create()); + + /** + Decodes an image stored in a buffer. + */ + GImage( + const unsigned char*data, + int length, + Format format = AUTODETECT, + const MemoryManager::Ref& m = MemoryManager::create()); + + GImage( + const GImage& other, + const MemoryManager::Ref& m = MemoryManager::create()); + + GImage& operator=(const GImage& other); + + /** + Returns a new GImage that has 4 channels. RGB is + taken from this GImage and the alpha from the red + channel of the supplied image. The new GImage is passed + as a reference parameter for speed. + */ + void insertRedAsAlpha(const GImage& alpha, GImage& output) const; + + /** + Returns a new GImage with 3 channels, removing + the alpha channel if there is one. The new GImage + is passed as a reference parameter for speed. + */ + void stripAlpha(GImage& output) const; + + /** + Loads an image from disk (clearing the old one first), + using the existing memory manager. + */ + void load( + const std::string& filename, + Format format = AUTODETECT); + + /** + Frees memory and resets to a 0x0 image. + */ + void clear(); + + /** + Deallocates the pixels. + */ + virtual ~GImage(); + + /** + Resizes the internal buffer to (\a width x \a height) with the + number of \a channels specified. + + \param zero If true, all data is set to 0 (black). + */ + void resize(int width, int height, int channels, bool zero = true); + + /** + Copies src sub-image data into dest at a certain offset. + The dest variable must already contain an image that is large + enough to contain the src sub-image at the specified offset. + Returns true on success and false if the src sub-image cannot + completely fit within dest at the specified offset. Both + src and dest must have the same number of channels. + */ + static bool pasteSubImage( + GImage& dest, + const GImage& src, + int destX, + int destY, + int srcX, + int srcY, + int srcWidth, + int srcHeight); + + /** + creates dest from src sub-image data. + Returns true on success and false if the src sub-image + is not within src. + */ + static bool copySubImage(GImage & dest, const GImage & src, + int srcX, int srcY, int srcWidth, int srcHeight); + + void convertToRGBA(); + + void convertToRGB(); + + /** Averages color channels if they exist */ + void convertToL8(); + + /** + Returns true if format is supported. Format + should be an extension string (e.g. "BMP"). + */ + static bool supportedFormat( + const std::string& format); + + /** + Converts a string to an enum, returns UNKNOWN if not recognized. + */ + static Format stringToFormat( + const std::string& format); + + /** + Encode and save to disk. + */ + void save( + const std::string& filename, + Format format = AUTODETECT) const; + + /** + The caller must delete the returned buffer. + TODO: provide a memory manager + */ + void encode( + Format format, + uint8*& outData, + int& outLength) const; + + /** + Does not commit the BinaryOutput when done. + */ + void encode( + Format format, + BinaryOutput& out) const; + + /** + Decodes the buffer into this image. + @param format Must be the correct format. + */ + void decode( + BinaryInput& input, + Format format); + + /** Returns the size of this object in bytes */ + int sizeInMemory() const; + + /** Ok for in == out */ + static void R8G8B8_to_Y8U8V8(int width, int height, const uint8* in, uint8* out); + + /** Ok for in == out */ + static void Y8U8V8_to_R8G8B8(int width, int height, const uint8* in, uint8* out); + + /** + @param in RGB buffer of numPixels * 3 bytes + @param out Buffer of numPixels * 4 bytes + @param numPixels Number of RGB pixels to convert + */ + static void RGBtoRGBA( + const uint8* in, + uint8* out, + int numPixels); + + static void RGBtoARGB( + const uint8* in, + uint8* out, + int numPixels); + + static void LtoRGB + (const uint8* in, + uint8* out, + int numPixels); + + static void LtoRGBA + (const uint8* in, + uint8* out, + int numPixels); + + /** Safe for in == out */ + static void RGBtoBGR( + const uint8* in, + uint8* out, + int numPixels); + + /** + Win32 32-bit HDC format. + */ + static void RGBtoBGRA( + const uint8* in, + uint8* out, + int numPixels); + + static void RGBAtoRGB( + const uint8* in, + uint8* out, + int numPixels); + /** + Uses the red channel of the second image as an alpha channel. + */ + static void RGBxRGBtoRGBA( + const uint8* colorRGB, + const uint8* alphaRGB, + uint8* out, + int numPixels); + + /** + Flips the image along the vertical axis. + Safe for in == out. + */ + static void flipRGBVertical( + const uint8* in, + uint8* out, + int width, + int height); + + static void flipRGBAVertical( + const uint8* in, + uint8* out, + int width, + int height); + + /** + Given a tangent space bump map, computes a new image where the + RGB channels are a tangent space normal map and the alpha channel + is the original bump map. Assumes the input image is tileable. + + In the resulting image, x = red = tangent, y = green = binormal, and z = blue = normal. + + Particularly useful as part of the idiom: +
+ 	    GImage normal;
+	    computeNormalMap(GImage(filename), normal);
+	    return Texture::fromGImage(filename, normal);
+    
+ + */ + static void computeNormalMap( + const class GImage& bump, + class GImage& normal, + const BumpMapPreprocess& preprocess = BumpMapPreprocess()); + + static void computeNormalMap + (int width, + int height, + int channels, + const uint8* src, + GImage& normal, + const BumpMapPreprocess& preprocess = BumpMapPreprocess()); + + /** + Bayer demosaicing using the filter proposed in + + HIGH-QUALITY LINEAR INTERPOLATION FOR DEMOSAICING OF BAYER-PATTERNED COLOR IMAGES + Henrique S. Malvar, Li-wei He, and Ross Cutler + + The filter wraps at the image boundaries. + + Assumes in != out. + */ + static void BAYER_G8B8_R8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out); + static void BAYER_G8R8_B8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out); + static void BAYER_R8G8_G8B8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out); + static void BAYER_B8G8_G8R8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out); + + /** Fast conversion; the output has 1/2 the size of the input in each direction. Assumes in != out. + See G3D::BAYER_G8B8_R8G8_to_R8G8B8_MHC for a much better result. */ + static void BAYER_G8B8_R8G8_to_Quarter_R8G8B8 + (int inWidth, + int inHeight, + const uint8* in, + uint8* out); + + /** Attempt to undo fast conversion of G3D::BAYER_G8B8_R8G8_to_Quarter_R8G8B8; + the green channel will lose data. Assumes in != out + The input should have size 3 * inWidth * inHeight. The output should have size + 2 * inWidth * 2 * inHeight. + */ + static void Quarter_R8G8B8_to_BAYER_G8B8_R8G8 + (int inWidth, + int inHeight, + const uint8* in, + uint8* out); + + /** Overwrites every pixel with one of the two colors in a checkerboard pattern. + The fields used from the two colors depend on the current number of channels in @a im. + */ + static void makeCheckerboard + (GImage& im, + int checkerSize = 1, + const Color4uint8& color1 = Color4uint8(255,255,255,255), + const Color4uint8& color2 = Color4uint8(0,0,0,255)); +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/GLight.h b/externals/g3dlite/G3D/GLight.h new file mode 100644 index 00000000000..3a95f1a8114 --- /dev/null +++ b/externals/g3dlite/G3D/GLight.h @@ -0,0 +1,106 @@ +/** + @file GLight.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2003-11-12 + @edited 2009-11-08 +*/ + +#ifndef G3D_GLight_h +#define G3D_GLight_h + +#include "G3D/platform.h" +#include "G3D/Vector4.h" +#include "G3D/Vector3.h" +#include "G3D/Color4.h" + +namespace G3D { +class Any; + +/** + A light representation that closely follows the OpenGL light format. + */ +class GLight { +public: + /** World space position (for a directional light, w = 0 */ + Vector4 position; + + /** For a spot or directional light, this is the "right vector" that will be used when constructing + a reference frame(). */ + Vector3 rightDirection; + + /** Direction in which the light faces, if a spot light. This is the "look vector" of the light source. */ + Vector3 spotDirection; + + /** In degrees. 180 = no cutoff (point/dir). Values less than 90 = spot light */ + float spotCutoff; + + /** If true, G3D::SuperShader will render a cone of light large + enough to encompass the entire square that bounds the cutoff + angle. This produces a square prism instead of a cone of light + when used with a G3D::ShadowMap. for an unshadowed light this + has no effect.*/ + bool spotSquare; + + /** Constant, linear, quadratic */ + float attenuation[3]; + + /** May be outside the range [0, 1] */ + Color3 color; + + /** If false, this light is ignored */ + bool enabled; + + /** If false, this light does not create specular highlights + (useful when using negative lights). */ + bool specular; + + /** If false, this light does not create diffuse illumination + (useful when rendering a specular-only pass). */ + bool diffuse; + + GLight(); + + /** Accepted forms: + - GLight::directional( vector3, color3, [bool, [bool]]) + - GLight::spot(vector3, vector3, #, color3, [#, [#, [#, [#, [bool, [bool]]]]) + - GLight::point(vector3, color3, [#, [#, [#, [#, [bool, [bool]]]]) + - GLight { [all fields] } + */ + GLight(const Any& any); + + /** Converts the Color3 to an Any. */ + operator Any() const; + + /** @param toLight will be normalized */ + static GLight directional(const Vector3& toLight, const Color3& color, bool specular = true, bool diffuse = true); + + static GLight point(const Vector3& pos, const Color3& color, float constAtt = 1, float linAtt = 0, float quadAtt = 0.5f, bool specular = true, bool diffuse = true); + + /** @param pointDirection Will be normalized. Points in the + direction that light propagates. + + @param cutOffAngleDegrees Must be on the range [0, 90]. This + is the angle from the point direction to the edge of the light + cone. I.e., a value of 45 produces a light with a 90-degree + cone of view. + */ + static GLight spot(const Vector3& pos, const Vector3& pointDirection, float cutOffAngleDegrees, + const Color3& color, float constAtt = 1, float linAtt = 0, float quadAtt = 0, + bool specular = true, bool diffuse = true); + + /** Returns the sphere within which this light has some noticable effect. May be infinite. + @param cutoff The value at which the light intensity is considered negligible. */ + class Sphere effectSphere(float cutoff = 30.0f / 255) const; + + /** Computes a reference frame (e.g., for use with G3D::ShadowMap */ + class CoordinateFrame frame() const; + + bool operator==(const GLight& other) const; + bool operator!=(const GLight& other) const; +}; + +} // namespace +#endif + diff --git a/externals/g3dlite/G3D/GMutex.h b/externals/g3dlite/G3D/GMutex.h new file mode 100644 index 00000000000..3469b812736 --- /dev/null +++ b/externals/g3dlite/G3D/GMutex.h @@ -0,0 +1,123 @@ +/** + @file GMutex.h + + @created 2005-09-22 + @edited 2009-03-25 + */ + +#ifndef G3D_GMutex_h +#define G3D_GMutex_h + +#include "G3D/platform.h" +#include "G3D/AtomicInt32.h" +#include "G3D/debugAssert.h" +#include + +#ifndef G3D_WIN32 +# include +# include +#endif + + +namespace G3D { + +/** + \brief A mutual exclusion lock that busy-waits when locking. + + On a machine with one (significant) thread per processor core, + a spinlock may be substantially faster than a mutex. + + \sa G3D::GThread, G3D::GMutex, G3D::AtomicInt32 + */ +class Spinlock { +private: + + AtomicInt32 x; + +public: + + inline Spinlock() : x(0) {} + + /** Busy waits until the lock is unlocked, then locks it + exclusively. Returns true if the lock succeeded on the first + try (indicating no contention). */ + inline bool lock() { + bool first = true; + while (x.compareAndSet(0, 1) == 1) { + first = false; +# ifdef G3D_WIN32 + Sleep(0); +# else + usleep(0); +# endif + } + return first; + } + + inline void unlock() { + x.compareAndSet(1, 0); + } + +}; + +/** + \brief Mutual exclusion lock used for synchronization. + + @sa G3D::GThread, G3D::AtomicInt32, G3D::Spinlock +*/ +class GMutex { +private: +# ifdef G3D_WIN32 + CRITICAL_SECTION m_handle; +# else + pthread_mutex_t m_handle; + pthread_mutexattr_t m_attr; +# endif + + // Not implemented on purpose, don't use + GMutex(const GMutex &mlock); + GMutex &operator=(const GMutex &); + bool operator==(const GMutex&); + +public: + GMutex(); + ~GMutex(); + + /** Locks the mutex or blocks until available. */ + void lock(); + + /** Locks the mutex if it not already locked. + Returns true if lock successful, false otherwise. */ + bool tryLock(); + + /** Unlocks the mutex. */ + void unlock(); +}; + + +/** + Automatically locks while in scope. +*/ +class GMutexLock { +private: + GMutex* m; + + // Not implemented on purpose, don't use + GMutexLock(const GMutexLock &mlock); + GMutexLock &operator=(const GMutexLock &); + bool operator==(const GMutexLock&); + +public: + GMutexLock(GMutex* mutex) { + m = mutex; + m->lock(); + } + + ~GMutexLock() { + m->unlock(); + } +}; + +} // G3D + +#endif diff --git a/externals/g3dlite/G3D/GThread.h b/externals/g3dlite/G3D/GThread.h new file mode 100644 index 00000000000..58437efc3fb --- /dev/null +++ b/externals/g3dlite/G3D/GThread.h @@ -0,0 +1,121 @@ +/** + @file GThread.h + + @created 2005-09-22 + @edited 2007-01-31 + + */ + +#ifndef G3D_GTHREAD_H +#define G3D_GTHREAD_H + +#include "G3D/platform.h" +#include "G3D/ReferenceCount.h" +#include + +#ifndef G3D_WIN32 +# include +# include +#endif + + +namespace G3D { + +typedef ReferenceCountedPointer GThreadRef; + +/** + Platform independent thread implementation. You can either subclass and + override GThread::threadMain or call the create method with a method. + + Beware of reference counting and threads. If circular references exist between + GThread subclasses then neither class will ever be deallocated. Also, + dropping all pointers (and causing deallocation) of a GThread does NOT + stop the underlying process. + + @sa G3D::GMutex, G3D::Spinlock, G3D::AtomicInt32 +*/ +class GThread : public ReferenceCountedObject { +private: + // "Status" is a reserved work on FreeBSD + enum GStatus {STATUS_CREATED, STATUS_STARTED, STATUS_RUNNING, STATUS_COMPLETED}; + + // Not implemented on purpose, don't use + GThread(const GThread &); + GThread& operator=(const GThread&); + bool operator==(const GThread&); + +#ifdef G3D_WIN32 + static DWORD WINAPI internalThreadProc(LPVOID param); +#else + static void* internalThreadProc(void* param); +#endif //G3D_WIN32 + + volatile GStatus m_status; + + // Thread handle to hold HANDLE and pthread_t +#ifdef G3D_WIN32 + HANDLE m_handle; + HANDLE m_event; +#else + pthread_t m_handle; +#endif //G3D_WIN32 + + std::string m_name; + +protected: + + /** Overriden by the thread implementor */ + virtual void threadMain() = 0; + +public: + typedef ReferenceCountedPointer Ref; + enum SpawnBehavior {USE_NEW_THREAD, USE_CURRENT_THREAD}; + + GThread(const std::string& name); + + virtual ~GThread(); + + /** Constructs a basic GThread without requiring a subclass. + + @param proc The global or static function for the threadMain() */ + static GThreadRef create(const std::string& name, void (*proc)(void*), void* param = NULL); + + /** Starts the thread and executes threadMain(). Returns false if + the thread failed to start (either because it was already started + or because the OS refused). + + @param behavior If USE_CURRENT_THREAD, rather than spawning a new thread, this routine + runs threadMain on the current thread. + */ + bool start(SpawnBehavior behavior = USE_NEW_THREAD); + + /** Terminates the thread without notifying or + waiting for a cancelation point. */ + void terminate(); + + /** + Returns true if threadMain is currently executing. This will + only be set when the thread is actually running and might not + be set when start() returns. */ + bool running() const; + + /** True after start() has been called, even through the thread + may have already completed(), or be currently running().*/ + bool started() const; + + /** Returns true if the thread has exited. */ + bool completed() const; + + /** Waits for the thread to finish executing. */ + void waitForCompletion(); + + /** Returns thread name */ + inline const std::string& name() { + return m_name; + } +}; + + +} // namespace G3D + +#endif //G3D_GTHREAD_H diff --git a/externals/g3dlite/G3D/GUniqueID.h b/externals/g3dlite/G3D/GUniqueID.h new file mode 100644 index 00000000000..c8b775c2e66 --- /dev/null +++ b/externals/g3dlite/G3D/GUniqueID.h @@ -0,0 +1,69 @@ +/** + @file GUniqueID.h + @author Morgan McGuire, http://graphics.cs.williams.edu + */ +#ifndef G3D_GUNIQUEID_H +#define G3D_GUNIQUEID_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Table.h" + +namespace G3D { + +/** Globally unique identifiers. The probability of two different + programs generating the same value from UniqueID::create is + vanishingly small. + + UniqueIDs optionally contain a 10-bit application specific tag + that distinguishes their type. +*/ +class GUniqueID { +private: + + uint64 id; + +public: + + GUniqueID() : id(0) {} + + bool uninitialized() const { + return id == 0; + } + + uint16 tag() const { + return id >> 54; + } + + operator uint64() const { + return id; + } + + bool operator==(const GUniqueID& other) const { + return id == other.id; + } + + bool operator!=(const GUniqueID& other) const { + return id != other.id; + } + + void serialize(class BinaryOutput& b) const; + + void deserialize(class BinaryInput& b); + + void serialize(class TextOutput& t) const; + + void deserialize(class TextInput& t); + + /** Create a new ID */ + static GUniqueID create(uint16 tag = 0); +}; + +} // G3D + +/** For Table and Set */ +template<> struct HashTrait { + static size_t hashCode(G3D::GUniqueID id) { return (size_t)(G3D::uint64)id; } +}; + +#endif diff --git a/externals/g3dlite/G3D/HashTrait.h b/externals/g3dlite/G3D/HashTrait.h new file mode 100644 index 00000000000..ca35da48643 --- /dev/null +++ b/externals/g3dlite/G3D/HashTrait.h @@ -0,0 +1,92 @@ +/** + @file HashTrait.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @created 2008-10-01 + @edited 2009-11-01 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_HashTrait_h +#define G3D_HashTrait_h + +#include "G3D/platform.h" +#include "G3D/Crypto.h" +#include "G3D/g3dmath.h" +#include "G3D/uint128.h" + +/** Must be specialized for custom types. + @see G3D::Table for specialization requirements. +*/ +template struct HashTrait{}; + +template struct HashTrait { + static size_t hashCode(const void* k) { return reinterpret_cast(k); } +}; + +#if 0 +template <> struct HashTrait { + static size_t hashCode(int k) { return static_cast(k); } +}; +#endif + +template <> struct HashTrait { + static size_t hashCode(G3D::int16 k) { return static_cast(k); } +}; + +template <> struct HashTrait { + static size_t hashCode(G3D::uint16 k) { return static_cast(k); } +}; + +//template <> struct HashTrait { +// static size_t hashCode(int k) { return static_cast(k); } +//}; + +template <> struct HashTrait { + static size_t hashCode(G3D::int32 k) { return static_cast(k); } +}; + +template <> struct HashTrait { + static size_t hashCode(G3D::uint32 k) { return static_cast(k); } +}; + +#if 0 +template <> struct HashTrait { + static size_t hashCode(G3D::uint32 k) { return static_cast(k); } +}; +#endif + +template <> struct HashTrait { + static size_t hashCode(G3D::int64 k) { return static_cast(k); } +}; + +template <> struct HashTrait { + static size_t hashCode(G3D::uint64 k) { return static_cast(k); } +}; + +template <> struct HashTrait { + static size_t hashCode(const std::string& k) { return static_cast(G3D::Crypto::crc32(k.c_str(), k.size())); } +}; + +template <> struct HashTrait { + // Use the FNV-1 hash (http://isthe.com/chongo/tech/comp/fnv/#FNV-1). + static size_t hashCode(G3D::uint128 key) { + static const G3D::uint128 FNV_PRIME_128(1 << 24, 0x159); + static const G3D::uint128 FNV_OFFSET_128(0xCF470AAC6CB293D2ULL, 0xF52F88BF32307F8FULL); + + G3D::uint128 hash = FNV_OFFSET_128; + G3D::uint128 mask(0, 0xFF); + for (int i = 0; i < 16; ++i) { + hash *= FNV_PRIME_128; + hash ^= (mask & key); + key >>= 8; + } + + G3D::uint64 foldedHash = hash.hi ^ hash.lo; + return static_cast((foldedHash >> 32) ^ (foldedHash & 0xFFFFFFFF)); + } +}; + +#endif diff --git a/externals/g3dlite/G3D/Image1.h b/externals/g3dlite/G3D/Image1.h new file mode 100644 index 00000000000..711e83f2079 --- /dev/null +++ b/externals/g3dlite/G3D/Image1.h @@ -0,0 +1,81 @@ +/** + @file Image1.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2007-01-31 + @edited 2007-01-31 +*/ + + +#ifndef G3D_IMAGE1_H +#define G3D_IMAGE1_H + +#include "G3D/platform.h" +#include "G3D/Map2D.h" +#include "G3D/Color1.h" +#include "G3D/GImage.h" + +namespace G3D { + +typedef ReferenceCountedPointer Image1Ref; + +/** + Luminance image with 32-bit floating point storage. + + See also G3D::Image1uint8, G3D::GImage. + */ +class Image1 : public Map2D { +public: + + typedef Image1 Type; + typedef ReferenceCountedPointer Ref; + typedef Color1 Storage; + typedef Color1 Compute; + +protected: + + Image1(int w, int h, WrapMode wrap); + + void copyGImage(const class GImage& im); + void copyArray(const Color1* src, int w, int h); + void copyArray(const Color3* src, int w, int h); + void copyArray(const Color4* src, int w, int h); + void copyArray(const Color1uint8* src, int w, int h); + void copyArray(const Color3uint8* src, int w, int h); + void copyArray(const Color4uint8* src, int w, int h); + +public: + + const class ImageFormat* format() const; + + /** Creates an all-zero width x height image. */ + static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR); + + /** Creates a 0 x 0 image. */ + static Ref createEmpty(WrapMode wrap = WrapMode::ERROR); + + static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT); + + static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + + static Ref fromImage1uint8(const ReferenceCountedPointer& im); + + static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR); + + /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input, + it is stripped. */ + void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); + + /** Saves in any of the formats supported by G3D::GImage. */ + void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); +}; + +} // G3D + +#endif diff --git a/externals/g3dlite/G3D/Image1uint8.h b/externals/g3dlite/G3D/Image1uint8.h new file mode 100644 index 00000000000..f32e022e92a --- /dev/null +++ b/externals/g3dlite/G3D/Image1uint8.h @@ -0,0 +1,80 @@ +/** + @file Image1uint8.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2007-01-31 + @edited 2007-01-31 +*/ + +#ifndef G3D_IMAGE1UINT8_H +#define G3D_IMAGE1UINT8_H + +#include "G3D/platform.h" +#include "G3D/Map2D.h" +#include "G3D/Color1uint8.h" +#include "G3D/Color1.h" +#include "G3D/GImage.h" + +namespace G3D { + +typedef ReferenceCountedPointer Image1uint8Ref; + +/** + Compact storage for luminance 8-bit images. + + See also G3D::Image3, G3D::GImage + */ +class Image1uint8 : public Map2D { +public: + + typedef Image1uint8 Type; + typedef Image1uint8Ref Ref; + +protected: + + Image1uint8(int w, int h, WrapMode wrap); + + void copyGImage(const class GImage& im); + void copyArray(const Color1* src, int w, int h); + void copyArray(const Color3* src, int w, int h); + void copyArray(const Color4* src, int w, int h); + void copyArray(const Color1uint8* src, int w, int h); + void copyArray(const Color3uint8* src, int w, int h); + void copyArray(const Color4uint8* src, int w, int h); + +public: + + const class ImageFormat* format() const; + + /** Creates an all-zero width x height image. */ + static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR); + + /** Creates a 0 x 0 image. */ + static Ref createEmpty(WrapMode wrap = WrapMode::ERROR); + + static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT); + + static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR); + + static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + + static Ref fromImage1(const ReferenceCountedPointer& im); + static Ref fromImage3uint8(const ReferenceCountedPointer& im); + + /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input, + it is stripped. */ + void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); + + /** Saves in any of the formats supported by G3D::GImage. */ + void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); +}; + +} // G3D + +#endif diff --git a/externals/g3dlite/G3D/Image3.h b/externals/g3dlite/G3D/Image3.h new file mode 100644 index 00000000000..13cb8fa7faf --- /dev/null +++ b/externals/g3dlite/G3D/Image3.h @@ -0,0 +1,81 @@ +/** + @file Image3.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2007-01-31 + @edited 2007-01-31 +*/ + + +#ifndef G3D_IMAGE3_H +#define G3D_IMAGE3_H + +#include "G3D/platform.h" +#include "G3D/Map2D.h" +#include "G3D/Color3.h" +#include "G3D/GImage.h" + +namespace G3D { + +typedef ReferenceCountedPointer Image3Ref; + +/** + RGB image with 32-bit floating point storage for each channel. + + See also G3D::Image3uint8, G3D::GImage. + */ +class Image3 : public Map2D { +public: + + typedef Image3 Type; + typedef ReferenceCountedPointer Ref; + typedef Color3 Storage; + typedef Color3 Compute; + +protected: + + Image3(int w, int h, WrapMode wrap); + + void copyGImage(const class GImage& im); + void copyArray(const Color1* src, int w, int h); + void copyArray(const Color3* src, int w, int h); + void copyArray(const Color4* src, int w, int h); + void copyArray(const Color1uint8* src, int w, int h); + void copyArray(const Color3uint8* src, int w, int h); + void copyArray(const Color4uint8* src, int w, int h); + +public: + + const class ImageFormat* format() const; + + /** Creates an all-zero width x height image. */ + static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR); + + /** Creates a 0 x 0 image. */ + static Ref createEmpty(WrapMode wrap = WrapMode::ERROR); + + static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT); + + static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + + static Ref fromImage3uint8(const ReferenceCountedPointer& im); + + static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR); + + /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input, + it is stripped. */ + void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); + + /** Saves in any of the formats supported by G3D::GImage. */ + void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); +}; + +} // G3D + +#endif diff --git a/externals/g3dlite/G3D/Image3uint8.h b/externals/g3dlite/G3D/Image3uint8.h new file mode 100644 index 00000000000..d4fdbc169ca --- /dev/null +++ b/externals/g3dlite/G3D/Image3uint8.h @@ -0,0 +1,85 @@ +/** + @file Image3uint8.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2007-01-31 + @edited 2007-01-31 +*/ + +#ifndef G3D_IMAGE3UINT8_H +#define G3D_IMAGE3UINT8_H + +#include "G3D/platform.h" +#include "G3D/Map2D.h" +#include "G3D/Color3uint8.h" +#include "G3D/Color3.h" +#include "G3D/GImage.h" + +namespace G3D { + +typedef ReferenceCountedPointer Image3uint8Ref; + +/** + Compact storage for RGB 8-bit per channel images. + + See also G3D::Image3, G3D::GImage + */ +class Image3uint8 : public Map2D { +public: + + typedef Image3uint8 Type; + typedef Image3uint8Ref Ref; + +protected: + + Image3uint8(int w, int h, WrapMode wrap); + + void copyGImage(const class GImage& im); + void copyArray(const Color1* src, int w, int h); + void copyArray(const Color3* src, int w, int h); + void copyArray(const Color4* src, int w, int h); + void copyArray(const Color1uint8* src, int w, int h); + void copyArray(const Color3uint8* src, int w, int h); + void copyArray(const Color4uint8* src, int w, int h); + +public: + + const class ImageFormat* format() const; + + /** Creates an all-zero width x height image. */ + static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR); + + + /** Creates a 0 x 0 image. */ + static Ref createEmpty(WrapMode wrap = WrapMode::ERROR); + + + static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT); + + static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR); + + static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + + static Ref fromImage3(const ReferenceCountedPointer& im); + static Ref fromImage1uint8(const ReferenceCountedPointer& im); + + /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input, + it is stripped. */ + void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); + + /** Saves in any of the formats supported by G3D::GImage. */ + void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); + + /** Extracts color channel 0 <= c <= 2 and returns it as a new monochrome image. */ + ReferenceCountedPointer getChannel(int c) const; +}; + +} // G3D + +#endif diff --git a/externals/g3dlite/G3D/Image4.h b/externals/g3dlite/G3D/Image4.h new file mode 100644 index 00000000000..21d7f1e79b1 --- /dev/null +++ b/externals/g3dlite/G3D/Image4.h @@ -0,0 +1,86 @@ +/** + @file Image4.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2007-01-31 + @edited 2007-01-31 +*/ + + +#ifndef G3D_IMAGE4_H +#define G3D_IMAGE4_H + +#include "G3D/platform.h" +#include "G3D/Map2D.h" +#include "G3D/Color4.h" +#include "G3D/GImage.h" + +namespace G3D { + +typedef ReferenceCountedPointer Image4Ref; + +/** + RGBA image with 32-bit floating point storage for each channel. + + Whenever a method needs to convert from RGB to RGBA, A=1 is assumed. + + Bilinear interpolation on Image4 is about 8x faster than on + Image4uint8 due to the large cost of converting int->float on modern + machines. + + @sa G3D::Image4uint8, G3D::GImage. + */ +class Image4 : public Map2D { +public: + + typedef Image4 Type; + typedef ReferenceCountedPointer Ref; + typedef Color4 Storage; + typedef Color4 Compute; + +protected: + + Image4(int w, int h, WrapMode wrap); + + void copyGImage(const class GImage& im); + void copyArray(const Color1* src, int w, int h); + void copyArray(const Color3* src, int w, int h); + void copyArray(const Color4* src, int w, int h); + void copyArray(const Color1uint8* src, int w, int h); + void copyArray(const Color3uint8* src, int w, int h); + void copyArray(const Color4uint8* src, int w, int h); + +public: + + const class ImageFormat* format() const; + + /** Creates an all-zero width x height image. */ + static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR); + + /** Creates a 0 x 0 image. */ + static Ref createEmpty(WrapMode wrap = WrapMode::ERROR); + + static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT); + + static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + + static Ref fromImage4uint8(const ReferenceCountedPointer& im); + + static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR); + + /** Loads from any of the file formats supported by G3D::GImage. */ + void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); + + /** Saves in any of the formats supported by G3D::GImage. */ + void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); +}; + +} // G3D + +#endif diff --git a/externals/g3dlite/G3D/Image4uint8.h b/externals/g3dlite/G3D/Image4uint8.h new file mode 100644 index 00000000000..46df6b490b4 --- /dev/null +++ b/externals/g3dlite/G3D/Image4uint8.h @@ -0,0 +1,85 @@ +/** + @file Image4uint8.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2007-01-31 + @edited 2007-01-31 +*/ + +#ifndef G3D_IMAGE4UINT8_H +#define G3D_IMAGE4UINT8_H + +#include "G3D/platform.h" +#include "G3D/Map2D.h" +#include "G3D/Color4uint8.h" +#include "G3D/Color4.h" +#include "G3D/GImage.h" +#include "G3D/Image1uint8.h" + +namespace G3D { + +typedef ReferenceCountedPointer Image4uint8Ref; + +/** + Compact storage for RGBA 8-bit per channel images. + + See also G3D::Image4, G3D::GImage + */ +class Image4uint8 : public Map2D { +public: + + typedef Image4uint8 Type; + typedef Image4uint8Ref Ref; + +protected: + + Image4uint8(int w, int h, WrapMode wrap); + + void copyGImage(const class GImage& im); + void copyArray(const Color1* src, int w, int h); + void copyArray(const Color3* src, int w, int h); + void copyArray(const Color4* src, int w, int h); + void copyArray(const Color1uint8* src, int w, int h); + void copyArray(const Color3uint8* src, int w, int h); + void copyArray(const Color4uint8* src, int w, int h); + +public: + + const class ImageFormat* format() const; + + /** Creates an all-zero width x height image. */ + static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR); + + + /** Creates a 0 x 0 image. */ + static Ref createEmpty(WrapMode wrap = WrapMode::ERROR); + + + static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT); + + static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR); + + static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR); + + static Ref fromImage4(const ReferenceCountedPointer& im); + + /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input, + it is stripped. */ + void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); + + /** Saves in any of the formats supported by G3D::GImage. */ + void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT); + + /** Extracts color channel 0 <= c <= 3 and returns it as a new monochrome image. */ + ReferenceCountedPointer getChannel(int c) const; +}; + +} // G3D + +#endif diff --git a/externals/g3dlite/G3D/ImageFormat.h b/externals/g3dlite/G3D/ImageFormat.h new file mode 100644 index 00000000000..7f098322d26 --- /dev/null +++ b/externals/g3dlite/G3D/ImageFormat.h @@ -0,0 +1,419 @@ +/** + @file ImageFormat.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2003-05-23 + @edited 2010-01-01 +*/ + +#ifndef GLG3D_ImageFormat_H +#define GLG3D_ImageFormat_H + +#include "G3D/platform.h" +#include "G3D/Table.h" +#include "G3D/enumclass.h" + +namespace G3D { + +/** Information about common image formats. + Don't construct these; use the methods provided. + + For most formats, the number indicates the number of bits per channel and a suffix of "F" indicates + floating point. This does not hold for the YUV and DXT formats.*/ +class ImageFormat { +public: + + // Must update ImageFormat::name() when this enum changes. + enum Code { + CODE_NONE = -1, + CODE_L8, + CODE_L16, + CODE_L16F, + CODE_L32F, + + CODE_A8, + CODE_A16, + CODE_A16F, + CODE_A32F, + + CODE_LA4, + CODE_LA8, + CODE_LA16, + CODE_LA16F, + CODE_LA32F, + + CODE_RGB5, + CODE_RGB5A1, + CODE_RGB8, + CODE_RGB10, + CODE_RGB10A2, + CODE_RGB16, + CODE_RGB16F, + CODE_RGB32F, + CODE_R11G11B10F, + CODE_RGB9E5F, + + CODE_RGB8I, + CODE_RGB8UI, + + CODE_ARGB8, + CODE_BGR8, + + CODE_RG8, + CODE_RG8I, + CODE_RG8UI, + + CODE_RGBA8, + CODE_RGBA16, + CODE_RGBA16F, + CODE_RGBA32F, + + CODE_RGBA32UI, + + CODE_BAYER_RGGB8, + CODE_BAYER_GRBG8, + CODE_BAYER_GBRG8, + CODE_BAYER_BGGR8, + CODE_BAYER_RGGB32F, + CODE_BAYER_GRBG32F, + CODE_BAYER_GBRG32F, + CODE_BAYER_BGGR32F, + + CODE_HSV8, + CODE_HSV32F, + + CODE_YUV420_PLANAR, + CODE_YUV422, + CODE_YUV444, + + CODE_RGB_DXT1, + CODE_RGBA_DXT1, + CODE_RGBA_DXT3, + CODE_RGBA_DXT5, + + CODE_SRGB8, + CODE_SRGBA8, + + CODE_SL8, + CODE_SLA8, + + CODE_SRGB_DXT1, + CODE_SRGBA_DXT1, + CODE_SRGBA_DXT3, + CODE_SRGBA_DXT5, + + CODE_DEPTH16, + CODE_DEPTH24, + CODE_DEPTH32, + CODE_DEPTH32F, + + CODE_STENCIL1, + CODE_STENCIL4, + CODE_STENCIL8, + CODE_STENCIL16, + + CODE_DEPTH24_STENCIL8, + + CODE_NUM + }; + + enum ColorSpace { + COLOR_SPACE_NONE, + COLOR_SPACE_RGB, + COLOR_SPACE_HSV, + COLOR_SPACE_YUV, + COLOR_SPACE_SRGB + }; + + enum BayerPattern { + BAYER_PATTERN_NONE, + BAYER_PATTERN_RGGB, + BAYER_PATTERN_GRBG, + BAYER_PATTERN_GBRG, + BAYER_PATTERN_BGGR + }; + + /** Number of channels (1 for a depth texture). */ + int numComponents; + bool compressed; + + /** Useful for serializing. */ + Code code; + + ColorSpace colorSpace; + + /** If this is a Bayer format, what is the pattern. */ + BayerPattern bayerPattern; + + /** The OpenGL format equivalent to this one, e.g, GL_RGB8 Zero if there is no equivalent. This is actually a GLenum */ + int openGLFormat; + + /** The OpenGL base format equivalent to this one (e.g., GL_RGB, GL_ALPHA). Zero if there is no equivalent. */ + int openGLBaseFormat; + + int luminanceBits; + + /** Number of bits per pixel storage for alpha values; Zero for compressed textures and non-RGB. */ + int alphaBits; + + /** Number of bits per pixel storage for red values; Zero for compressed textures and non-RGB. */ + int redBits; + + /** Number of bits per pixel storage for green values; Zero for compressed textures and non-RGB. */ + int greenBits; + + /** Number of bits per pixel storage for blue values; Zero for compressed textures and non-RGB. */ + int blueBits; + + /** Number of bits per pixel */ + int stencilBits; + + /** Number of depth bits (for depth textures; e.g. shadow maps) */ + int depthBits; + + /** Amount of CPU memory per pixel when packed into an array, discounting any end-of-row padding. */ + int cpuBitsPerPixel; + + /** Amount of CPU memory per pixel when packed into an array, discounting any end-of-row padding. + @deprecated Use cpuBitsPerPixel*/ + int packedBitsPerTexel; + + /** + Amount of GPU memory per pixel on most graphics cards, for formats supported by OpenGL. This is + only an estimate--the actual amount of memory may be different on your actual card. + + This may be greater than the sum of the per-channel bits + because graphics cards need to pad to the nearest 1, 2, or + 4 bytes. + */ + int openGLBitsPerPixel; + + /** @deprecated Use openGLBitsPerPixel */ + int hardwareBitsPerTexel; + + /** The OpenGL bytes (type) format of the data buffer used with this texture format, e.g., GL_UNSIGNED_BYTE */ + int openGLDataFormat; + + /** True if there is no alpha channel for this texture. */ + bool opaque; + + /** True if the bit depths specified are for float formats. */ + bool floatingPoint; + + /** Human readable name of this format.*/ + const std::string& name() const; + + /** Takes the same values that name() returns */ + static const ImageFormat* fromString(const std::string& s); + +private: + + ImageFormat + (int numComponents, + bool compressed, + int glFormat, + int glBaseFormat, + int luminanceBits, + int alphaBits, + int redBits, + int greenBits, + int blueBits, + int depthBits, + int stencilBits, + int hardwareBitsPerTexel, + int packedBitsPerTexel, + int glDataFormat, + bool opaque, + bool floatingPoint, + Code code, + ColorSpace colorSpace, + BayerPattern bayerPattern = BAYER_PATTERN_NONE); + +public: + + static const ImageFormat* L8(); + + static const ImageFormat* L16(); + + static const ImageFormat* L16F(); + + static const ImageFormat* L32F(); + + static const ImageFormat* A8(); + + static const ImageFormat* A16(); + + static const ImageFormat* A16F(); + + static const ImageFormat* A32F(); + + static const ImageFormat* LA4(); + + static const ImageFormat* LA8(); + + static const ImageFormat* LA16(); + + static const ImageFormat* LA16F(); + + static const ImageFormat* LA32F(); + + static const ImageFormat* BGR8(); + + static const ImageFormat* RG8(); + static const ImageFormat* RG8I(); + static const ImageFormat* RG8UI(); + + static const ImageFormat* RGB5(); + + static const ImageFormat* RGB5A1(); + + static const ImageFormat* RGB8(); + + static const ImageFormat* RGB10(); + + static const ImageFormat* RGB10A2(); + + static const ImageFormat* RGB16(); + + static const ImageFormat* RGB16F(); + + static const ImageFormat* RGB32F(); + + static const ImageFormat* RGBA8(); + + static const ImageFormat* RGBA16(); + + static const ImageFormat* RGBA16F(); + + static const ImageFormat* RGBA32F(); + + static const ImageFormat* RGBA32UI(); + + static const ImageFormat* R11G11B10F(); + + static const ImageFormat* RGB9E5F(); + + static const ImageFormat* RGB8I(); + + static const ImageFormat* RGB8UI(); + + static const ImageFormat* RGB_DXT1(); + + static const ImageFormat* RGBA_DXT1(); + + static const ImageFormat* RGBA_DXT3(); + + static const ImageFormat* RGBA_DXT5(); + + static const ImageFormat* SRGB8(); + + static const ImageFormat* SRGBA8(); + + static const ImageFormat* SL8(); + + static const ImageFormat* SLA8(); + + static const ImageFormat* SRGB_DXT1(); + + static const ImageFormat* SRGBA_DXT1(); + + static const ImageFormat* SRGBA_DXT3(); + + static const ImageFormat* SRGBA_DXT5(); + + static const ImageFormat* DEPTH16(); + + static const ImageFormat* DEPTH24(); + + static const ImageFormat* DEPTH32(); + + static const ImageFormat* DEPTH32F(); + + static const ImageFormat* STENCIL1(); + + static const ImageFormat* STENCIL4(); + + static const ImageFormat* STENCIL8(); + + static const ImageFormat* STENCIL16(); + + static const ImageFormat* DEPTH24_STENCIL8(); + + static const ImageFormat* YUV420_PLANAR(); + + static const ImageFormat* YUV422(); + + static const ImageFormat* YUV444(); + + /** + NULL pointer; indicates that the G3D::Texture class should choose + either RGBA8 or RGB8 depending on the presence of an alpha channel + in the input. + */ + static const ImageFormat* AUTO() { return NULL; } + + /** Returns DEPTH16, DEPTH24, or DEPTH32 according to the bits + specified. You can use "glGetInteger(GL_DEPTH_BITS)" to match + the screen's format.*/ + static const ImageFormat* depth(int depthBits = 24); + + /** Returns STENCIL1, STENCIL4, STENCIL8 or STENCIL16 according to the bits + specified. You can use "glGetInteger(GL_STENCIL_BITS)" to match + the screen's format.*/ + static const ImageFormat* stencil(int bits = 8); + + /** Returns the matching ImageFormat* identified by the Code. May return NULL + if this format's code is reserved but not yet implemented by G3D. */ + static const ImageFormat* fromCode(ImageFormat::Code code); + + + + /** For use with ImageFormat::convert. */ + class BayerAlgorithm { + public: + enum Value { + NEAREST, + BILINEAR, + MHC, + HIGH_QUALITY = MHC + }; + private: + + Value value; + + public: + + G3D_DECLARE_ENUM_CLASS_METHODS(BayerAlgorithm); + }; + + /** Converts between arbitrary formats on the CPU. Not all format conversions are supported or directly supported. + Formats without direct conversions will attempt to convert through RGBA first. + + A conversion routine might only support source or destination padding or y inversion or none. + If support is needed and not available in any of the direct conversion routines, then no conversion is done. + + YUV422 expects data in YUY2 format (Y, U, Y2, v). Most YUV formats require width and heights that are multiples of 2. + + Returns true if a conversion was available, false if none occurred. + */ + static bool convert(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, + const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, + bool invertY = false, BayerAlgorithm bayerAlg = BayerAlgorithm::HIGH_QUALITY); + + /* Checks if a conversion between two formats is available. */ + static bool conversionAvailable(const ImageFormat* srcFormat, int srcRowPadBits, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY = false); +}; + +typedef ImageFormat TextureFormat; + +} + +template <> +struct HashTrait { + static size_t hashCode(const G3D::ImageFormat* key) { return reinterpret_cast(key); } +}; + + + +#endif diff --git a/externals/g3dlite/G3D/Intersect.h b/externals/g3dlite/G3D/Intersect.h new file mode 100644 index 00000000000..4a3c8fb4540 --- /dev/null +++ b/externals/g3dlite/G3D/Intersect.h @@ -0,0 +1,55 @@ +/** + @file Intersect.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2009-06-29 + @edited 2009-06-29 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + + From the G3D Innovation Engine + http://g3d.sf.net + */ +#ifndef G3D_Intersect +#define G3D_Intersect + +#include "G3D/platform.h" +#include "G3D/Ray.h" +#include "G3D/AABox.h" + +namespace G3D { + +/** + @beta + */ +class Intersect { +public: + + /** \brief Returns true if the intersection of the ray and the solid box is non-empty. + + \cite "Fast Ray / Axis-Aligned Bounding Box Overlap Tests using Ray Slopes" + by Martin Eisemann, Thorsten Grosch, Stefan Müller and Marcus Magnor + Computer Graphics Lab, TU Braunschweig, Germany and + University of Koblenz-Landau, Germany + */ + static bool __fastcall rayAABox(const Ray& ray, const AABox& box); + + /** \brief Returns true if the intersection of the ray and the solid box is non-empty. + + \param time If there is an intersection, set to the time to that intersection. If the ray origin is inside the box, + this is a negative value indicating the distance backwards from the ray origin to the first intersection. + \a time is not set if there is no intersection. + + \cite Slope-Mul method from "Fast Ray / Axis-Aligned Bounding Box Overlap Tests using Ray Slopes" + by Martin Eisemann, Thorsten Grosch, Stefan Müller and Marcus Magnor + Computer Graphics Lab, TU Braunschweig, Germany and + University of Koblenz-Landau, Germany + */ + static bool __fastcall rayAABox(const Ray& ray, const AABox& box, float& time); +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/KDTree.h b/externals/g3dlite/G3D/KDTree.h new file mode 100644 index 00000000000..4785ef2baea --- /dev/null +++ b/externals/g3dlite/G3D/KDTree.h @@ -0,0 +1,1667 @@ +/** + @file KDTree.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2004-01-11 + @edited 2009-12-28 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_KDTREE_H +#define G3D_KDTREE_H + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/Table.h" +#include "G3D/Vector2.h" +#include "G3D/Vector3.h" +#include "G3D/Vector4.h" +#include "G3D/AABox.h" +#include "G3D/Sphere.h" +#include "G3D/Box.h" +#include "G3D/Triangle.h" +#include "G3D/Ray.h" +#include "G3D/GCamera.h" +#include "G3D/BinaryInput.h" +#include "G3D/BinaryOutput.h" +#include "G3D/CollisionDetection.h" +#include "G3D/GCamera.h" +#include "G3D/BoundsTrait.h" +#include + +// If defined, in debug mode the tree is checked for consistency +// as a way of detecting corruption due to implementation bugs +// #define VERIFY_TREE + +template<> struct BoundsTrait { + static void getBounds(const G3D::Vector2& v, G3D::AABox& out) { out = G3D::AABox(G3D::Vector3(v, 0)); } +}; + +template<> struct BoundsTrait { + static void getBounds(const G3D::Vector3& v, G3D::AABox& out) { out = G3D::AABox(v); } +}; + +template<> struct BoundsTrait { + static void getBounds(const G3D::Vector4& v, G3D::AABox& out) { out = G3D::AABox(v.xyz()); } +}; + +template<> struct BoundsTrait { + static void getBounds(const G3D::AABox& v, G3D::AABox& out) { out = v; } +}; + +template<> struct BoundsTrait { + static void getBounds(const G3D::Sphere& s, G3D::AABox& out) { s.getBounds(out); } +}; + +template<> struct BoundsTrait { + static void getBounds(const G3D::Box& b, G3D::AABox& out) { b.getBounds(out); } +}; + +template<> struct BoundsTrait { + static void getBounds(const G3D::Vector2*& v, G3D::AABox& out) { out = G3D::AABox(G3D::Vector3(*v, 0)); } +}; + +template<> struct BoundsTrait { + static void getBounds(const G3D::Vector3*& v, G3D::AABox& out) { out = G3D::AABox(*v); } +}; + +template<> struct BoundsTrait { + static void getBounds(const G3D::Vector4*& v, G3D::AABox& out) { out = G3D::AABox(v->xyz()); } +}; + +template<> struct BoundsTrait { + static void getBounds(const G3D::AABox*& v, G3D::AABox& out) { out = *v; } +}; + +template<> struct BoundsTrait { + static void getBounds(const G3D::Sphere*& s, G3D::AABox& out) { s->getBounds(out); } +}; + +template<> struct BoundsTrait { + static void getBounds(const G3D::Box*& b, G3D::AABox& out) { b->getBounds(out); } +}; + + +template<> struct BoundsTrait { + static void getBounds(const G3D::Triangle*& t, G3D::AABox& out) { t->getBounds(out); } +}; + +namespace G3D { + namespace _internal { + + /** + Wraps a pointer value so that it can be treated as the instance itself; + convenient for inserting pointers into a Table but using the + object equality instead of pointer equality. + */ + template + class Indirector { + public: + Type* handle; + + inline Indirector(Type* h) : handle(h) {} + + inline Indirector() : handle(NULL) {} + + /** Returns true iff the values referenced by the handles are equivalent. */ + inline bool operator==(const Indirector& m) const { + return *handle == *(m.handle); + } + + inline bool operator==(const Type& m) const { + return *handle == m; + } + + inline size_t hashCode() const { + return handle->hashCode(); + } + }; + } // namespace internal +} // namespace G3D + +template struct HashTrait > { + static size_t hashCode(const G3D::_internal::Indirector& key) { return key.hashCode(); } +}; + +namespace G3D { + +/** + A set that supports spatial queries using a KD tree (axis-aligned + BSP tree) for speed. + + KDTree allows you to quickly find objects in 3D that lie within + a box or along a ray. For large sets of objects it is much faster + than testing each object for a collision. + + KDTree is as powerful as but more general than a Quad Tree, Oct + Tree, or regular KD tree that cycles through axes, but less general than an unconstrained BSP tree + (which is much slower to create). + + Internally, objects + are arranged into a tree according to their + axis-aligned bounds. This increases the cost of insertion to + O(log n) but allows fast overlap queries. + + Template Parameters +
The template parameter T must be one for which + the following functions are all overloaded: + +
+  T::T(); // public constructor of no arguments
+  template <> struct HashTrait { static size_t hashCode(int key); };
+  template<> struct BoundsTrait { static void getBounds(const T& obj, G3D::AABox& out); };
+ 
+ + G3D provides these for common classes like G3D::Vector3 and G3D::Sphere. + If you use a custom class, or a pointer to a custom class, you will need + to define those functions. + + Moving %Set Members +
It is important that objects do not move without updating the + KDTree. If the axis-aligned bounds of an object are about + to change, KDTree::remove it before they change and + KDTree::insert it again afterward. For objects + where the hashCode and == operator are invariant with respect + to the 3D position, + you can use the KDTree::update method as a shortcut to + insert/remove an object in one step after it has moved. + + + Note: Do not mutate any value once it has been inserted into KDTree. Values + are copied interally. All KDTree iterators convert to pointers to constant + values to reinforce this. + + If you want to mutate the objects you intend to store in a KDTree + simply insert pointers to your objects instead of the objects + themselves, and ensure that the above operations are defined. (And + actually, because values are copied, if your values are large you may + want to insert pointers anyway, to save space and make the balance + operation faster.) + + Dimensions + Although designed as a 3D-data structure, you can use the KDTree + for data distributed along 2 or 1 axes by simply returning bounds + that are always zero along one or more dimensions. + +*/ +template< class T, + class BoundsFunc = BoundsTrait, + class HashFunc = HashTrait, + class EqualsFunc = EqualsTrait > +class KDTree { +protected: +#define TreeType KDTree + + /** Wrapper for a value that includes a cache of its bounds. + Except for the test value used in a set-query operation, there + is only ever one instance of the handle associated with any + value and the memberTable and Nodes maintain pointers to that + heap-allocated value. + */ + class Handle { + public: + /** The bounds of each object are constrained to AABox::large */ + AABox bounds; + + /** Center of bounds. We cache this value to avoid recomputing it + during the median sort, and because MSVC 6 std::sort goes into + an infinite loop if we compute the midpoint on the fly (possibly + a floating point roundoff issue, where B& point, + int beginIndex, + int endIndex) { + + Vector3 lo = Vector3::inf(); + Vector3 hi = -lo; + + debugAssertM(beginIndex <= endIndex, "No points"); + for (int p = beginIndex; p <= endIndex; ++p) { + // This code is written with the vector min and max expanded + // because otherwise it compiles incorrectly with -O3 on + // gcc 3.4 + + const Vector3& pLo = point[p]->bounds.low(); + const Vector3& pHi = point[p]->bounds.high(); + for (int a = 0; a < 3; ++a) { + lo[a] = G3D::min(lo[a], pLo[a]); + hi[a] = G3D::max(hi[a], pHi[a]); + } + } + + return AABox(lo, hi); + } + + /** Compares centers */ + class CenterComparator { + public: + Vector3::Axis sortAxis; + + CenterComparator(Vector3::Axis a) : sortAxis(a) {} + + inline int operator()(Handle* A, const Handle* B) const { + float a = A->center[sortAxis]; + float b = B->center[sortAxis]; + + if (a < b) { + return 1; + } else if (a > b) { + return -1; + } else { + return 0; + } + } + }; + + + /** Compares bounds for strict >, <, or overlap*/ + class BoundsComparator { + public: + Vector3::Axis sortAxis; + + BoundsComparator(Vector3::Axis a) : sortAxis(a) {} + + inline int operator()(Handle* A, const Handle* B) const { + const AABox& a = A->bounds; + const AABox& b = B->bounds; + + if (a.high()[sortAxis] < b.low()[sortAxis]) { + return 1; + } else if (a.low()[sortAxis] > b.high()[sortAxis]) { + return -1; + } else { + return 0; + } + } + }; + + + /** Compares bounds to the sort location */ + class Comparator { + public: + Vector3::Axis sortAxis; + float sortLocation; + + Comparator(Vector3::Axis a, float l) : sortAxis(a), sortLocation(l) {} + + inline int operator()(Handle* ignore, const Handle* handle) const { + (void)ignore; + const AABox& box = handle->bounds; + debugAssert(ignore == NULL); + + if (box.high()[sortAxis] < sortLocation) { + // Box is strictly below the sort location + return -1; + } else if (box.low()[sortAxis] > sortLocation) { + // Box is strictly above the sort location + return 1; + } else { + // Box overlaps the sort location + return 0; + } + } + }; + + // Using System::malloc with this class provided no speed improvement. + class Node { + public: + + /** Spatial bounds on all values at this node and its children, based purely on + the parent's splitting planes. May be infinite. */ + AABox splitBounds; + + Vector3::Axis splitAxis; + + /** Location along the specified axis */ + float splitLocation; + + /** child[0] contains all values strictly + smaller than splitLocation along splitAxis. + + child[1] contains all values strictly + larger. + + Both may be NULL if there are not enough + values to bother recursing. + */ + Node* child[2]; + + /** Array of values at this node (i.e., values + straddling the split plane + all values if + this is a leaf node). + + This is an array of pointers because that minimizes + data movement during tree building, which accounts + for about 15% of the time cost of tree building. + */ + Array valueArray; + + /** For each object in the value array, a copy of its bounds. + Packing these into an array at the node level + instead putting them in the valueArray improves + cache coherence, which is about a 3x performance + increase when performing intersection computations. + */ + Array boundsArray; + + /** Creates node with NULL children */ + Node() { + splitAxis = Vector3::X_AXIS; + splitLocation = 0; + splitBounds = AABox(-Vector3::inf(), Vector3::inf()); + for (int i = 0; i < 2; ++i) { + child[i] = NULL; + } + } + + /** + Doesn't clone children. + */ + Node(const Node& other) : valueArray(other.valueArray), boundsArray(other.boundsArray) { + splitAxis = other.splitAxis; + splitLocation = other.splitLocation; + splitBounds = other.splitBounds; + for (int i = 0; i < 2; ++i) { + child[i] = NULL; + } + } + + /** Copies the specified subarray of pt into point, NULLs the children. + Assumes a second pass will set splitBounds. */ + Node(const Array& pt) : valueArray(pt) { + splitAxis = Vector3::X_AXIS; + splitLocation = 0; + for (int i = 0; i < 2; ++i) { + child[i] = NULL; + } + + boundsArray.resize(valueArray.size()); + for (int i = 0; i < valueArray.size(); ++i) { + boundsArray[i] = valueArray[i]->bounds; + } + } + + /** Deletes the children (but not the values) */ + ~Node() { + for (int i = 0; i < 2; ++i) { + delete child[i]; + } + } + + /** Returns true if this node is a leaf (no children) */ + inline bool isLeaf() const { + return (child[0] == NULL) && (child[1] == NULL); + } + + + /** + Recursively appends all handles and children's handles + to the array. + */ + void getHandles(Array& handleArray) const { + handleArray.append(valueArray); + for (int i = 0; i < 2; ++i) { + if (child[i] != NULL) { + child[i]->getHandles(handleArray); + } + } + } + + void verifyNode(const Vector3& lo, const Vector3& hi) { + // debugPrintf("Verifying: split %d @ %f [%f, %f, %f], [%f, %f, %f]\n", + // splitAxis, splitLocation, lo.x, lo.y, lo.z, hi.x, hi.y, hi.z); + + debugAssertM(lo == splitBounds.low(), + format("lo = %s, splitBounds.lo = %s", + lo.toString().c_str(), splitBounds.low().toString().c_str())); + debugAssert(hi == splitBounds.high()); + + for (int i = 0; i < valueArray.length(); ++i) { + const AABox& b = valueArray[i]->bounds; + debugAssert(b == boundsArray[i]); + + for(int axis = 0; axis < 3; ++axis) { + debugAssert(b.low()[axis] <= b.high()[axis]); + debugAssert(b.low()[axis] >= lo[axis]); + debugAssert(b.high()[axis] <= hi[axis]); + } + } + + if (child[0] || child[1]) { + debugAssert(lo[splitAxis] < splitLocation); + debugAssert(hi[splitAxis] > splitLocation); + } + + Vector3 newLo = lo; + newLo[splitAxis] = splitLocation; + Vector3 newHi = hi; + newHi[splitAxis] = splitLocation; + + if (child[0] != NULL) { + child[0]->verifyNode(lo, newHi); + } + + if (child[1] != NULL) { + child[1]->verifyNode(newLo, hi); + } + } + + + /** + Stores the locations of the splitting planes (the structure but not the content) + so that the tree can be quickly rebuilt from a previous configuration without + calling balance. + */ + static void serializeStructure(const Node* n, BinaryOutput& bo) { + if (n == NULL) { + bo.writeUInt8(0); + } else { + bo.writeUInt8(1); + n->splitBounds.serialize(bo); + serialize(n->splitAxis, bo); + bo.writeFloat32(n->splitLocation); + for (int c = 0; c < 2; ++c) { + serializeStructure(n->child[c], bo); + } + } + } + + /** Clears the member table */ + static Node* deserializeStructure(BinaryInput& bi) { + if (bi.readUInt8() == 0) { + return NULL; + } else { + Node* n = new Node(); + n->splitBounds.deserialize(bi); + deserialize(n->splitAxis, bi); + n->splitLocation = bi.readFloat32(); + for (int c = 0; c < 2; ++c) { + n->child[c] = deserializeStructure(bi); + } + return n; + } + } + + /** Returns the deepest node that completely contains bounds. */ + Node* findDeepestContainingNode(const AABox& bounds) { + + // See which side of the splitting plane the bounds are on + if (bounds.high()[splitAxis] < splitLocation) { + // Bounds are on the low side. Recurse into the child + // if it exists. + if (child[0] != NULL) { + return child[0]->findDeepestContainingNode(bounds); + } + } else if (bounds.low()[splitAxis] > splitLocation) { + // Bounds are on the high side, recurse into the child + // if it exists. + if (child[1] != NULL) { + return child[1]->findDeepestContainingNode(bounds); + } + } + + // There was no containing child, so this node is the + // deepest containing node. + return this; + } + + + /** Appends all members that intersect the box. + If useSphere is true, members that pass the box test + face a second test against the sphere. */ + void getIntersectingMembers( + const AABox& box, + const Sphere& sphere, + Array& members, + bool useSphere) const { + + // Test all values at this node + for (int v = 0; v < boundsArray.size(); ++v) { + const AABox& bounds = boundsArray[v]; + if (bounds.intersects(box) && + (! useSphere || bounds.intersects(sphere))) { + members.append(& (valueArray[v]->value)); + } + } + + // If the left child overlaps the box, recurse into it + if ((child[0] != NULL) && (box.low()[splitAxis] < splitLocation)) { + child[0]->getIntersectingMembers(box, sphere, members, useSphere); + } + + // If the right child overlaps the box, recurse into it + if ((child[1] != NULL) && (box.high()[splitAxis] > splitLocation)) { + child[1]->getIntersectingMembers(box, sphere, members, useSphere); + } + } + + /** + Recurse through the tree, assigning splitBounds fields. + */ + void assignSplitBounds(const AABox& myBounds) { + splitBounds = myBounds; + + AABox childBounds[2]; + myBounds.split(splitAxis, splitLocation, childBounds[0], childBounds[1]); + +# if defined(G3D_DEBUG) && defined(VERIFY_TREE) + // Verify the split + for (int v = 0; v < boundsArray.size(); ++v) { + const AABox& bounds = boundsArray[v]; + debugAssert(myBounds.contains(bounds)); + } +# endif + + for (int c = 0; c < 2; ++c) { + if (child[c]) { + child[c]->assignSplitBounds(childBounds[c]); + } + } + } + + /** Returns true if the ray intersects this node */ + bool intersects(const Ray& ray, float distance) const { + // See if the ray will ever hit this node or its children + Vector3 location; + bool alreadyInsideBounds = false; + bool rayWillHitBounds = + CollisionDetection::collisionLocationForMovingPointFixedAABox( + ray.origin(), ray.direction(), splitBounds, location, alreadyInsideBounds); + + bool canHitThisNode = (alreadyInsideBounds || + (rayWillHitBounds && ((location - ray.origin()).squaredLength() < square(distance)))); + + return canHitThisNode; + } + + template + void intersectRay( + const Ray& ray, + RayCallback& intersectCallback, + float& distance, + bool intersectCallbackIsFast) const { + + if (! intersects(ray, distance)) { + // The ray doesn't hit this node, so it can't hit the children of the node. + return; + } + + // Test for intersection against every object at this node. + for (int v = 0; v < valueArray.size(); ++v) { + bool canHitThisObject = true; + + if (! intersectCallbackIsFast) { + // See if + Vector3 location; + const AABox& bounds = boundsArray[v]; + bool alreadyInsideBounds = false; + bool rayWillHitBounds = + CollisionDetection::collisionLocationForMovingPointFixedAABox( + ray.origin(), ray.direction(), bounds, location, alreadyInsideBounds); + + canHitThisObject = (alreadyInsideBounds || + (rayWillHitBounds && ((location - ray.origin()).squaredLength() < square(distance)))); + } + + if (canHitThisObject) { + // It is possible that this ray hits this object. Look for the intersection using the + // callback. + const T& value = valueArray[v]->value; + intersectCallback(ray, value, distance); + } + } + + // There are three cases to consider next: + // + // 1. the ray can start on one side of the splitting plane and never enter the other, + // 2. the ray can start on one side and enter the other, and + // 3. the ray can travel exactly down the splitting plane + + enum {NONE = -1}; + int firstChild = NONE; + int secondChild = NONE; + + if (ray.origin()[splitAxis] < splitLocation) { + + // The ray starts on the small side + firstChild = 0; + + if (ray.direction()[splitAxis] > 0) { + // The ray will eventually reach the other side + secondChild = 1; + } + + } else if (ray.origin()[splitAxis] > splitLocation) { + + // The ray starts on the large side + firstChild = 1; + + if (ray.direction()[splitAxis] < 0) { + secondChild = 0; + } + } else { + // The ray starts on the splitting plane + if (ray.direction()[splitAxis] < 0) { + // ...and goes to the small side + firstChild = 0; + } else if (ray.direction()[splitAxis] > 0) { + // ...and goes to the large side + firstChild = 1; + } + } + + // Test on the side closer to the ray origin. + if ((firstChild != NONE) && child[firstChild]) { + child[firstChild]->intersectRay(ray, intersectCallback, distance, intersectCallbackIsFast); + } + + if (ray.direction()[splitAxis] != 0) { + // See if there was an intersection before hitting the splitting plane. + // If so, there is no need to look on the far side and recursion terminates. + float distanceToSplittingPlane = (splitLocation - ray.origin()[splitAxis]) / ray.direction()[splitAxis]; + if (distanceToSplittingPlane > distance) { + // We aren't going to hit anything else before hitting the splitting plane, + // so don't bother looking on the far side of the splitting plane at the other + // child. + return; + } + } + + // Test on the side farther from the ray origin. + if ((secondChild != NONE) && child[secondChild]) { + child[secondChild]->intersectRay(ray, intersectCallback, distance, intersectCallbackIsFast); + } + + } + }; + + + /** + Recursively subdivides the subarray. + + Clears the source array as soon as it is no longer needed. + + Call assignSplitBounds() on the root node after making a tree. + */ + Node* makeNode( + Array& source, + int valuesPerNode, + int numMeanSplits, + Array& temp) { + + Node* node = NULL; + + if (source.size() <= valuesPerNode) { + // Make a new leaf node + node = new Node(source); + + // Set the pointers in the memberTable + for (int i = 0; i < source.size(); ++i) { + memberTable.set(Member(source[i]), node); + } + source.clear(); + + } else { + // Make a new internal node + node = new Node(); + + const AABox& bounds = computeBounds(source, 0, source.size() - 1); + const Vector3& extent = bounds.high() - bounds.low(); + + Vector3::Axis splitAxis = extent.primaryAxis(); + + float splitLocation; + + // Arrays for holding the children + Array lt, gt; + + if (numMeanSplits <= 0) { + + source.medianPartition(lt, node->valueArray, gt, temp, CenterComparator(splitAxis)); + + // Choose the split location to be the center of whatever fell in the center + splitLocation = node->valueArray[0]->center[splitAxis]; + + // Some of the elements in the lt or gt array might really overlap the split location. + // Move them as needed. + for (int i = 0; i < lt.size(); ++i) { + const AABox& bounds = lt[i]->bounds; + if ((bounds.low()[splitAxis] <= splitLocation) && (bounds.high()[splitAxis] >= splitLocation)) { + node->valueArray.append(lt[i]); + // Remove this element and process the new one that + // is swapped in in its place. + lt.fastRemove(i); --i; + } + } + + for (int i = 0; i < gt.size(); ++i) { + const AABox& bounds = gt[i]->bounds; + if ((bounds.low()[splitAxis] <= splitLocation) && (bounds.high()[splitAxis] >= splitLocation)) { + node->valueArray.append(gt[i]); + // Remove this element and process the new one that + // is swapped in in its place. + gt.fastRemove(i); --i; + } + } + + if ((node->valueArray.size() > (source.size() / 2)) && + (source.size() > 6)) { + // This was a bad partition; we ended up putting the splitting plane right in the middle of most of the + // objects. We could try to split on a different axis, or use a different partition (e.g., the extents mean, + // or geometric mean). This implementation falls back on the extents mean, since that case is already handled + // below. + numMeanSplits = 1; + } + } + + // Note: numMeanSplits may have been increased by the code in the previous case above in order to + // force a re-partition. + + if (numMeanSplits > 0) { + // Split along the mean + splitLocation = + bounds.high()[splitAxis] * 0.5f + + bounds.low()[splitAxis] * 0.5f; + + debugAssertM(isFinite(splitLocation), + "Internal error: split location must be finite."); + + source.partition(NULL, lt, node->valueArray, gt, Comparator(splitAxis, splitLocation)); + + // The Comparator ensures that elements are strictly on the correct side of the split + } + + +# if defined(G3D_DEBUG) && defined(VERIFY_TREE) + debugAssert(lt.size() + node->valueArray.size() + gt.size() == source.size()); + // Verify that all objects ended up on the correct side of the split. + // (i.e., make sure that the Array partition was correct) + for (int i = 0; i < lt.size(); ++i) { + const AABox& bounds = lt[i]->bounds; + debugAssert(bounds.high()[splitAxis] < splitLocation); + } + + for (int i = 0; i < gt.size(); ++i) { + const AABox& bounds = gt[i]->bounds; + debugAssert(bounds.low()[splitAxis] > splitLocation); + } + + for (int i = 0; i < node->valueArray.size(); ++i) { + const AABox& bounds = node->valueArray[i]->bounds; + debugAssert(bounds.high()[splitAxis] >= splitLocation); + debugAssert(bounds.low()[splitAxis] <= splitLocation); + } +# endif + + // The source array is no longer needed + source.clear(); + + node->splitAxis = splitAxis; + node->splitLocation = splitLocation; + + // Update the bounds array and member table + node->boundsArray.resize(node->valueArray.size()); + for (int i = 0; i < node->valueArray.size(); ++i) { + Handle* v = node->valueArray[i]; + node->boundsArray[i] = v->bounds; + memberTable.set(Member(v), node); + } + + if (lt.size() > 0) { + node->child[0] = makeNode(lt, valuesPerNode, numMeanSplits - 1, temp); + } + + if (gt.size() > 0) { + node->child[1] = makeNode(gt, valuesPerNode, numMeanSplits - 1, temp); + } + + } + + return node; + } + + /** + Recursively clone the passed in node tree, setting + pointers for members in the memberTable as appropriate. + called by the assignment operator. + */ + Node* cloneTree(Node* src) { + Node* dst = new Node(*src); + + // Make back pointers + for (int i = 0; i < dst->valueArray.size(); ++i) { + memberTable.set(Member(dst->valueArray[i]), dst); + } + + // Clone children + for (int i = 0; i < 2; ++i) { + if (src->child[i] != NULL) { + dst->child[i] = cloneTree(src->child[i]); + } + } + + return dst; + } + + /** + Wrapper for a Handle; used to create a memberTable that acts like Table but + stores only Handle* internally to avoid memory copies. + */ + typedef _internal::Indirector Member; + + typedef Table MemberTable; + + /** Maps members to the node containing them */ + MemberTable memberTable; + + Node* root; + +public: + + /** To construct a balanced tree, insert the elements and then call + KDTree::balance(). */ + KDTree() : root(NULL) {} + + + KDTree(const KDTree& src) : root(NULL) { + *this = src; + } + + + KDTree& operator=(const KDTree& src) { + delete root; + // Clone tree takes care of filling out the memberTable. + root = cloneTree(src.root); + return *this; + } + + + ~KDTree() { + clear(); + } + + /** + Throws out all elements of the set. + */ + void clear() { + typedef typename Table<_internal::Indirector, Node*>::Iterator It; + + // Delete all handles stored in the member table + It cur = memberTable.begin(); + It end = memberTable.end(); + while (cur != end) { + delete cur->key.handle; + cur->key.handle = NULL; + ++cur; + } + memberTable.clear(); + + // Delete the tree structure itself + delete root; + root = NULL; + } + + int size() const { + return memberTable.size(); + } + + /** + Inserts an object into the set if it is not + already present. O(log n) time. Does not + cause the tree to be balanced. + */ + void insert(const T& value) { + if (contains(value)) { + // Already in the set + return; + } + + Handle* h = new Handle(value); + + if (root == NULL) { + // This is the first node; create a root node + root = new Node(); + } + + Node* node = root->findDeepestContainingNode(h->bounds); + + // Insert into the node + node->valueArray.append(h); + node->boundsArray.append(h->bounds); + + // Insert into the node table + Member m(h); + memberTable.set(m, node); + } + + /** Inserts each elements in the array in turn. If the tree + begins empty (no structure and no elements), this is faster + than inserting each element in turn. You still need to balance + the tree at the end.*/ + void insert(const Array& valueArray) { + if (root == NULL) { + // Optimized case for an empty tree; don't bother + // searching or reallocating the root node's valueArray + // as we incrementally insert. + root = new Node(); + root->valueArray.resize(valueArray.size()); + root->boundsArray.resize(root->valueArray.size()); + for (int i = 0; i < valueArray.size(); ++i) { + // Insert in opposite order so that we have the exact same + // data structure as if we inserted each (i.e., order is reversed + // from array). + Handle* h = new Handle(valueArray[i]); + int j = valueArray.size() - i - 1; + root->valueArray[j] = h; + root->boundsArray[j] = h->bounds; + memberTable.set(Member(h), root); + } + + } else { + // Insert at appropriate tree depth. + for (int i = 0; i < valueArray.size(); ++i) { + insert(valueArray[i]); + } + } + } + + + /** + Returns true if this object is in the set, otherwise + returns false. O(1) time. + */ + bool contains(const T& value) { + // Temporarily create a handle and member + Handle h(value); + return memberTable.containsKey(Member(&h)); + } + + + /** + Removes an object from the set in O(1) time. + It is an error to remove members that are not already + present. May unbalance the tree. + + Removing an element never causes a node (split plane) to be removed... + nodes are only changed when the tree is rebalanced. This behavior + is desirable because it allows the split planes to be serialized, + and then deserialized into an empty tree which can be repopulated. + */ + void remove(const T& value) { + debugAssertM(contains(value), + "Tried to remove an element from a " + "KDTree that was not present"); + + // Get the list of elements at the node + Handle h(value); + Member m(&h); + + Array& list = memberTable[m]->valueArray; + + Handle* ptr = NULL; + + // Find the element and remove it + for (int i = list.length() - 1; i >= 0; --i) { + if (list[i]->value == value) { + // This was the element. Grab the pointer so that + // we can delete it below + ptr = list[i]; + + // Remove the handle from the node + list.fastRemove(i); + + // Remove the corresponding bounds + memberTable[m]->boundsArray.fastRemove(i); + break; + } + } + + // Remove the member + memberTable.remove(m); + + // Delete the handle data structure + delete ptr; + ptr = NULL; + } + + + /** + If the element is in the set, it is removed. + The element is then inserted. + + This is useful when the == and hashCode methods + on T are independent of the bounds. In + that case, you may call update(v) to insert an + element for the first time and call update(v) + again every time it moves to keep the tree + up to date. + */ + void update(const T& value) { + if (contains(value)) { + remove(value); + } + insert(value); + } + + + /** + Rebalances the tree (slow). Call when objects + have moved substantially from their original positions + (which unbalances the tree and causes the spatial + queries to be slow). + + @param valuesPerNode Maximum number of elements to put at + a node. + + @param numMeanSplits numMeanSplits = 0 gives a + fully axis aligned BSP-tree, where the balance operation attempts to balance + the tree so that every splitting plane has an equal number of left + and right children (i.e. it is a median split along that axis). + This tends to maximize average performance. + + You can override this behavior by + setting a number of mean (average) splits. numMeanSplits = MAX_INT + creates a full oct-tree, which tends to optimize peak performance at the expense of + average performance. It tends to have better clustering behavior when + members are not uniformly distributed. + */ + void balance(int valuesPerNode = 5, int numMeanSplits = 3) { + if (root == NULL) { + // Tree is empty + return; + } + + // Get all handles and delete the old tree structure + Node* oldRoot = root; + for (int c = 0; c < 2; ++c) { + if (root->child[c] != NULL) { + root->child[c]->getHandles(root->valueArray); + + // Delete the child; this will delete all structure below it + delete root->child[c]; + root->child[c] = NULL; + } + } + + Array temp; + // Make a new root. Work with a copy of the value array because + // makeNode clears the source array as it progresses + Array copy(oldRoot->valueArray); + root = makeNode(copy, valuesPerNode, numMeanSplits, temp); + + // Throw away the old root node + delete oldRoot; + oldRoot = NULL; + + // Walk the tree, assigning splitBounds. We start with unbounded + // space. This will override the current member table. + const AABox& LARGE = AABox::large(); + root->assignSplitBounds(LARGE); + +# ifdef _DEBUG + { + // Ensure that the balanced tree is still correct + root->verifyNode(LARGE.low(), LARGE.high()); + } +# endif + } + + + /** Clear, set the contents to the values in the array, and then balance */ + void setContents(const Array& array, int valuesPerNode = 5, int numMeanSplits = 3) { + clear(); + insert(array); + balance(valuesPerNode, numMeanSplits); + } + + +protected: + + /** + @param parentMask The mask that this node returned from culledBy. + */ + static void getIntersectingMembers( + const Array& plane, + Array& members, + Node* node, + uint32 parentMask) { + + int dummy; + + if (parentMask == 0) { + // None of these planes can cull anything + for (int v = node->valueArray.size() - 1; v >= 0; --v) { + members.append(& (node->valueArray[v]->value)); + } + + // Iterate through child nodes + for (int c = 0; c < 2; ++c) { + if (node->child[c]) { + getIntersectingMembers(plane, members, node->child[c], 0); + } + } + } else { + + // Test values at this node against remaining planes + for (int v = node->boundsArray.size() - 1; v >= 0; --v) { + if (! node->boundsArray[v].culledBy(plane, dummy, parentMask)) { + members.append(&(node->valueArray[v]->value)); + } + } + + uint32 childMask = 0xFFFFFF; + + // Iterate through child nodes + for (int c = 0; c < 2; ++c) { + if (node->child[c] && + ! node->child[c]->splitBounds.culledBy(plane, dummy, parentMask, childMask)) { + // This node was not culled + getIntersectingMembers(plane, members, node->child[c], childMask); + } + } + } + } + +public: + + /** + Returns all members inside the set of planes. + @param members The results are appended to this array. + */ + void getIntersectingMembers(const Array& plane, Array& members) const { + if (root == NULL) { + return; + } + + getIntersectingMembers(plane, members, root, 0xFFFFFF); + } + + void getIntersectingMembers(const Array& plane, Array& members) const { + Array temp; + getIntersectingMembers(plane, temp, root, 0xFFFFFF); + for (int i = 0; i < temp.size(); ++i) { + members.append(*temp[i]); + } + } + + /** + Typically used to find all visible + objects inside the view frustum (see also GCamera::getClipPlanes)... i.e. all objects + not culled by frustum. + + Example: +
+        Array  visible;
+        tree.getIntersectingMembers(camera.frustum(), visible);
+        // ... Draw all objects in the visible array.
+      
+ @param members The results are appended to this array. + */ + void getIntersectingMembers(const GCamera::Frustum& frustum, Array& members) const { + Array plane; + + for (int i = 0; i < frustum.faceArray.size(); ++i) { + plane.append(frustum.faceArray[i].plane); + } + + getIntersectingMembers(plane, members); + } + + void getIntersectingMembers(const GCamera::Frustum& frustum, Array& members) const { + Array temp; + getIntersectingMembers(frustum, temp); + for (int i = 0; i < temp.size(); ++i) { + members.append(*temp[i]); + } + } + + /** + C++ STL style iterator variable. See beginBoxIntersection(). + The iterator overloads the -> (dereference) operator, so this + acts like a pointer to the current member. + */ + // This iterator turns Node::getIntersectingMembers into a + // coroutine. It first translates that method from recursive to + // stack based, then captures the system state (analogous to a Scheme + // continuation) after each element is appended to the member array, + // and allowing the computation to be restarted. + class BoxIntersectionIterator { + private: + friend class TreeType; + + /** True if this is the "end" iterator instance */ + bool isEnd; + + /** The box that we're testing against. */ + AABox box; + + /** Node that we're currently looking at. Undefined if isEnd + is true. */ + Node* node; + + /** Nodes waiting to be processed */ + // We could use backpointers within the tree and careful + // state management to avoid ever storing the stack-- but + // it is much easier this way and only inefficient if the + // caller uses post increment (which they shouldn't!). + Array stack; + + /** The next index of current->valueArray to return. + Undefined when isEnd is true.*/ + int nextValueArrayIndex; + + BoxIntersectionIterator() : isEnd(true) {} + + BoxIntersectionIterator(const AABox& b, const Node* root) : + isEnd(root == NULL), box(b), + node(const_cast(root)), nextValueArrayIndex(-1) { + + // We intentionally start at the "-1" index of the current + // node so we can use the preincrement operator to move + // ourselves to element 0 instead of repeating all of the + // code from the preincrement method. Note that this might + // cause us to become the "end" instance. + ++(*this); + } + + public: + + inline bool operator!=(const BoxIntersectionIterator& other) const { + return ! (*this == other); + } + + bool operator==(const BoxIntersectionIterator& other) const { + if (isEnd) { + return other.isEnd; + } else if (other.isEnd) { + return false; + } else { + // Two non-end iterators; see if they match. This is kind of + // silly; users shouldn't call == on iterators in general unless + // one of them is the end iterator. + if ((box != other.box) || (node != other.node) || + (nextValueArrayIndex != other.nextValueArrayIndex) || + (stack.length() != other.stack.length())) { + return false; + } + + // See if the stacks are the same + for (int i = 0; i < stack.length(); ++i) { + if (stack[i] != other.stack[i]) { + return false; + } + } + + // We failed to find a difference; they must be the same + return true; + } + } + + /** + Pre increment. + */ + BoxIntersectionIterator& operator++() { + ++nextValueArrayIndex; + + bool foundIntersection = false; + while (! isEnd && ! foundIntersection) { + + // Search for the next node if we've exhausted this one + while ((! isEnd) && (nextValueArrayIndex >= node->valueArray.length())) { + // If we entered this loop, then the iterator has exhausted the elements at + // node (possibly because it just switched to a child node with no members). + // This loop continues until it finds a node with members or reaches + // the end of the whole intersection search. + + // If the right child overlaps the box, push it onto the stack for + // processing. + if ((node->child[1] != NULL) && + (box.high()[node->splitAxis] > node->splitLocation)) { + stack.push(node->child[1]); + } + + // If the left child overlaps the box, push it onto the stack for + // processing. + if ((node->child[0] != NULL) && + (box.low()[node->splitAxis] < node->splitLocation)) { + stack.push(node->child[0]); + } + + if (stack.length() > 0) { + // Go on to the next node (which may be either one of the ones we + // just pushed, or one from farther back the tree). + node = stack.pop(); + nextValueArrayIndex = 0; + } else { + // That was the last node; we're done iterating + isEnd = true; + } + } + + // Search for the next intersection at this node until we run out of children + while (! isEnd && ! foundIntersection && (nextValueArrayIndex < node->valueArray.length())) { + if (box.intersects(node->boundsArray[nextValueArrayIndex])) { + foundIntersection = true; + } else { + ++nextValueArrayIndex; + // If we exhaust this node, we'll loop around the master loop + // to find a new node. + } + } + } + + return *this; + } + + private: + /** + Post increment (much slower than preincrement!). + Intentionally overloaded to preclude accidentally slow code. + */ + BoxIntersectionIterator operator++(int); + /*{ + BoxIntersectionIterator old = *this; + ++this; + return old; + }*/ + + public: + + /** Overloaded dereference operator so the iterator can masquerade as a pointer + to a member */ + const T& operator*() const { + alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); + return node->valueArray[nextValueArrayIndex]->value; + } + + /** Overloaded dereference operator so the iterator can masquerade as a pointer + to a member */ + T const * operator->() const { + alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); + return &(stack.last()->valueArray[nextValueArrayIndex]->value); + } + + /** Overloaded cast operator so the iterator can masquerade as a pointer + to a member */ + operator T*() const { + alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); + return &(stack.last()->valueArray[nextValueArrayIndex]->value); + } + }; + + + /** + Iterates through the members that intersect the box + */ + BoxIntersectionIterator beginBoxIntersection(const AABox& box) const { + return BoxIntersectionIterator(box, root); + } + + BoxIntersectionIterator endBoxIntersection() const { + // The "end" iterator instance + return BoxIntersectionIterator(); + } + + /** + Appends all members whose bounds intersect the box. + See also KDTree::beginBoxIntersection. + */ + void getIntersectingMembers(const AABox& box, Array& members) const { + if (root == NULL) { + return; + } + root->getIntersectingMembers(box, Sphere(Vector3::zero(), 0), members, false); + } + + void getIntersectingMembers(const AABox& box, Array& members) const { + Array temp; + getIntersectingMembers(box, temp); + for (int i = 0; i < temp.size(); ++i) { + members.append(*temp[i]); + } + } + + + /** + Invoke a callback for every member along a ray until the closest intersection is found. + + @param callback either a function or an instance of a class with an overloaded operator() of the form: + + void callback(const Ray& ray, const T& object, float& distance). If the ray hits the object + before travelling distance distance, updates distance with the new distance to + the intersection, otherwise leaves it unmodified. A common example is: + +
+     class Entity {
+     public:
+
+                void intersect(const Ray& ray, float& maxDist, Vector3& outLocation, Vector3& outNormal) {
+                    float d = maxDist;
+
+                    // ... search for intersection distance d
+
+                    if ((d > 0) && (d < maxDist)) {
+                        // Intersection occured
+                        maxDist = d;
+                        outLocation = ...;
+                        outNormal = ...;
+                    }
+                }
+            };
+
+            // Finds the surface normal and location of the first intersection with the scene
+            class Intersection {
+            public:
+                Entity*     closestEntity;
+                Vector3     hitLocation;
+                Vector3     hitNormal;
+
+                void operator()(const Ray& ray, const Entity* entity, float& distance) {
+                    entity->intersect(ray, distance, hitLocation, hitNormal);
+                }
+            };
+
+            KDTree scene;
+
+            Intersection intersection;
+            float distance = finf();
+            scene.intersectRay(camera.worldRay(x, y), intersection, distance);
+          
+ + + @param distance When the method is invoked, this is the maximum + distance that the tree should search for an intersection. On + return, this is set to the distance to the first intersection + encountered. + + @param intersectCallbackIsFast If false, each object's bounds are + tested before the intersectCallback is invoked. If the + intersect callback runs at the same speed or faster than + AABox-ray intersection, set this to true. + */ + template + void intersectRay( + const Ray& ray, + RayCallback& intersectCallback, + float& distance, + bool intersectCallbackIsFast = false) const { + + root->intersectRay(ray, intersectCallback, distance, intersectCallbackIsFast); + } + + + /** + @brief Finds all members whose bounding boxes intersect the sphere. The actual + elements may not intersect the sphere. + + @param members The results are appended to this array. + */ + void getIntersectingMembers(const Sphere& sphere, Array& members) const { + if (root == NULL) { + return; + } + + AABox box; + sphere.getBounds(box); + root->getIntersectingMembers(box, sphere, members, true); + } + + void getIntersectingMembers(const Sphere& sphere, Array& members) const { + Array temp; + getIntersectingMembers(sphere, temp); + for (int i = 0; i < temp.size(); ++i) { + members.append(*temp[i]); + } + } + + /** + Stores the locations of the splitting planes (the structure but not the content) + so that the tree can be quickly rebuilt from a previous configuration without + calling balance. + */ + void serializeStructure(BinaryOutput& bo) const { + Node::serializeStructure(root, bo); + } + + /** Clears the member table */ + void deserializeStructure(BinaryInput& bi) { + clear(); + root = Node::deserializeStructure(bi); + } + + /** + Returns an array of all members of the set. See also KDTree::begin. + */ + void getMembers(Array& members) const { + Array temp; + memberTable.getKeys(temp); + for (int i = 0; i < temp.size(); ++i) { + members.append(*(temp.handle)); + } + } + + + /** If a value that is EqualsFunc to @a value is present, returns a pointer to the + version stored in the data structure, otherwise returns NULL. + */ + const T* getPointer(const T& value) const { + // Temporarily create a handle and member + Handle h(value); + const Member* member = memberTable.getKeyPointer(Member(&h)); + if (member == NULL) { + // Not found + return NULL; + } else { + return &(member->handle->value); + } + } + + + /** + C++ STL style iterator variable. See begin(). + Overloads the -> (dereference) operator, so this acts like a pointer + to the current member. + */ + class Iterator { + private: + friend class TreeType; + + // Note: this is a Table iterator, we are currently defining + // Set iterator + typename Table::Iterator it; + + Iterator(const typename Table::Iterator& it) : it(it) {} + + public: + + inline bool operator!=(const Iterator& other) const { + return !(*this == other); + } + + bool operator==(const Iterator& other) const { + return it == other.it; + } + + /** + Pre increment. + */ + Iterator& operator++() { + ++it; + return *this; + } + + private: + /** + Post increment (slower than preincrement). Intentionally unimplemented to prevent slow code. + */ + Iterator operator++(int);/* { + Iterator old = *this; + ++(*this); + return old; + }*/ + public: + + const T& operator*() const { + return it->key.handle->value; + } + + T* operator->() const { + return &(it->key.handle->value); + } + + operator T*() const { + return &(it->key.handle->value); + } + }; + + + /** + C++ STL style iterator method. Returns the first member. + Use preincrement (++entry) to get to the next element (iteration + order is arbitrary). + Do not modify the set while iterating. + */ + Iterator begin() const { + return Iterator(memberTable.begin()); + } + + + /** + C++ STL style iterator method. Returns one after the last iterator + element. + */ + Iterator end() const { + return Iterator(memberTable.end()); + } +#undef TreeType +}; + + +} + +#endif diff --git a/externals/g3dlite/G3D/Line.h b/externals/g3dlite/G3D/Line.h new file mode 100644 index 00000000000..3579a6becec --- /dev/null +++ b/externals/g3dlite/G3D/Line.h @@ -0,0 +1,105 @@ +/** + @file Line.h + + Line class + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2001-06-02 + @edited 2006-02-28 + */ + +#ifndef G3D_LINE_H +#define G3D_LINE_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" + +namespace G3D { + +class Plane; + +/** + An infinite 3D line. + */ +class Line { +protected: + + Vector3 _point; + Vector3 _direction; + + Line(const Vector3& point, const Vector3& direction) { + _point = point; + _direction = direction.direction(); + } + +public: + + /** Undefined (provided for creating Array only) */ + inline Line() {} + + Line(class BinaryInput& b); + + void serialize(class BinaryOutput& b) const; + + void deserialize(class BinaryInput& b); + + virtual ~Line() {} + + /** + Constructs a line from two (not equal) points. + */ + static Line fromTwoPoints(const Vector3 &point1, const Vector3 &point2) { + return Line(point1, point2 - point1); + } + + /** + Creates a line from a point and a (nonzero) direction. + */ + static Line fromPointAndDirection(const Vector3& point, const Vector3& direction) { + return Line(point, direction); + } + + /** + Returns the closest point on the line to point. + */ + Vector3 closestPoint(const Vector3& pt) const; + + /** + Returns the distance between point and the line + */ + double distance(const Vector3& point) const { + return (closestPoint(point) - point).magnitude(); + } + + /** Returns a point on the line */ + Vector3 point() const; + + /** Returns the direction (or negative direction) of the line */ + Vector3 direction() const; + + /** + Returns the point where the line and plane intersect. If there + is no intersection, returns a point at infinity. + */ + Vector3 intersection(const Plane &plane) const; + + + /** Finds the closest point to the two lines. + + @param minDist Returns the minimum distance between the lines. + + @cite http://objectmix.com/graphics/133793-coordinates-closest-points-pair-skew-lines.html + */ + Vector3 closestPoint(const Line& B, float& minDist) const; + + inline Vector3 closestPoint(const Line& B) const { + float m; + return closestPoint(B, m); + } +}; + +};// namespace + + +#endif diff --git a/externals/g3dlite/G3D/LineSegment.h b/externals/g3dlite/G3D/LineSegment.h new file mode 100644 index 00000000000..70210ec7e00 --- /dev/null +++ b/externals/g3dlite/G3D/LineSegment.h @@ -0,0 +1,115 @@ +/** + @file LineSegment.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2003-02-08 + @edited 2008-02-02 + */ + +#ifndef G3D_LINESEGMENT_H +#define G3D_LINESEGMENT_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" + +namespace G3D { + +/** + An finite segment of an infinite 3D line. + */ +class LineSegment { +protected: + + Vector3 _point; + + /** Not normalized */ + Vector3 direction; + + LineSegment(const Vector3& __point, const Vector3& _direction) : _point(__point), direction(_direction) { + } + +public: + + inline LineSegment() : _point(Vector3::zero()), direction(Vector3::zero()) {} + + LineSegment(class BinaryInput& b); + + void serialize(class BinaryOutput& b) const; + + void deserialize(class BinaryInput& b); + + virtual ~LineSegment() {} + + /** + * Constructs a line from two (not equal) points. + */ + static LineSegment fromTwoPoints(const Vector3 &point1, const Vector3 &point2) { + return LineSegment(point1, point2 - point1); + } + + /** Call with 0 or 1 */ + Vector3 point(int i) const; + + inline float length() const { + return direction.magnitude(); + } + + /** + * Returns the closest point on the line segment to point. + */ + Vector3 closestPoint(const Vector3 &point) const; + + /** + Returns the distance between point and the line + */ + double distance(const Vector3& p) const { + return (closestPoint(p) - p).magnitude(); + } + + double distanceSquared(const Vector3& p) const { + return (closestPoint(p) - p).squaredMagnitude(); + } + + /** Returns true if some part of this segment is inside the sphere */ + bool intersectsSolidSphere(const class Sphere& s) const; + + Vector3 randomPoint() const; + +}; + + +class LineSegment2D { +private: + + Vector2 m_origin; + + /** Not normalized */ + Vector2 m_direction; + + /** Length of m_direction */ + float m_length; + +public: + + LineSegment2D() {} + + static LineSegment2D fromTwoPoints(const Vector2& p0, const Vector2& p1); + + /** Returns the intersection of these segements (including + testing endpoints), or Vector2::inf() if they do not intersect. */ + Vector2 intersection(const LineSegment2D& other) const; + + Vector2 point(int i) const; + + Vector2 closestPoint(const Vector2& Q) const; + + float distance(const Vector2& p) const; + + float length() const; +}; + +} // namespace + + +#endif diff --git a/externals/g3dlite/G3D/Log.h b/externals/g3dlite/G3D/Log.h new file mode 100644 index 00000000000..d252d0c1a17 --- /dev/null +++ b/externals/g3dlite/G3D/Log.h @@ -0,0 +1,109 @@ +/** + @file Log.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @cite Backtrace by Aaron Orenstein + @created 2001-08-04 + @edited 2005-11-04 + */ + +#ifndef G3D_LOG_H +#define G3D_LOG_H + +#include +#include +#include "G3D/platform.h" + +#ifndef G3D_WIN32 + #include +#endif + +namespace G3D { + +/** Prints to the common system log, log.txt, which is usually + in the working directory of the program. If your disk is + not writable or is slow, it will attempt to write to "c:/tmp/log.txt" or + "c:/temp/log.txt" on Windows systems instead. + + Unlike printf or debugPrintf, + this function guarantees that all output is committed before it returns. + This is very useful for debugging a crash, which might hide the last few + buffered print statements otherwise. + + Many G3D routines write useful warnings and debugging information to the + system log, which makes it a good first place to go when tracking down + a problem. + */ +void logPrintf(const char* fmt, ...); + +/** Does not flush the buffer; follow up with a logPrintf to force the flush. */ +void logLazyPrintf(const char* fmt, ...); + +/** + System log for debugging purposes. The first log opened + is the "common log" and can be accessed with the static + method common(). If you access common() and a common log + does not yet exist, one is created for you. + */ +class Log { +private: + + /** + Log messages go here. + */ + FILE* logFile; + + std::string filename; + + static Log* commonLog; + + int stripFromStackBottom; + +public: + + /** + @param stripFromStackBottom Number of call stacks to strip from the + bottom of the stack when printing a trace. Useful for hiding + routines like "main" and "WinMain". If the specified file cannot + be opened for some reason, tries to open "c:/tmp/log.txt" or + "c:/temp/log.txt" instead. + */ + Log(const std::string& filename = "log.txt", + int stripFromStackBottom = 0); + + virtual ~Log(); + + /** + Returns the handle to the file log. + */ + FILE* getFile() const; + + /** + Marks the beginning of a logfile section. + */ + void section(const std::string& s); + + /** + Given arguments like printf, writes characters to the debug text overlay. + */ + // We want G3D_CHECK_PRINTF_ARGS here, but that conflicts with the + // overload. + void __cdecl printf(const char* fmt, ...) G3D_CHECK_PRINTF_METHOD_ARGS; + + void __cdecl vprintf(const char*, va_list argPtr) G3D_CHECK_VPRINTF_METHOD_ARGS; + /** Does not flush */ + void __cdecl lazyvprintf(const char*, va_list argPtr) G3D_CHECK_VPRINTF_METHOD_ARGS; + + static Log* common(); + + static std::string getCommonLogFilename(); + + void print(const std::string& s); + + + void println(const std::string& s); +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/Map2D.h b/externals/g3dlite/G3D/Map2D.h new file mode 100644 index 00000000000..9af9f7242c1 --- /dev/null +++ b/externals/g3dlite/G3D/Map2D.h @@ -0,0 +1,667 @@ +/** + @file Map2D.h + + More flexible support than provided by G3D::GImage. + + @maintainer Morgan McGuire, morgan@cs.brown.edu + @created 2004-10-10 + @edited 2009-03-24 + */ +#ifndef G3D_Map2D_h +#define G3D_Map2D_h + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Array.h" +#include "G3D/vectorMath.h" +#include "G3D/Vector2int16.h" +#include "G3D/ReferenceCount.h" +#include "G3D/AtomicInt32.h" +#include "G3D/GThread.h" +#include "G3D/Rect2D.h" +#include "G3D/WrapMode.h" + +#include + +namespace G3D { +namespace _internal { + +/** The default compute type for a type is the type itself. */ +template class _GetComputeType { +public: + typedef Storage Type; +}; + +} // _internal +} // G3D + +// This weird syntax is needed to support VC6, which doesn't +// properly implement template overloading. +#define DECLARE_COMPUTE_TYPE(StorageType, ComputeType) \ +namespace G3D { \ + namespace _internal { \ + template<> class _GetComputeType < StorageType > { \ + public: \ + typedef ComputeType Type; \ + }; \ + } \ +} + +DECLARE_COMPUTE_TYPE( float32, float64) +DECLARE_COMPUTE_TYPE( float64, float64) + +DECLARE_COMPUTE_TYPE( int8, float32) +DECLARE_COMPUTE_TYPE( int16, float32) +DECLARE_COMPUTE_TYPE( int32, float64) +DECLARE_COMPUTE_TYPE( int64, float64) + +DECLARE_COMPUTE_TYPE( uint8, float32) +DECLARE_COMPUTE_TYPE( uint16, float32) +DECLARE_COMPUTE_TYPE( uint32, float64) +DECLARE_COMPUTE_TYPE( uint64, float64) + +DECLARE_COMPUTE_TYPE( Vector2, Vector2) +DECLARE_COMPUTE_TYPE( Vector2int16, Vector2) + +DECLARE_COMPUTE_TYPE( Vector3, Vector3) +DECLARE_COMPUTE_TYPE( Vector3int16, Vector3) + +DECLARE_COMPUTE_TYPE( Vector4, Vector4) + +DECLARE_COMPUTE_TYPE( Color3, Color3) +DECLARE_COMPUTE_TYPE( Color3uint8, Color3) + +DECLARE_COMPUTE_TYPE( Color4, Color4) +DECLARE_COMPUTE_TYPE( Color4uint8, Color4) +#undef DECLARE_COMPUTE_TYPE + +namespace G3D { + +/** + Map of values across a discrete 2D plane. Can be thought of as a generic class for 2D images, + allowing flexibility as to pixel format and convenient methods. + In fact, the "pixels" can be any values + on a grid that can be sensibly interpolated--RGB colors, scalars, 4D vectors, and so on. + + Other "image" classes in G3D: + + G3D::GImage - Supports file formats, fast, Color3uint8 and Color4uint8 formats. No interpolation. + + G3D::Texture::Ref - Represents image on the graphics card (not directly readable on the CPU). Supports 2D, 3D, and a variety of interpolation methods, loads file formats. + + G3D::Image3 - A subclass of Map2D that supports image loading and saving and conversion to Texture. + + G3D::Image4 - A subclass of Map2D that supports image loading and saving and conversion to Texture. + + G3D::Image3uint8 - A subclass of Map2D that supports image loading and saving and conversion to Texture. + + G3D::Image4uint8 - A subclass of Map2D that supports image loading and saving and conversion to Texture. + + There are two type parameters-- the first (@ Storage) is the type + used to store the "pixel" values efficiently and + the second (@a Compute) is + the type operated on by computation. The Compute::Compute(Storage&) constructor + is used to convert between storage and computation types. + @a Storage is often an integer version of @a Compute, for example + Map2D. By default, the computation type is: + +
+     Storage       Computation
+
+     uint8          float32
+     uint16         float32
+     uint32         float64
+     uint64         float64
+
+     int8           float32
+     int16          float32
+     int32          float64
+     int64          float64
+
+     float32        float64
+     float64        float64
+
+     Vector2        Vector2
+     Vector2int16   Vector2
+
+     Vector3        Vector3
+     Vector3int16   Vector3
+
+     Vector4        Vector4
+
+     Color3         Color3
+     Color3uint8    Color3
+
+     Color4         Color4
+     Color4uint8    Color4
+    
+ Any other storage type defaults to itself as the computation type. + + The computation type can be any that + supports lerp, +, -, *, /, and an empty constructor. + + Assign value: + + im->set(x, y, 7); or + im->get(x, y) = 7; + + Read value: + + int c = im(x, y); + + Can also sample with nearest neighbor, bilinear, and bicubic + interpolation. + + Sampling follows OpenGL conventions, where + pixel values represent grid points and (0.5, 0.5) is half-way + between two vertical and two horizontal grid points. + To draw an image of dimensions w x h with nearest neighbor + sampling, render pixels from [0, 0] to [w - 1, h - 1]. + + Under the WrapMode::CLAMP wrap mode, the value of bilinear interpolation + becomes constant outside [1, w - 2] horizontally. Nearest neighbor + interpolation is constant outside [0, w - 1] and bicubic outside + [3, w - 4]. The class does not offer quadratic interpolation because + the interpolation filter could not center over a pixel. + + @author Morgan McGuire, http://graphics.cs.williams.edu + */ +template< typename Storage, +typename Compute = typename G3D::_internal::_GetComputeType::Type> +class Map2D : public ReferenceCountedObject { + +// +// It doesn't make sense to automatically convert from Compute back to Storage +// because the rounding rule (and scaling) is application dependent. +// Thus the interpolation methods all return type Compute. +// + +public: + + typedef Storage StorageType; + typedef Compute ComputeType; + typedef Map2D Type; + typedef ReferenceCountedPointer Ref; + +protected: + + Storage ZERO; + + /** Width, in pixels. */ + uint32 w; + + /** Height, in pixels. */ + uint32 h; + + WrapMode _wrapMode; + + /** 0 if no mutating method has been invoked + since the last call to setChanged(); */ + AtomicInt32 m_changed; + + Array data; + + /** Handles the exceptional cases from get */ + const Storage& slowGet(int x, int y, WrapMode wrap) { + switch (wrap) { + case WrapMode::CLAMP: + return fastGet(iClamp(x, 0, w - 1), iClamp(y, 0, h - 1)); + + case WrapMode::TILE: + return fastGet(iWrap(x, w), iWrap(y, h)); + + case WrapMode::ZERO: + return ZERO; + + case WrapMode::ERROR: + alwaysAssertM(((uint32)x < w) && ((uint32)y < h), + format("Index out of bounds: (%d, %d), w = %d, h = %d", + x, y, w, h)); + + // intentionally fall through + case WrapMode::IGNORE: + // intentionally fall through + default: + { + static Storage temp; + return temp; + } + } + } + +public: + + /** Unsafe access to the underlying data structure with no wrapping support; requires that (x, y) is in bounds. */ + inline const Storage& fastGet(int x, int y) const { + debugAssert(((uint32)x < w) && ((uint32)y < h)); + return data[x + y * w]; + } + + /** Unsafe access to the underlying data structure with no wrapping support; requires that (x, y) is in bounds. */ + inline void fastSet(int x, int y, const Storage& v) { + debugAssert(((uint32)x < w) && ((uint32)y < h)); + data[x + y * w] = v; + } + +protected: + + /** Given four control points and a value on the range [0, 1) + evaluates the Catmull-rom spline between the times of the + middle two control points */ + Compute bicubic(const Compute* ctrl, double s) const { + + // f = B * S * ctrl' + + // B matrix: Catmull-Rom spline basis + static const double B[4][4] = { + { 0.0, -0.5, 1.0, -0.5}, + { 1.0, 0.0, -2.5, 1.5}, + { 0.0, 0.5, 2.0, -1.5}, + { 0.0, 0.0, -0.5, 0.5}}; + + // S: Powers of the fraction + double S[4]; + double s2 = s * s; + S[0] = 1.0; + S[1] = s; + S[2] = s2; + S[3] = s2 * s; + + Compute sum(ZERO); + + for (int c = 0; c < 4; ++c) { + double coeff = 0.0; + for (int power = 0; power < 4; ++power) { + coeff += B[c][power] * S[power]; + } + sum += ctrl[c] * coeff; + } + + return sum; + } + + + Map2D(int w, int h, WrapMode wrap) : w(0), h(0), _wrapMode(wrap), m_changed(1) { + ZERO = Storage(Compute(Storage()) * 0); + resize(w, h); + } + +public: + + /** + Although Map2D is not threadsafe (except for the setChanged() method), + you can use this mutex to create your own threadsafe access to a Map2D. + Not used by the default implementation. + */ + GMutex mutex; + + static Ref create(int w = 0, int h = 0, WrapMode wrap = WrapMode::ERROR) { + return new Map2D(w, h, wrap); + } + + /** Resizes without clearing, leaving garbage. + */ + void resize(uint32 newW, uint32 newH) { + if ((newW != w) || (newH != h)) { + w = newW; + h = newH; + data.resize(w * h); + setChanged(true); + } + } + + /** + Returns true if this map has been written to since the last call to setChanged(false). + This is useful if you are caching a texture map other value that must be recomputed + whenever this changes. + */ + bool changed() { + return m_changed.value() != 0; + } + + /** Set/unset the changed flag. */ + void setChanged(bool c) { + m_changed = c ? 1 : 0; + } + + /** Returns a pointer to the underlying row-major data. There is no padding at the end of the row. + Be careful--this will be reallocated during a resize. You should call setChanged(true) if you mutate the array.*/ + Storage* getCArray() { + return data.getCArray(); + } + + + const Storage* getCArray() const { + return data.getCArray(); + } + + + /** Row-major array. You should call setChanged(true) if you mutate the array. */ + Array& getArray() { + return data; + } + + + const Array& getArray() const { + return data; + } + + /** is (x, y) strictly within the image bounds, or will it trigger some kind of wrap mode */ + inline bool inBounds(int x, int y) const { + return (((uint32)x < w) && ((uint32)y < h)); + } + + /** is (x, y) strictly within the image bounds, or will it trigger some kind of wrap mode */ + inline bool inBounds(const Vector2int16& v) const { + return inBounds(v.x, v.y); + } + + /** Get the value at (x, y). + + Note that the type of image->get(x, y) is + the storage type, not the computation + type. If the constructor promoting Storage to Compute rescales values + (as, for example Color3(Color3uint8&) does), this will not match the value + returned by Map2D::nearest. + */ + inline const Storage& get(int x, int y, WrapMode wrap) const { + if (((uint32)x < w) && ((uint32)y < h)) { + return data[x + y * w]; + } else { + // Remove the const to allow a slowGet on this object + // (we're returning a const reference so this is ok) + return const_cast(this)->slowGet(x, y, wrap); + } +# ifndef G3D_WIN32 + // gcc gives a useless warning that the above code might reach the end of the function; + // we use this line to supress the warning. + return ZERO; +# endif + } + + inline const Storage& get(int x, int y) const { + return get(x, y, _wrapMode); + } + + inline const Storage& get(const Vector2int16& p) const { + return get(p.x, p.y, _wrapMode); + } + + inline const Storage& get(const Vector2int16& p, WrapMode wrap) const { + return get(p.x, p.y, wrap); + } + + inline Storage& get(int x, int y, WrapMode wrap) { + return const_cast(const_cast(this)->get(x, y, wrap)); +# ifndef G3D_WIN32 + // gcc gives a useless warning that the above code might reach the end of the function; + // we use this line to supress the warning. + return ZERO; +# endif + } + + inline Storage& get(int x, int y) { + return const_cast(const_cast(this)->get(x, y)); +# ifndef G3D_WIN32 + // gcc gives a useless warning that the above code might reach the end of the function; + // we use this line to supress the warning. + return ZERO; +# endif + } + + inline Storage& get(const Vector2int16& p) { + return get(p.x, p.y); + } + + /** Sets the changed flag to true */ + inline void set(const Vector2int16& p, const Storage& v) { + set(p.x, p.y, v); + } + + /** Sets the changed flag to true */ + void set(int x, int y, const Storage& v, WrapMode wrap) { + setChanged(true); + if (((uint32)x < w) && ((uint32)y < h)) { + // In bounds, wrapping isn't an issue. + data[x + y * w] = v; + } else { + const_cast(slowGet(x, y, wrap)) = v; + } + } + + void set(int x, int y, const Storage& v) { + set(x, y, v, _wrapMode); + } + + + void setAll(const Storage& v) { + for(int i = 0; i < data.size(); ++i) { + data[i] = v; + } + setChanged(true); + } + + /** flips if @a flip is true*/ + void maybeFlipVertical(bool flip) { + if (flip) { + flipVertical(); + } + } + + virtual void flipVertical() { + int halfHeight = h/2; + Storage* d = data.getCArray(); + for (int y = 0; y < halfHeight; ++y) { + int o1 = y * w; + int o2 = (h - y - 1) * w; + for (int x = 0; x < (int)w; ++x) { + int i1 = o1 + x; + int i2 = o2 + x; + Storage temp = d[i1]; + d[i1] = d[i2]; + d[i2] = temp; + } + } + setChanged(true); + } + + virtual void flipHorizontal() { + int halfWidth = w / 2; + Storage* d = data.getCArray(); + for (int x = 0; x < halfWidth; ++x) { + for (int y = 0; y < (int)h; ++y) { + int i1 = y * w + x; + int i2 = y * w + (w - x - 1); + Storage temp = d[i1]; + d[i1] = d[i2]; + d[i2] = temp; + } + } + setChanged(true); + } + + /** + Crops this map so that it only contains pixels between (x, y) and (x + w - 1, y + h - 1) inclusive. + */ + virtual void crop(int newX, int newY, int newW, int newH) { + alwaysAssertM(newX + newW <= (int)w, "Cannot grow when cropping"); + alwaysAssertM(newY + newH <= (int)h, "Cannot grow when cropping"); + alwaysAssertM(newX >= 0 && newY >= 0, "Origin out of bounds."); + + // Always safe to copy towards the upper left, provided + // that we're iterating towards the lower right. This lets us avoid + // reallocating the underlying array. + for (int y = 0; y < newH; ++y) { + for (int x = 0; x < newW; ++x) { + data[x + y * newW] = data[(x + newX) + (y + newY) * w]; + } + } + + resize(newW, newH); + } + + /** iRounds to the nearest x0 and y0. */ + virtual void crop(const Rect2D& rect) { + crop(iRound(rect.x0()), iRound(rect.y0()), iRound(rect.x1()) - iRound(rect.x0()), iRound(rect.y1()) - iRound(rect.y0())); + } + + /** Returns the nearest neighbor. Pixel values are considered + to be at the upper left corner, so image->nearest(x, y) == image(x, y) + */ + inline Compute nearest(float x, float y, WrapMode wrap) const { + int ix = iRound(x); + int iy = iRound(y); + return Compute(get(ix, iy, wrap)); + } + + inline Compute nearest(float x, float y) const { + return nearest(x, y, _wrapMode); + } + + inline Compute nearest(const Vector2& p) const { + return nearest(p.x, p.y); + } + + /** Returns the average value of all elements of the map */ + Compute average() const { + if ((w == 0) || (h == 0)) { + return ZERO; + } + + // To avoid overflows, compute the average of row averages + + Compute rowSum = ZERO; + for (unsigned int y = 0; y < h; ++y) { + Compute sum = ZERO; + int offset = y * w; + for (unsigned int x = 0; x < w; ++x) { + sum += Compute(data[offset + x]); + } + rowSum += sum * (1.0f / w); + } + + return rowSum * (1.0f / h); + } + + /** + Needs to access elements from (floor(x), floor(y)) + to (floor(x) + 1, floor(y) + 1) and will use + the wrap mode appropriately (possibly generating + out of bounds errors). + + Guaranteed to match nearest(x, y) at integers. */ + Compute bilinear(float x, float y, WrapMode wrap) const { + const int i = iFloor(x); + const int j = iFloor(y); + + const float fX = x - i; + const float fY = y - j; + + // Horizontal interpolation, first row + const Compute& t0 = get(i, j, wrap); + const Compute& t1 = get(i + 1, j, wrap); + + // Horizontal interpolation, second row + const Compute& t2 = get(i, j + 1, wrap); + const Compute& t3 = get(i + 1, j + 1, wrap); + + const Compute& A = lerp(t0, t1, fX); + const Compute& B = lerp(t2, t3, fX); + + // Vertical interpolation + return lerp(A, B, fY); + } + + Compute bilinear(float x, float y) const { + return bilinear(x, y, _wrapMode); + } + + inline Compute bilinear(const Vector2& p) const { + return bilinear(p.x, p.y, _wrapMode); + } + + inline Compute bilinear(const Vector2& p, WrapMode wrap) const { + return bilinear(p.x, p.y, wrap); + } + + /** + Uses Catmull-Rom splines to interpolate between grid + values. Guaranteed to match nearest(x, y) at integers. + */ + Compute bicubic(float x, float y, WrapMode wrap) const { + int i = iFloor(x); + int j = iFloor(y); + float fX = x - i; + float fY = y - j; + + Compute vsample[4]; + for (int v = 0; v < 4; ++v) { + + // Horizontal interpolation + Compute hsample[4]; + for (int u = 0; u < 4; ++u) { + hsample[u] = Compute(get(i + u - 1, j + v - 1, wrap)); + } + + vsample[v] = bicubic(hsample, fX); + } + + // Vertical interpolation + return bicubic(vsample, fY); + } + + Compute bicubic(float x, float y) const { + return bicubic(x, y, _wrapMode); + } + + inline Compute bicubic(const Vector2& p, WrapMode wrap) const { + return bicubic(p.x, p.y, wrap); + } + + inline Compute bicubic(const Vector2& p) const { + return bicubic(p.x, p.y, _wrapMode); + } + + /** Pixel width */ + inline int32 width() const { + return (int32)w; + } + + + /** Pixel height */ + inline int32 height() const { + return (int32)h; + } + + + /** Dimensions in pixels */ + Vector2int16 size() const { + return Vector2int16(w, h); + } + + /** Rectangle from (0, 0) to (w, h) */ + Rect2D rect2DBounds() const { + return Rect2D::xywh(0, 0, w, h); + } + + /** Number of bytes occupied by the image data and this structure */ + size_t sizeInMemory() const { + return data.size() * sizeof(Storage) + sizeof(*this); + } + + + WrapMode wrapMode() const { + return _wrapMode; + } + + + void setWrapMode(WrapMode m) { + _wrapMode = m; + } +}; + + + +} + +#endif // G3D_IMAGE_H diff --git a/externals/g3dlite/G3D/Matrix.h b/externals/g3dlite/G3D/Matrix.h new file mode 100644 index 00000000000..3c5394d9a76 --- /dev/null +++ b/externals/g3dlite/G3D/Matrix.h @@ -0,0 +1,634 @@ +/** + @file Matrix.h + @author Morgan McGuire, http://graphics.cs.williams.edu + + @created 2005-10-23 + @edited 2007-07-18 + */ + +#ifndef G3D_MATRIX_H +#define G3D_MATRIX_H + +#include "G3D/g3dmath.h" +#include "G3D/Vector3.h" +#include "G3D/Vector4.h" +#include "G3D/Matrix3.h" +#include "G3D/Matrix4.h" +#include "G3D/ReferenceCount.h" + +namespace G3D { + +/** + N x M matrix. + + The actual data is tracked internally by a reference counted pointer; + it is efficient to pass and assign Matrix objects because no data is actually copied. + This avoids the headache of pointers and allows natural math notation: + +
+    Matrix A, B, C;
+    // ...
+
+    C = A * f(B);
+    C = C.inverse();
+
+    A = Matrix::identity(4);
+    C = A;
+    C.set(0, 0, 2.0); // Triggers a copy of the data so that A remains unchanged.
+
+    // etc.
+
+  
+ + The Matrix::debugNumCopyOps and Matrix::debugNumAllocOps counters + increment every time an operation forces the copy and allocation of matrices. You + can use these to detect slow operations when efficiency is a major concern. + + Some methods accept an output argument instead of returning a value. For example, + A = B.transpose() can also be invoked as B.transpose(A). + The latter may be more efficient, since Matrix may be able to re-use the storage of + A (if it has approximatly the right size and isn't currently shared with another matrix). + + @sa G3D::Matrix3, G3D::Matrix4, G3D::Vector2, G3D::Vector3, G3D::Vector4, G3D::CoordinateFrame + + @beta + */ +class Matrix { +public: + /** + Internal precision. Currently float, but this may become a templated class in the future + to allow operations like Matrix and Matrix. + + Not necessarily a plain-old-data type (e.g., could ComplexFloat), but must be something + with no constructor, that can be safely memcpyd, and that has a bit pattern of all zeros + when zero.*/ + typedef float T; + + /** Incremented every time the elements of a matrix are copied. Useful for profiling your + own code that uses Matrix to determine when it is slow due to copying.*/ + static int debugNumCopyOps; + + /** Incremented every time a new matrix object is allocated. Useful for profiling your + own code that uses Matrix to determine when it is slow due to allocation.*/ + static int debugNumAllocOps; + +private: +public: + + /** Used internally by Matrix. + + Does not throw exceptions-- assumes the caller has taken care of + argument checking. */ + class Impl : public ReferenceCountedObject { + public: + + static void* operator new(size_t size) { + return System::malloc(size); + } + + static void operator delete(void* p) { + System::free(p); + } + + ~Impl(); + + private: + friend class Matrix; + + /** elt[r][c] = the element. Pointers into data.*/ + T** elt; + + /** Row major data for the entire matrix. */ + T* data; + + /** The number of rows */ + int R; + + /** The number of columns */ + int C; + + int dataSize; + + /** If R*C is much larger or smaller than the current, deletes all previous data + and resets to random data. Otherwise re-uses existing memory and just resets + R, C, and the row pointers. */ + void setSize(int newRows, int newCols); + + inline Impl() : elt(NULL), data(NULL), R(0), C(0), dataSize(0) {} + + Impl(const Matrix3& M); + + Impl(const Matrix4& M); + + inline Impl(int r, int c) : elt(NULL), data(NULL), R(0), C(0), dataSize(0) { + setSize(r, c); + } + + Impl& operator=(const Impl& m); + + inline Impl(const Impl& B) : elt(NULL), data(NULL), R(0), C(0), dataSize(0) { + // Use the assignment operator + *this = B; + } + + void setZero(); + + inline void set(int r, int c, T v) { + debugAssert(r < R); + debugAssert(c < C); + elt[r][c] = v; + } + + inline const T& get(int r, int c) const { + debugAssert(r < R); + debugAssert(c < C); + return elt[r][c]; + } + + /** Multiplies this by B and puts the result in out. */ + void mul(const Impl& B, Impl& out) const; + + /** Ok if out == this or out == B */ + void add(const Impl& B, Impl& out) const; + + /** Ok if out == this or out == B */ + void add(T B, Impl& out) const; + + /** Ok if out == this or out == B */ + void sub(const Impl& B, Impl& out) const; + + /** Ok if out == this or out == B */ + void sub(T B, Impl& out) const; + + /** B - this */ + void lsub(T B, Impl& out) const; + + /** Ok if out == this or out == B */ + void arrayMul(const Impl& B, Impl& out) const; + + /** Ok if out == this or out == B */ + void mul(T B, Impl& out) const; + + /** Ok if out == this or out == B */ + void arrayDiv(const Impl& B, Impl& out) const; + + /** Ok if out == this or out == B */ + void div(T B, Impl& out) const; + + void negate(Impl& out) const; + + /** Slow way of computing an inverse; for reference */ + void inverseViaAdjoint(Impl& out) const; + + /** Use Gaussian elimination with pivots to solve for the inverse destructively in place. */ + void inverseInPlaceGaussJordan(); + + void adjoint(Impl& out) const; + + /** Matrix of all cofactors */ + void cofactor(Impl& out) const; + + /** + Cofactor [r][c] is defined as C[r][c] = -1 ^(r+c) * det(A[r][c]), + where A[r][c] is the (R-1)x(C-1) matrix formed by removing row r and + column c from the original matrix. + */ + T cofactor(int r, int c) const; + + /** Ok if out == this or out == B */ + void transpose(Impl& out) const; + + T determinant() const; + + /** Determinant computed without the given row and column */ + T determinant(int r, int c) const; + + void arrayLog(Impl& out) const; + + void arrayExp(Impl& out) const; + + void arraySqrt(Impl& out) const; + + void arrayCos(Impl& out) const; + + void arraySin(Impl& out) const; + + void swapRows(int r0, int r1); + + void swapAndNegateCols(int c0, int c1); + + void mulRow(int r, const T& v); + + void abs(Impl& out) const; + + /** Makes a (R-1)x(C-1) copy of this matrix */ + void withoutRowAndCol(int excludeRow, int excludeCol, Impl& out) const; + + bool anyNonZero() const; + + bool allNonZero() const; + + void setRow(int r, const T* vals); + + void setCol(int c, const T* vals); + }; +private: + + typedef ReferenceCountedPointer ImplRef; + + ImplRef impl; + + inline Matrix(ImplRef i) : impl(i) {} + inline Matrix(Impl* i) : impl(ImplRef(i)) {} + + /** Used by SVD */ + class SortRank { + public: + T value; + int col; + + inline bool operator>(const SortRank& x) const { + return x.value > value; + } + + inline bool operator<(const SortRank& x) const { + return x.value < value; + } + + inline bool operator>=(const SortRank& x) const { + return x.value >= value; + } + + inline bool operator<=(const SortRank& x) const { + return x.value <= value; + } + + inline bool operator==(const SortRank& x) const { + return x.value == value; + } + + inline bool operator!=(const SortRank& x) const { + return x.value != value; + } + }; + + Matrix vectorPseudoInverse() const; + Matrix partitionPseudoInverse() const; + Matrix colPartPseudoInverse() const; + Matrix rowPartPseudoInverse() const; + + Matrix col2PseudoInverse(const Matrix& B) const; + Matrix col3PseudoInverse(const Matrix& B) const; + Matrix col4PseudoInverse(const Matrix& B) const; + Matrix row2PseudoInverse(const Matrix& B) const; + Matrix row3PseudoInverse(const Matrix& B) const; + Matrix row4PseudoInverse(const Matrix& B) const; + +public: + + Matrix() : impl(new Impl(0, 0)) {} + + Matrix(const Matrix3& M) : impl(new Impl(M)) {} + + Matrix(const Matrix4& M) : impl(new Impl(M)) {} + + template + static Matrix fromDiagonal(const Array& d) { + Matrix D = zero(d.length(), d.length()); + for (int i = 0; i < d.length(); ++i) { + D.set(i, i, d[i]); + } + return D; + } + + static Matrix fromDiagonal(const Matrix& d); + + /** Returns a new matrix that is all zero. */ + Matrix(int R, int C) : impl(new Impl(R, C)) { + impl->setZero(); + } + + /** Returns a new matrix that is all zero. */ + static Matrix zero(int R, int C); + + /** Returns a new matrix that is all one. */ + static Matrix one(int R, int C); + + /** Returns a new identity matrix */ + static Matrix identity(int N); + + /** Uniformly distributed values between zero and one. */ + static Matrix random(int R, int C); + + /** The number of rows */ + inline int rows() const { + return impl->R; + } + + /** Number of columns */ + inline int cols() const { + return impl->C; + } + + /** Generally more efficient than A * B */ + Matrix& operator*=(const T& B); + + /** Generally more efficient than A / B */ + Matrix& operator/=(const T& B); + + /** Generally more efficient than A + B */ + Matrix& operator+=(const T& B); + + /** Generally more efficient than A - B */ + Matrix& operator-=(const T& B); + + /** No performance advantage over A * B because + matrix multiplication requires intermediate + storage. */ + Matrix& operator*=(const Matrix& B); + + /** Generally more efficient than A + B */ + Matrix& operator+=(const Matrix& B); + + /** Generally more efficient than A - B */ + Matrix& operator-=(const Matrix& B); + + /** Returns a new matrix that is a subset of this one, + from r1:r2 to c1:c2, inclusive.*/ + Matrix subMatrix(int r1, int r2, int c1, int c2) const; + + /** Matrix multiplication. To perform element-by-element multiplication, + see arrayMul. */ + inline Matrix operator*(const Matrix& B) const { + Matrix C(impl->R, B.impl->C); + impl->mul(*B.impl, *C.impl); + return C; + } + + /** See also A *= B, which is more efficient in many cases */ + inline Matrix operator*(const T& B) const { + Matrix C(impl->R, impl->C); + impl->mul(B, *C.impl); + return C; + } + + /** See also A += B, which is more efficient in many cases */ + inline Matrix operator+(const Matrix& B) const { + Matrix C(impl->R, impl->C); + impl->add(*B.impl, *C.impl); + return C; + } + + /** See also A -= B, which is more efficient in many cases */ + inline Matrix operator-(const Matrix& B) const { + Matrix C(impl->R, impl->C); + impl->sub(*B.impl, *C.impl); + return C; + } + + /** See also A += B, which is more efficient in many cases */ + inline Matrix operator+(const T& v) const { + Matrix C(impl->R, impl->C); + impl->add(v, *C.impl); + return C; + } + + /** See also A -= B, which is more efficient in many cases */ + inline Matrix operator-(const T& v) const { + Matrix C(impl->R, impl->C); + impl->sub(v, *C.impl); + return C; + } + + + Matrix operator>(const T& scalar) const; + + Matrix operator<(const T& scalar) const; + + Matrix operator>=(const T& scalar) const; + + Matrix operator<=(const T& scalar) const; + + Matrix operator==(const T& scalar) const; + + Matrix operator!=(const T& scalar) const; + + /** scalar B - this */ + inline Matrix lsub(const T& B) const { + Matrix C(impl->R, impl->C); + impl->lsub(B, *C.impl); + return C; + } + + inline Matrix arrayMul(const Matrix& B) const { + Matrix C(impl->R, impl->C); + impl->arrayMul(*B.impl, *C.impl); + return C; + } + + Matrix3 toMatrix3() const; + + Matrix4 toMatrix4() const; + + Vector2 toVector2() const; + + Vector3 toVector3() const; + + Vector4 toVector4() const; + + /** Mutates this */ + void arrayMulInPlace(const Matrix& B); + + /** Mutates this */ + void arrayDivInPlace(const Matrix& B); + + // Declares an array unary method and its explicit-argument counterpart +# define DECLARE_METHODS_1(method)\ + inline Matrix method() const {\ + Matrix C(impl->R, impl->C);\ + impl->method(*C.impl);\ + return C;\ + }\ + void method(Matrix& out) const; + + + DECLARE_METHODS_1(abs) + DECLARE_METHODS_1(arrayLog) + DECLARE_METHODS_1(arrayExp) + DECLARE_METHODS_1(arraySqrt) + DECLARE_METHODS_1(arrayCos) + DECLARE_METHODS_1(arraySin) + DECLARE_METHODS_1(negate) + +# undef DECLARE_METHODS_1 + + inline Matrix operator-() const { + return negate(); + } + + /** + A-1 computed using the Gauss-Jordan algorithm, + for square matrices. + Run time is O(R3), where R is the + number of rows. + */ + inline Matrix inverse() const { + Impl* A = new Impl(*impl); + A->inverseInPlaceGaussJordan(); + return Matrix(A); + } + + inline T determinant() const { + return impl->determinant(); + } + + /** + AT + */ + inline Matrix transpose() const { + Impl* A = new Impl(cols(), rows()); + impl->transpose(*A); + return Matrix(A); + } + + /** Transpose in place; more efficient than transpose */ + void transpose(Matrix& out) const; + + inline Matrix adjoint() const { + Impl* A = new Impl(cols(), rows()); + impl->adjoint(*A); + return Matrix(A); + } + + /** + (ATA)-1AT) computed + using SVD. + + @param tolerance Use -1 for automatic tolerance. + */ + Matrix pseudoInverse(float tolerance = -1) const; + + /** Called from pseudoInverse when the matrix has size > 4 along some dimension.*/ + Matrix svdPseudoInverse(float tolerance = -1) const; + + /** + (ATA)-1AT) computed + using Gauss-Jordan elimination. + */ + inline Matrix gaussJordanPseudoInverse() const { + Matrix trans = transpose(); + return (trans * (*this)).inverse() * trans; + } + + /** Singular value decomposition. Factors into three matrices + such that @a this = @a U * fromDiagonal(@a d) * @a V.transpose(). + + The matrix must have at least as many rows as columns. + + Run time is O(C2*R). + + @param sort If true (default), the singular values + are arranged so that D is sorted from largest to smallest. + */ + void svd(Matrix& U, Array& d, Matrix& V, bool sort = true) const; + + void set(int r, int c, T v); + + void setCol(int c, const Matrix& vec); + + void setRow(int r, const Matrix& vec); + + Matrix col(int c) const; + + Matrix row(int r) const; + + T get(int r, int c) const; + + Vector2int16 size() const { + return Vector2int16(rows(), cols()); + } + + int numElements() const { + return rows() * cols(); + } + + void swapRows(int r0, int r1); + + /** Swaps columns c0 and c1 and negates both */ + void swapAndNegateCols(int c0, int c1); + + void mulRow(int r, const T& v); + + /** Returns true if any element is non-zero */ + bool anyNonZero() const; + + /** Returns true if all elements are non-zero */ + bool allNonZero() const; + + inline bool allZero() const { + return !anyNonZero(); + } + + inline bool anyZero() const { + return !allNonZero(); + } + + /** Serializes in Matlab source format */ + void serialize(TextOutput& t) const; + + std::string toString(const std::string& name) const; + + std::string toString() const { + static const std::string name = ""; + return toString(name); + } + + /** 2-norm squared: sum(squares). (i.e., dot product with itself) */ + double normSquared() const; + + /** 2-norm (sqrt(sum(squares)) */ + double norm() const; + + /** + Low-level SVD functionality. Useful for applications that do not want + to construct a Matrix but need to perform the SVD operation. + + this = U * D * V' + + Assumes that rows >= cols + + @return NULL on success, a string describing the error on failure. + @param U rows x cols matrix to be decomposed, gets overwritten with U, a rows x cols matrix with orthogonal columns. + @param D vector of singular values of a (diagonal of the D matrix). Length cols. + @param V returns the right orthonormal transformation matrix, size cols x cols + + @cite Based on Dianne Cook's implementation, which is adapted from + svdecomp.c in XLISP-STAT 2.1, which is code from Numerical Recipes + adapted by Luke Tierney and David Betz. The Numerical Recipes code + is adapted from Forsythe et al, who based their code on Golub and + Reinsch's original implementation. + */ + static const char* svdCore(float** U, int rows, int cols, float* D, float** V); + +}; + +} + +inline G3D::Matrix operator-(const G3D::Matrix::T& v, const G3D::Matrix& M) { + return M.lsub(v); +} + +inline G3D::Matrix operator*(const G3D::Matrix::T& v, const G3D::Matrix& M) { + return M * v; +} + +inline G3D::Matrix operator+(const G3D::Matrix::T& v, const G3D::Matrix& M) { + return M + v; +} + +inline G3D::Matrix abs(const G3D::Matrix& M) { + return M.abs(); +} + +#endif + diff --git a/externals/g3dlite/G3D/Matrix2.h b/externals/g3dlite/G3D/Matrix2.h new file mode 100644 index 00000000000..eaf4aefa220 --- /dev/null +++ b/externals/g3dlite/G3D/Matrix2.h @@ -0,0 +1,69 @@ +#ifndef G3D_MATRIX2_H +#define G3D_MATRIX2_H + +#include "G3D/platform.h" +#include "G3D/Vector2.h" + +namespace G3D { + +/** @beta */ +class Matrix2 { +private: + + float data[2][2]; + +public: + + inline Matrix2() { + data[0][0] = 1.0f; data[0][1] = 0.0f; + data[1][0] = 0.0f; data[1][1] = 1.0f; + } + + inline Matrix2(float v00, float v01, float v10, float v11) { + data[0][0] = v00; data[0][1] = v01; + data[1][0] = v10; data[1][1] = v11; + } + + inline Vector2 operator*(const Vector2& v) const { + return Vector2(data[0][0] * v[0] + data[0][1] * v[1], + data[1][0] * v[0] + data[1][1] * v[1]); + } + + inline Matrix2 inverse() const { + return Matrix2(data[0][0], data[1][0], + data[0][1], data[1][1]) * (1.0f / determinant()); + } + + inline Matrix2 transpose() const { + return Matrix2(data[0][0], data[1][0], + data[0][1], data[1][1]); + } + + inline float determinant() const { + return data[0][0] * data[1][1] - data[0][1] * data[1][0]; + } + + inline Matrix2 operator*(float f) const { + return Matrix2(data[0][0] * f, data[0][1] * f, + data[1][0] * f, data[1][1] * f); + } + + inline Matrix2 operator/(float f) const { + return Matrix2(data[0][0] / f, data[0][1] / f, + data[1][0] / f, data[1][1] / f); + } + + inline float* operator[](int i) { + debugAssert(i >= 0 && i <= 2); + return data[i]; + } + + inline const float* operator[](int i) const { + debugAssert(i >= 0 && i <= 1); + return data[i]; + } +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/Matrix3.h b/externals/g3dlite/G3D/Matrix3.h new file mode 100644 index 00000000000..06ec7e67474 --- /dev/null +++ b/externals/g3dlite/G3D/Matrix3.h @@ -0,0 +1,366 @@ +/** + @file Matrix3.h + + 3x3 matrix class + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @cite Portions based on Dave Eberly's Magic Software Library at
http://www.magic-software.com + + @created 2001-06-02 + @edited 2006-04-05 + */ + +#ifndef G3D_Matrix3_h +#define G3D_Matrix3_h + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Vector4.h" +#include "G3D/debugAssert.h" + +#include + +namespace G3D { + +#ifdef _MSC_VER +// Turn off "conditional expression is constant" warning; MSVC generates this +// for debug assertions in inlined methods. +# pragma warning (disable : 4127) +#endif + +class Any; + +/** + 3x3 matrix. Do not subclass. + */ +class Matrix3 { +private: + + float elt[3][3]; + + // Hidden operators + bool operator<(const Matrix3&) const; + bool operator>(const Matrix3&) const; + bool operator<=(const Matrix3&) const; + bool operator>=(const Matrix3&) const; + +public: + + Matrix3(const Any& any); + + operator Any() const; + + /** Initial values are undefined for performance. See also + Matrix3::zero(), Matrix3::identity(), Matrix3::fromAxisAngle, etc.*/ + inline Matrix3() {} + + Matrix3 (class BinaryInput& b); + Matrix3 (const float aafEntry[3][3]); + Matrix3 (const Matrix3& rkMatrix); + Matrix3 (float fEntry00, float fEntry01, float fEntry02, + float fEntry10, float fEntry11, float fEntry12, + float fEntry20, float fEntry21, float fEntry22); + + bool fuzzyEq(const Matrix3& b) const; + + /** Constructs a matrix from a quaternion. + @cite Graphics Gems II, p. 351--354 + @cite Implementation from Watt and Watt, pg 362*/ + Matrix3(const class Quat& q); + + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + + /** Returns true if column(0).cross(column(1)).dot(column(2)) > 0. */ + bool isRightHanded() const; + + /** + Sets all elements. + */ + void set(float fEntry00, float fEntry01, float fEntry02, + float fEntry10, float fEntry11, float fEntry12, + float fEntry20, float fEntry21, float fEntry22); + + /** + * member access, allows use of construct mat[r][c] + */ + inline float* operator[] (int iRow) { + debugAssert(iRow >= 0); + debugAssert(iRow < 3); + return (float*)&elt[iRow][0]; + } + + inline const float* operator[] (int iRow) const { + debugAssert(iRow >= 0); + debugAssert(iRow < 3); + return (const float*)&elt[iRow][0]; + } + + inline operator float* () { + return (float*)&elt[0][0]; + } + + inline operator const float* () const{ + return (const float*)&elt[0][0]; + } + + Vector3 column(int c) const; + const Vector3& row(int r) const; + + void setColumn(int iCol, const Vector3 &vector); + void setRow(int iRow, const Vector3 &vector); + + // assignment and comparison + inline Matrix3& operator= (const Matrix3& rkMatrix) { + memcpy(elt, rkMatrix.elt, 9 * sizeof(float)); + return *this; + } + + bool operator== (const Matrix3& rkMatrix) const; + bool operator!= (const Matrix3& rkMatrix) const; + + // arithmetic operations + Matrix3 operator+ (const Matrix3& rkMatrix) const; + Matrix3 operator- (const Matrix3& rkMatrix) const; + /** Matrix-matrix multiply */ + Matrix3 operator* (const Matrix3& rkMatrix) const; + Matrix3 operator- () const; + + Matrix3& operator+= (const Matrix3& rkMatrix); + Matrix3& operator-= (const Matrix3& rkMatrix); + Matrix3& operator*= (const Matrix3& rkMatrix); + + /** + * matrix * vector [3x3 * 3x1 = 3x1] + */ + inline Vector3 operator* (const Vector3& v) const { + Vector3 kProd; + + for (int r = 0; r < 3; ++r) { + kProd[r] = + elt[r][0] * v[0] + + elt[r][1] * v[1] + + elt[r][2] * v[2]; + } + + return kProd; + } + + + /** + * vector * matrix [1x3 * 3x3 = 1x3] + */ + friend Vector3 operator* (const Vector3& rkVector, + const Matrix3& rkMatrix); + + /** + * matrix * scalar + */ + Matrix3 operator* (float fScalar) const; + + /** scalar * matrix */ + friend Matrix3 operator* (double fScalar, const Matrix3& rkMatrix); + friend Matrix3 operator* (float fScalar, const Matrix3& rkMatrix); + friend Matrix3 operator* (int fScalar, const Matrix3& rkMatrix); + + Matrix3& operator*= (float k); + Matrix3& operator/= (float k); + + +private: + /** Multiplication where out != A and out != B */ + static void _mul(const Matrix3& A, const Matrix3& B, Matrix3& out); +public: + + /** Optimized implementation of out = A * B. It is safe (but slow) to call + with A, B, and out possibly pointer equal to one another.*/ + // This is a static method so that it is not ambiguous whether "this" + // is an input or output argument. + inline static void mul(const Matrix3& A, const Matrix3& B, Matrix3& out) { + if ((&out == &A) || (&out == &B)) { + // We need a temporary anyway, so revert to the stack method. + out = A * B; + } else { + // Optimized in-place multiplication. + _mul(A, B, out); + } + } + +private: + static void _transpose(const Matrix3& A, Matrix3& out); +public: + + /** Optimized implementation of out = A.transpose(). It is safe (but slow) to call + with A and out possibly pointer equal to one another. + + Note that A.transpose() * v can be computed + more efficiently as v * A. + */ + inline static void transpose(const Matrix3& A, Matrix3& out) { + if (&A == &out) { + out = A.transpose(); + } else { + _transpose(A, out); + } + } + + /** Returns true if the rows and column L2 norms are 1.0 and the rows are orthogonal. */ + bool isOrthonormal() const; + + Matrix3 transpose () const; + bool inverse (Matrix3& rkInverse, float fTolerance = 1e-06) const; + Matrix3 inverse (float fTolerance = 1e-06) const; + float determinant () const; + + /** singular value decomposition */ + void singularValueDecomposition (Matrix3& rkL, Vector3& rkS, + Matrix3& rkR) const; + /** singular value decomposition */ + void singularValueComposition (const Matrix3& rkL, + const Vector3& rkS, const Matrix3& rkR); + + /** Gram-Schmidt orthonormalization (applied to columns of rotation matrix) */ + void orthonormalize(); + + /** orthogonal Q, diagonal D, upper triangular U stored as (u01,u02,u12) */ + void qDUDecomposition (Matrix3& rkQ, Vector3& rkD, + Vector3& rkU) const; + + /** + Polar decomposition of a matrix. Based on pseudocode from Nicholas J + Higham, "Computing the Polar Decomposition -- with Applications Siam + Journal of Science and Statistical Computing, Vol 7, No. 4, October + 1986. + + Decomposes A into R*S, where R is orthogonal and S is symmetric. + + Ken Shoemake's "Matrix animation and polar decomposition" + in Proceedings of the conference on Graphics interface '92 + seems to be better known in the world of graphics, but Higham's version + uses a scaling constant that can lead to faster convergence than + Shoemake's when the initial matrix is far from orthogonal. + */ + void polarDecomposition(Matrix3 &R, Matrix3 &S) const; + + /** + * Matrix norms. + */ + float spectralNorm () const; + + float squaredFrobeniusNorm() const; + + float frobeniusNorm() const; + + float l1Norm() const; + + float lInfNorm() const; + + float diffOneNorm(const Matrix3 &y) const; + + /** matrix must be orthonormal */ + void toAxisAngle(Vector3& rkAxis, float& rfRadians) const; + + static Matrix3 fromDiagonal(const Vector3& d) { + return Matrix3(d.x, 0, 0, + 0, d.y, 0, + 0, 0, d.z); + } + + static Matrix3 fromAxisAngle(const Vector3& rkAxis, float fRadians); + + /** + * The matrix must be orthonormal. The decomposition is yaw*pitch*roll + * where yaw is rotation about the Up vector, pitch is rotation about the + * right axis, and roll is rotation about the Direction axis. + */ + bool toEulerAnglesXYZ (float& rfYAngle, float& rfPAngle, + float& rfRAngle) const; + bool toEulerAnglesXZY (float& rfYAngle, float& rfPAngle, + float& rfRAngle) const; + bool toEulerAnglesYXZ (float& rfYAngle, float& rfPAngle, + float& rfRAngle) const; + bool toEulerAnglesYZX (float& rfYAngle, float& rfPAngle, + float& rfRAngle) const; + bool toEulerAnglesZXY (float& rfYAngle, float& rfPAngle, + float& rfRAngle) const; + bool toEulerAnglesZYX (float& rfYAngle, float& rfPAngle, + float& rfRAngle) const; + static Matrix3 fromEulerAnglesXYZ (float fYAngle, float fPAngle, float fRAngle); + static Matrix3 fromEulerAnglesXZY (float fYAngle, float fPAngle, float fRAngle); + static Matrix3 fromEulerAnglesYXZ (float fYAngle, float fPAngle, float fRAngle); + static Matrix3 fromEulerAnglesYZX (float fYAngle, float fPAngle, float fRAngle); + static Matrix3 fromEulerAnglesZXY (float fYAngle, float fPAngle, float fRAngle); + static Matrix3 fromEulerAnglesZYX (float fYAngle, float fPAngle, float fRAngle); + + /** eigensolver, matrix must be symmetric */ + void eigenSolveSymmetric (float afEigenvalue[3], + Vector3 akEigenvector[3]) const; + + static void tensorProduct (const Vector3& rkU, const Vector3& rkV, + Matrix3& rkProduct); + std::string toString() const; + + static const float EPSILON; + + // Special values. + // The unguaranteed order of initialization of static variables across + // translation units can be a source of annoying bugs, so now the static + // special values (like Vector3::ZERO, Color3::WHITE, ...) are wrapped + // inside static functions that return references to them. + // These functions are intentionally not inlined, because: + // "You might be tempted to write [...] them as inline functions + // inside their respective header files, but this is something you + // must definitely not do. An inline function can be duplicated + // in every file in which it appears œóõ½ and this duplication + // includes the static object definition. Because inline functions + // automatically default to internal linkage, this would result in + // having multiple static objects across the various translation + // units, which would certainly cause problems. So you must + // ensure that there is only one definition of each wrapping + // function, and this means not making the wrapping functions inline", + // according to Chapter 10 of "Thinking in C++, 2nd ed. Volume 1" by Bruce Eckel, + // http://www.mindview.net/ + static const Matrix3& zero(); + static const Matrix3& identity(); + +protected: + + // support for eigensolver + void tridiagonal (float afDiag[3], float afSubDiag[3]); + bool qLAlgorithm (float afDiag[3], float afSubDiag[3]); + + // support for singular value decomposition + static const float ms_fSvdEpsilon; + static const int ms_iSvdMaxIterations; + static void bidiagonalize (Matrix3& kA, Matrix3& kL, + Matrix3& kR); + static void golubKahanStep (Matrix3& kA, Matrix3& kL, + Matrix3& kR); + + // support for spectral norm + static float maxCubicRoot (float afCoeff[3]); + +}; + + +//---------------------------------------------------------------------------- +/** v * M == M.transpose() * v */ +inline Vector3 operator* (const Vector3& rkPoint, const Matrix3& rkMatrix) { + Vector3 kProd; + + for (int r = 0; r < 3; ++r) { + kProd[r] = + rkPoint[0] * rkMatrix.elt[0][r] + + rkPoint[1] * rkMatrix.elt[1][r] + + rkPoint[2] * rkMatrix.elt[2][r]; + } + + return kProd; +} + + +} // namespace + +#endif + diff --git a/externals/g3dlite/G3D/Matrix4.h b/externals/g3dlite/G3D/Matrix4.h new file mode 100644 index 00000000000..9ce87d875b8 --- /dev/null +++ b/externals/g3dlite/G3D/Matrix4.h @@ -0,0 +1,249 @@ +/** + @file Matrix4.h + + 4x4 matrix class + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2003-10-02 + @edited 2009-10-20 + */ + +#ifndef G3D_Matrix4_h +#define G3D_Matrix4_h + +#ifdef _MSC_VER +// Disable conditional expression is constant, which occurs incorrectly on inlined functions +# pragma warning (push) +# pragma warning( disable : 4127 ) +#endif + +#include "G3D/platform.h" +#include "G3D/debugAssert.h" +#include "G3D/Matrix3.h" +#include "G3D/Vector3.h" + +namespace G3D { + +class Any; + +/** + A 4x4 matrix. + + See also G3D::CoordinateFrame, G3D::Matrix3, G3D::Quat + */ +class Matrix4 { +private: + + float elt[4][4]; + + /** + Computes the determinant of the 3x3 matrix that lacks excludeRow + and excludeCol. + */ + float subDeterminant(int excludeRow, int excludeCol) const; + + // Hidden operators + bool operator<(const Matrix4&) const; + bool operator>(const Matrix4&) const; + bool operator<=(const Matrix4&) const; + bool operator>=(const Matrix4&) const; + +public: + /** Must be of the form: Matrix4(#, #, # .... #)*/ + Matrix4(const Any& any); + + operator Any() const; + + Matrix4( + float r1c1, float r1c2, float r1c3, float r1c4, + float r2c1, float r2c2, float r2c3, float r2c4, + float r3c1, float r3c2, float r3c3, float r3c4, + float r4c1, float r4c2, float r4c3, float r4c4); + + /** + init should be row major. + */ + Matrix4(const float* init); + + /** + a is the upper left 3x3 submatrix and b is the upper right 3x1 submatrix. The last row of the created matrix is (0,0,0,1). + */ + Matrix4(const class Matrix3& upper3x3, const class Vector3& lastCol = Vector3::zero()); + + Matrix4(const class CoordinateFrame& c); + + Matrix4(const double* init); + + Matrix4(); + + /** Produces an RT transformation that nearly matches this Matrix4. + Because a Matrix4 may not be precisely a rotation and translation, + this may introduce error. */ + class CoordinateFrame approxCoordinateFrame() const; + + // Special values. + // Intentionally not inlined: see Matrix3::identity() for details. + static const Matrix4& identity(); + static const Matrix4& zero(); + + /** If this is a perspective projection matrix created by + Matrix4::perspectiveProjection, extract its parameters. */ + void getPerspectiveProjectionParameters + (float& left, + float& right, + float& bottom, + float& top, + float& nearval, + float& farval, + float updirection = -1.0f) const; + + inline float* operator[](int r) { + debugAssert(r >= 0); + debugAssert(r < 4); + return (float*)&elt[r]; + } + + inline const float* operator[](int r) const { + debugAssert(r >= 0); + debugAssert(r < 4); + return (const float*)&elt[r]; + } + + inline operator float* () { + return (float*)&elt[0][0]; + } + + inline operator const float* () const { + return (const float*)&elt[0][0]; + } + + Matrix4 operator*(const Matrix4& other) const; + + class Matrix3 upper3x3() const; + + /** Homogeneous multiplication. Let k = M * [v w]^T. result = k.xyz() / k.w */ + class Vector3 homoMul(const class Vector3& v, float w) const; + + /** + Constructs an orthogonal projection matrix from the given parameters. + Near and far are the NEGATIVE of the near and far plane Z values + (to follow OpenGL conventions). + + \param upDirection Use -1.0 for 2D Y increasing downwards (the G3D 8.x default convention), + 1.0 for 2D Y increasing upwards (the G3D 7.x default and OpenGL convention) + */ + static Matrix4 orthogonalProjection( + float left, + float right, + float bottom, + float top, + float nearval, + float farval, + float upDirection = -1.0f); + + + /** \param upDirection Use -1.0 for 2D Y increasing downwards (the G3D 8.x default convention), + 1.0 for 2D Y increasing upwards (the G3D 7.x default and OpenGL convention) + */ + static Matrix4 orthogonalProjection( + const class Rect2D& rect, + float nearval, + float farval, + float upDirection = -1.0f); + + /** \param upDirection Use -1.0 for 2D Y increasing downwards (the G3D 8.x default convention), + 1.0 for 2D Y increasing upwards (the G3D 7.x default and OpenGL convention) + */ + static Matrix4 perspectiveProjection( + float left, + float right, + float bottom, + float top, + float nearval, + float farval, + float upDirection = -1.0f); + + void setRow(int r, const class Vector4& v); + void setColumn(int c, const Vector4& v); + + const Vector4& row(int r) const; + Vector4 column(int c) const; + + Matrix4 operator*(const float s) const; + Vector4 operator*(const Vector4& vector) const; + + Matrix4 transpose() const; + + bool operator!=(const Matrix4& other) const; + bool operator==(const Matrix4& other) const; + + float determinant() const; + Matrix4 inverse() const; + + /** + Transpose of the cofactor matrix (used in computing the inverse). + Note: This is in fact only one type of adjoint. More generally, + an adjoint of a matrix is any mapping of a matrix which possesses + certain properties. This returns the so-called adjugate + or classical adjoint. + */ + Matrix4 adjoint() const; + Matrix4 cofactor() const; + + /** Serializes row-major */ + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + + std::string toString() const; + + /** 3D scale matrix */ + inline static Matrix4 scale(const Vector3& v) { + return Matrix4(v.x, 0, 0, 0, + 0, v.y, 0, 0, + 0, 0, v.z, 0, + 0, 0, 0, 1); + } + + /** 3D scale matrix */ + inline static Matrix4 scale(float x, float y, float z) { + return scale(Vector3(x, y, z)); + } + + /** 3D scale matrix */ + inline static Matrix4 scale(float s) { + return scale(s,s,s); + } + + /** 3D translation matrix */ + inline static Matrix4 translation(const Vector3& v) { + return Matrix4(Matrix3::identity(), v); + } + + inline static Matrix4 translation(float x, float y, float z) { + return Matrix4(Matrix3::identity(), Vector3(x, y, z)); + } + + /** Create a rotation matrix that rotates \a deg degrees around the Y axis */ + inline static Matrix4 yawDegrees(float deg) { + return Matrix4(Matrix3::fromAxisAngle(Vector3::unitY(), toRadians(deg))); + } + + inline static Matrix4 pitchDegrees(float deg) { + return Matrix4(Matrix3::fromAxisAngle(Vector3::unitX(), toRadians(deg))); + } + + inline static Matrix4 rollDegrees(float deg) { + return Matrix4(Matrix3::fromAxisAngle(Vector3::unitZ(), toRadians(deg))); + } +}; + + + +} // namespace + +#ifdef _MSC_VER +# pragma warning (pop) +#endif + +#endif diff --git a/externals/g3dlite/G3D/MemoryManager.h b/externals/g3dlite/G3D/MemoryManager.h new file mode 100644 index 00000000000..15bf6d8be43 --- /dev/null +++ b/externals/g3dlite/G3D/MemoryManager.h @@ -0,0 +1,93 @@ +/** + @file MemoryManager.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @created 2009-04-20 + @edited 2009-04-20 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ +#ifndef G3D_MemoryManager_h +#define G3D_MemoryManager_h + +#include "G3D/platform.h" +#include "G3D/ReferenceCount.h" + +namespace G3D { + +/** + Abstraction of memory management. + Default implementation uses G3D::System::malloc and is threadsafe. + + \sa CRTMemoryManager, AlignedMemoryManager, AreaMemoryManager */ +class MemoryManager : public ReferenceCountedObject { +protected: + + MemoryManager(); + +public: + + typedef ReferenceCountedPointer Ref; + + /** Return a pointer to \a s bytes of memory that are unused by + the rest of the program. The contents of the memory are + undefined */ + virtual void* alloc(size_t s); + + /** Invoke to declare that this memory will no longer be used by + the program. The memory manager is not required to actually + reuse or release this memory. */ + virtual void free(void* ptr); + + /** Returns true if this memory manager is threadsafe (i.e., alloc + and free can be called asychronously) */ + virtual bool isThreadsafe() const; + + /** Return the instance. There's only one instance of the default + MemoryManager; it is cached after the first creation. */ + static MemoryManager::Ref create(); +}; + +/** + Allocates memory on 16-byte boundaries. + \sa MemoryManager, CRTMemoryManager, AreaMemoryManager */ +class AlignedMemoryManager : public MemoryManager { +protected: + + AlignedMemoryManager(); + +public: + + typedef ReferenceCountedPointer Ref; + + + virtual void* alloc(size_t s); + + virtual void free(void* ptr); + + virtual bool isThreadsafe() const; + + static AlignedMemoryManager::Ref create(); +}; + + +/** MemoryManager implemented using the C runtime. */ +class CRTMemoryManager : public MemoryManager { +protected: + CRTMemoryManager(); + +public: + typedef ReferenceCountedPointer Ref; + virtual void* alloc(size_t s); + virtual void free(void* ptr); + virtual bool isThreadsafe() const; + + /** There's only one instance of this memory manager; it is + cached after the first creation. */ + static CRTMemoryManager::Ref create(); +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/MeshAlg.h b/externals/g3dlite/G3D/MeshAlg.h new file mode 100644 index 00000000000..1decea10105 --- /dev/null +++ b/externals/g3dlite/G3D/MeshAlg.h @@ -0,0 +1,683 @@ +/** + @file MeshAlg.h + + Indexed Mesh algorithms. + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2003-09-14 + @edited 2010-01-18 +*/ + +#ifndef G3D_MeshAlg_h +#define G3D_MeshAlg_h + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/Vector3.h" +#include "G3D/CoordinateFrame.h" +#include "G3D/SmallArray.h" +#include "G3D/constants.h" +#include "G3D/Image1.h" + +#ifdef G3D_WIN32 +// Turn off "conditional expression is constant" warning; MSVC generates this +// for debug assertions in inlined methods. +#pragma warning (disable : 4127) +#endif + +namespace G3D { + +/** + Indexed mesh algorithms. You have to build your own mesh class. +

+ No mesh class is provided with G3D because there isn't an "ideal" + mesh format-- one application needs keyframed animation, another + skeletal animation, a third texture coordinates, a fourth + cannot precompute information, etc. Instead of compromising, this + class implements the hard parts of mesh computation and you can write + your own ideal mesh class on top of it. + + \sa G3D::ArticulatedModel, G3D::IFSModel + */ +class MeshAlg { +public: + + /** \deprecated */ + typedef PrimitiveType Primitive; + + /** Adjacency information for a vertex. + Does not contain the vertex position or normal, + which are stored in the MeshAlg::Geometry object. + Vertexs must be stored in an array + parallel to (indexed in the same way as) + MeshAlg::Geometry::vertexArray. + */ + class Vertex { + public: + Vertex() {} + + /** + Array of edges adjacent to this vertex. + Let e = edgeIndex[i]. + edge[(e >= 0) ? e : ~e].vertexIndex[0] == this + vertex index. + + Edges may be listed multiple times if they are + degenerate. + */ + SmallArray edgeIndex; + + /** + Returns true if e or ~e is in the edgeIndex list. + */ + inline bool inEdge(int e) const { + return edgeIndex.contains(~e) || edgeIndex.contains(e); + } + + /** + Array of faces containing this vertex. Faces + may be listed multiple times if they are degenerate. + */ + SmallArray faceIndex; + + inline bool inFace(int f) const { + debugAssert(f >= 0); + return faceIndex.contains(f); + } + }; + + + /** + Oriented, indexed triangle. + */ + class Face { + public: + Face(); + + /** + Used by Edge::faceIndex to indicate a missing face. + This is a large negative value. + */ + static const int NONE; + + + /** + Vertices in the face in counter-clockwise order. + Degenerate faces may include the same vertex multiple times. + */ + int vertexIndex[3]; + + inline bool containsVertex(int v) const { + return contains(vertexIndex, 3, v); + } + + /** + Edge indices in counter-clockwise order. Edges are + undirected, so it is important to know which way + each edge is pointing in a face. This is encoded + using negative indices. + + If edgeIndex[i] >= 0 then this face + contains the directed edge + between vertex indices + edgeArray[face.edgeIndex[i]].vertexIndex[0] + and + edgeArray[face.edgeIndex[i]].vertexIndex[1]. + + If edgeIndex[i] < 0 then + ~edgeIndex[i] (i.e. the two's + complement of) is used and this face contains the directed + edge between vertex indices + edgeArray[~face.edgeIndex[i]].vertexIndex[0] + and + edgeArray[~face.edgeIndex[i]].vertexIndex[1]. + + Degenerate faces may include the same edge multiple times. + */ + // Temporarily takes on the value Face::NONE during adjacency + // computation to indicate an edge that has not yet been assigned. + int edgeIndex[3]; + + inline bool containsEdge(int e) const { + if (e < 0) { + e = ~e; + } + return contains(edgeIndex, 3, e) || contains(edgeIndex, 3, ~e); + } + + /** Contains the forward edge e if e >= 0 and the backward edge + ~e otherwise. */ + inline bool containsDirectedEdge(int e) const { + return contains(edgeIndex, 3, e); + } + }; + + + /** Oriented, indexed edge */ + class Edge { + public: + Edge(); + + /** Degenerate edges may include the same vertex times. */ + int vertexIndex[2]; + + inline bool containsVertex(int v) const { + return contains(vertexIndex, 2, v); + } + + /** + The edge is directed forward in face 0 + backward in face 1. Face index of MeshAlg::Face::NONE + indicates a boundary (a.k.a. crack, broken) edge. + */ + int faceIndex[2]; + + /** Returns true if f is contained in the faceIndex array in either slot. + To see if it is forward in that face, just check edge.faceIndex[0] == f.*/ + inline bool inFace(int f) const { + return contains(faceIndex, 2, f); + } + + /** + Returns true if either faceIndex is NONE. + */ + inline bool boundary() const { + return (faceIndex[0] == Face::NONE) || + (faceIndex[1] == Face::NONE); + } + + /** + Returns the reversed edge. + */ + inline Edge reverse() const { + Edge e; + e.vertexIndex[0] = vertexIndex[1]; + e.vertexIndex[1] = vertexIndex[0]; + e.faceIndex[0] = faceIndex[1]; + e.faceIndex[1] = faceIndex[0]; + return e; + } + }; + + + /** + Convenient for passing around the per-vertex data that changes under + animation. The faces and edges are needed to interpret + these values. + */ + class Geometry { + public: + /** Vertex positions */ + Array vertexArray; + + /** Vertex normals */ + Array normalArray; + + /** + Assignment is optimized using SSE. + */ + Geometry& operator=(const Geometry& src); + + void clear() { + vertexArray.clear(); + normalArray.clear(); + } + }; + + /** + Given a set of vertices and a set of indices for traversing them + to create triangles, computes other mesh properties. + + Colocated vertices are treated as separate. To have + colocated vertices collapsed (necessary for many algorithms, + like shadowing), weld the mesh before computing adjacency. + + Recent change: In version 6.00, colocated vertices were automatically + welded by this routine and degenerate faces and edges were removed. That + is no longer the case. + + Where two faces meet, there are two opposite directed edges. These + are collapsed into a single bidirectional edge in the edgeArray. + If four faces meet exactly at the same edge, that edge will appear + twice in the array, and so on. If an edge is a boundary of the mesh + (i.e. if the edge has only one adjacent face) it will appear in the + array with one face index set to MeshAlg::Face::NONE. + + @param vertexGeometry %Vertex positions to use when deciding colocation. + @param indexArray Order to traverse vertices to make triangles + @param faceArray Output + @param edgeArray Output. Sorted so that boundary edges are at the end of the array. + @param vertexArray Output + */ + static void computeAdjacency( + const Array& vertexGeometry, + const Array& indexArray, + Array& faceArray, + Array& edgeArray, + Array& vertexArray); + + /** + @deprecated Use the other version of computeAdjacency, which takes Array. + @param facesAdjacentToVertex Output adjacentFaceArray[v] is an array of + indices for faces touching vertex index v + */ + static void computeAdjacency( + const Array& vertexArray, + const Array& indexArray, + Array& faceArray, + Array& edgeArray, + Array< Array >& facesAdjacentToVertex); + + /** + Computes some basic mesh statistics including: min, max mean and median, + edge lengths; and min, mean, median, and max face area. + + @param vertexArray %Vertex positions to use when deciding colocation. + @param indexArray Order to traverse vertices to make triangles + @param minEdgeLength Minimum edge length + @param meanEdgeLength Mean edge length + @param medianEdgeLength Median edge length + @param maxEdgeLength Max edge length + @param minFaceArea Minimum face area + @param meanFaceArea Mean face area + @param medianFaceArea Median face area + @param maxFaceArea Max face area + */ + static void computeAreaStatistics( + const Array& vertexArray, + const Array& indexArray, + double& minEdgeLength, + double& meanEdgeLength, + double& medianEdgeLength, + double& maxEdgeLength, + double& minFaceArea, + double& meanFaceArea, + double& medianFaceArea, + double& maxFaceArea); + +private: + + /** Helper for weldAdjacency */ + static void weldBoundaryEdges( + Array& faceArray, + Array& edgeArray, + Array& vertexArray); + +public: + + /** + Computes tangent and binormal vectors, + which provide a (mostly) consistent + parameterization over the surface for + effects like bump mapping. In the resulting coordinate frame, + T = x (varies with texture s coordinate), B = y (varies with negative texture t coordinate), + and N = z for a right-handed coordinate frame. If a billboard is vertical on the screen + in view of the camera, the tangent space matches the camera's coordinate frame. + + The vertex, texCoord, tangent, and binormal + arrays are parallel arrays. + + The resulting tangent and binormal might not be exactly + perpendicular to each other. They are guaranteed to + be perpendicular to the normal. + + @cite Max McGuire + */ + static void computeTangentSpaceBasis( + const Array& vertexArray, + const Array& texCoordArray, + const Array& vertexNormalArray, + const Array& faceArray, + Array& tangent, + Array& binormal); + + /** @deprecated */ + static void computeNormals( + const Array& vertexArray, + const Array& faceArray, + const Array< Array >& adjacentFaceArray, + Array& vertexNormalArray, + Array& faceNormalArray); + + /** + Vertex normals are weighted by the area of adjacent faces. + Nelson Max showed this is superior to uniform weighting for + general meshes in jgt. + + @param vertexNormalArray Output. Unit length + @param faceNormalArray Output. Degenerate faces produce zero magnitude normals. Unit length + @see weld + */ + static void computeNormals( + const Array& vertexGeometry, + const Array& faceArray, + const Array& vertexArray, + Array& vertexNormalArray, + Array& faceNormalArray); + + /** Computes unit length normals in place using the other computeNormals methods. + If you already have a face array use another method; it will be faster. + @see weld*/ + static void computeNormals( + Geometry& geometry, + const Array& indexArray); + + /** + Computes face normals only. Significantly faster (especially if + normalize is false) than computeNormals. + @see weld + */ + static void computeFaceNormals( + const Array& vertexArray, + const Array& faceArray, + Array& faceNormals, + bool normalize = true); + + /** + Classifies each face as a backface or a front face relative + to the observer point P (which is at infinity when P.w = 0). + A face with normal exactly perpendicular to the observer vector + may be classified as either a front or a back face arbitrarily. + */ + static void identifyBackfaces( + const Array& vertexArray, + const Array& faceArray, + const Vector4& P, + Array& backface); + + /** A faster version of identifyBackfaces for the case where + face normals have already been computed */ + static void identifyBackfaces( + const Array& vertexArray, + const Array& faceArray, + const Vector4& P, + Array& backface, + const Array& faceNormals); + + /** + Welds nearby and colocated elements of the oldVertexArray together so that + newVertexArray contains no vertices within radius of one another. + Every vertex in newVertexPositions also appears in oldVertexPositions. + This is useful for downsampling meshes and welding cracks created by artist errors + or numerical imprecision. + + The two integer arrays map indices back and forth between the arrays according to: +

+     oldVertexArray[toOld[ni]] == newVertexArray[ni]
+     oldVertexArray[oi] == newVertexArray[toNew[ni]]
+     
+ + Note that newVertexPositions is never longer than oldVertexPositions + and is shorter when vertices are welded. + + Welding with a large radius will effectively compute a lower level of detail for + the mesh. + + The welding method runs in roughly linear time in the length of oldVertexArray-- + a uniform spatial grid is used to achieve nearly constant time vertex collapses + for uniformly distributed vertices. + + It is sometimes desirable to keep the original vertex ordering but + identify the unique vertices. The following code computes + array canonical s.t. canonical[v] = first occurance of + a vertex near oldVertexPositions[v] in oldVertexPositions. + +
+        Array canonical(oldVertexPositions.size()), toNew, toOld;
+        computeWeld(oldVertexPositions, Array(), toNew, toOld, radius);
+        for (int v = 0; v < canonical.size(); ++v) {
+            canonical[v] = toOld[toNew[v]];
+        }
+     
+ + See also G3D::MeshAlg::weldAdjacency. + + @cite The method is that described as the 'Grouper' in Baum, Mann, Smith, and Winget, + Making Radiosity Usable: Automatic Preprocessing and Meshing Techniques for + the Generation of Accurate Radiosity Solutions, Computer Graphics vol 25, no 4, July 1991. + + @deprecated Use weld. + */ + static void computeWeld( + const Array& oldVertexPositions, + Array& newVertexPositions, + Array& toNew, + Array& toOld, + double radius = fuzzyEpsilon); + + /** + Modifies the face, edge, and vertex arrays in place so that + colocated (within radius) vertices are treated as identical. + Note that the vertexArray and corresponding geometry will + contain elements that are no longer used. In the vertexArray, + these elements are initialized to MeshAlg::Vertex() but not + removed (because removal would change the indexing). + + This is a good preprocessing step for algorithms that are only + concerned with the shape of a mesh (e.g. cartoon rendering, fur, shadows) + and not the indexing of the vertices. + + Use this method when you have already computed adjacency information + and want to collapse colocated vertices within that data without + disturbing the actual mesh vertices or indexing scheme. + + If you have not computed adjacency already, use MeshAlg::computeWeld + instead and compute adjacency information after welding. + + @deprecated Use weld. + + @param faceArray Mutated in place. Size is maintained (degenerate + faces are not removed). + @param edgeArray Mutated in place. May shrink if boundary edges + are welded together. + @param vertexArray Mutated in place. Size is maintained (duplicate + vertices contain no adjacency info). + */ + static void weldAdjacency( + const Array& originalGeometry, + Array& faceArray, + Array& edgeArray, + Array& vertexArray, + double radius = fuzzyEpsilon); + + + /** + Counts the number of edges (in an edge array returned from + MeshAlg::computeAdjacency) that have only one adjacent face. + */ + static int countBoundaryEdges(const Array& edgeArray); + + + /** + Generates an array of integers from start to start + n - 1 that have run numbers + in series then omit the next skip before the next run. Useful for turning + a triangle list into an indexed face set. + + Example: +
+       createIndexArray(10, x);
+       // x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
+
+       createIndexArray(5, x, 2);
+       // x = [2, 3, 4, 5, 6, 7] 
+
+       createIndexArray(6, x, 0, 2, 1);
+       // x = [0, 1, 3, 4, 6, 7]
+     
+ */ + static void createIndexArray( + int n, + Array& array, + int start = 0, + int run = 1, + int skip = 0); + + /** + Computes a conservative, near-optimal axis aligned bounding box and sphere. + + @cite The bounding sphere uses the method from J. Ritter. An effcient bounding sphere. In Andrew S. Glassner, editor, Graphics Gems. Academic Press, Boston, MA, 1990. + + */ + static void computeBounds(const Array& vertex, class AABox& box, class Sphere& sphere); + + /** Computes bounds for a subset of the vertices. It is ok if vertices appear more than once in the index array. */ + static void computeBounds(const Array& vertex, const Array& index, class AABox& box, class Sphere& sphere); + + /** + In debug mode, asserts that the adjacency references between the + face, edge, and vertex array are consistent. + */ + static void debugCheckConsistency( + const Array& faceArray, + const Array& edgeArray, + const Array& vertexArray); + + /** + Generates a unit square in the X-Z plane composed of a grid of wCells x hCells + squares and then transforms it by xform. + + @param vertex Output vertices + @param texCoord Output texture coordinates + @param index Output triangle list indices + @param textureScale Lower-right texture coordinate + @param spaceCentered If true, the coordinates generated are centered at the origin before the transformation. + @param twoSided If true, matching top and bottom planes are generated. + \param elevation If non-NULL, values from this image are used as elevations. Apply an \a xform to adjust the scale + */ + static void generateGrid( + Array& vertex, + Array& texCoord, + Array& index, + int wCells = 10, + int hCells = 10, + const Vector2& textureScale = Vector2(1,1), + bool spaceCentered = true, + bool twoSided = true, + const CoordinateFrame& xform = CoordinateFrame(), + const Image1::Ref& elevation = NULL); + + /** Converts quadlist (QUADS), + triangle fan (TRIANGLE_FAN), + tristrip(TRIANGLE_STRIP), and quadstrip (QUAD_STRIP) indices into + triangle list (TRIANGLES) indices and appends them to outIndices. */ + template + static void toIndexedTriList( + const Array& inIndices, + MeshAlg::Primitive inType, + Array& outIndices) { + + debugAssert( + inType == PrimitiveType::TRIANGLE_STRIP || + inType == PrimitiveType::TRIANGLE_FAN || + inType == PrimitiveType::QUADS || + inType == PrimitiveType::QUAD_STRIP); + + const int inSize = inIndices.size(); + + switch(inType) { + case PrimitiveType::TRIANGLE_FAN: + { + debugAssert(inSize >= 3); + + int N = outIndices.size(); + outIndices.resize(N + (inSize - 2) * 3); + + for (IndexType i = 1, outIndex = N; i <= (inSize - 2); ++i, outIndex += 3) { + outIndices[outIndex] = inIndices[0]; + outIndices[outIndex + 1] = inIndices[i]; + outIndices[outIndex + 2] = inIndices[i + 1]; + } + + break; + } + + case PrimitiveType::TRIANGLE_STRIP: + { + debugAssert(inSize >= 3); + + int N = outIndices.size(); + outIndices.resize(N + (inSize - 2) * 3); + + bool atEven = false; + for (IndexType i = 0, outIndex = N; i <= (inSize - 2); ++i, outIndex += 3) { + if (atEven) { + outIndices[outIndex] = inIndices[i + 1]; + outIndices[outIndex + 1] = inIndices[i]; + outIndices[outIndex + 2] = inIndices[i + 2]; + atEven = false; + } else { + outIndices[outIndex] = inIndices[i]; + outIndices[outIndex + 1] = inIndices[i + 1]; + outIndices[outIndex + 2] = inIndices[i + 2]; + atEven = true; + } + } + + break; + } + + case PrimitiveType::QUADS: + { + debugAssert(inIndices.size() >= 4); + + int N = outIndices.size(); + outIndices.resize(N + (inSize / 4) * 3); + + for (IndexType i = 0, outIndex = N; i <= (inSize - 4); i += 4, outIndex += 6) { + outIndices[outIndex] = inIndices[i]; + outIndices[outIndex + 1] = inIndices[i + 1]; + outIndices[outIndex + 2] = inIndices[i + 3]; + outIndices[outIndex + 3] = inIndices[i + 1]; + outIndices[outIndex + 4] = inIndices[i + 2]; + outIndices[outIndex + 5] = inIndices[i + 3]; + } + + break; + } + + case PrimitiveType::QUAD_STRIP: + { + debugAssert(inIndices.size() >= 4); + + int N = outIndices.size(); + outIndices.resize(N + (inSize - 2) * 3); + + for (IndexType i = 0, outIndex = N; i <= (inSize - 2); i += 2, outIndex += 6) { + outIndices[outIndex] = inIndices[i]; + outIndices[outIndex + 1] = inIndices[i + 1]; + outIndices[outIndex + 2] = inIndices[i + 2]; + outIndices[outIndex + 3] = inIndices[i + 2]; + outIndices[outIndex + 4] = inIndices[i + 1]; + outIndices[outIndex + 5] = inIndices[i + 3]; + } + break; + } + default: + alwaysAssertM(false, "Illegal argument"); + } + } + +protected: + + /** + Helper for computeAdjacency. If a directed edge with index e already + exists from i0 to i1 then e is returned. If a directed edge with index e + already exists from i1 to i0, ~e is returned (the complement) and + edgeArray[e] is set to f. Otherwise, a new edge is created from i0 to i1 + with first face index f and its index is returned. + + @param vertexArray Vertex positions to use when deciding colocation. + + @param area Area of face f. When multiple edges of the same direction + are found between the same vertices (usually because of degenerate edges) + the face with larger area is kept in the edge table. + */ + static int findEdgeIndex( + const Array& vertexArray, + Array& geometricEdgeArray, + int i0, int i1, int f, double area); +}; +} +#endif + diff --git a/externals/g3dlite/G3D/MeshBuilder.h b/externals/g3dlite/G3D/MeshBuilder.h new file mode 100644 index 00000000000..9920d59d7d3 --- /dev/null +++ b/externals/g3dlite/G3D/MeshBuilder.h @@ -0,0 +1,82 @@ +/** + @file MeshBuilder.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2002-02-27 + @edited 2004-10-04 + */ +#ifndef G3D_MESHBUILDER_H +#define G3D_MESHBUILDER_H + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/Vector3.h" +#include "G3D/Triangle.h" + +namespace G3D { + +/** + Allows creation of optimized watertight meshes from unoptimized polygon soups. + See also G3D::MeshAlg for algorithms that operate on the output. + */ +class MeshBuilder { +public: + + /** + Set setWeldRadius to AUTO_WELD to weld vertices closer than 1/2 + the smallest edge length in a model. + */ + enum {AUTO_WELD = -100}; + +private: + /** Indices of vertices in or near a grid cell. */ + typedef Array List; + + std::string name; + + /** + All of the triangles, as a long triangle list. + */ + Array triList; + + void centerTriList(); + void computeBounds(Vector3& min, Vector3& max); + + bool _twoSided; + + /** Collapse radius */ + double close; + +public: + + inline MeshBuilder(bool twoSided = false) : _twoSided(twoSided), close(AUTO_WELD) {} + + /** Writes the model to the arrays, which can then be used with + G3D::IFSModel::save and G3D::MeshAlg */ + void commit(std::string& name, Array& indexArray, Array& vertexArray); + + /** + Adds a new triangle to the model. (Counter clockwise) + */ + void addTriangle(const Vector3& a, const Vector3& b, const Vector3& c); + + /** + Adds two new triangles to the model. (Counter clockwise) + */ + void addQuad(const Vector3& a, const Vector3& b, const Vector3& c, const Vector3& d); + + void addTriangle(const Triangle& t); + + void setName(const std::string& n); + + /** Vertices within this distance are considered identical. + Use AUTO_WELD (the default) to have the distance be a function of the model size.*/ + void setWeldRadius(double r) { + close = r; + } +}; + +} // namespace + +#endif diff --git a/externals/g3dlite/G3D/NetAddress.h b/externals/g3dlite/G3D/NetAddress.h new file mode 100644 index 00000000000..8ed20a06690 --- /dev/null +++ b/externals/g3dlite/G3D/NetAddress.h @@ -0,0 +1,132 @@ +#ifndef G3D_NETADDRESS_H +#define G3D_NETADDRESS_H + +#include "G3D/platform.h" +#include "G3D/Table.h" + +/** These control the version of Winsock used by G3D. + Version 2.0 is standard for G3D 6.09 and later. + Version 1.1 is standard for G3D 6.08 and earlier. + */ +#define G3D_WINSOCK_MAJOR_VERSION 2 +#define G3D_WINSOCK_MINOR_VERSION 0 + +#ifdef G3D_WIN32 +# if (G3D_WINSOCK_MAJOR_VERSION == 2) +# include +# elif (G3D_WINSOCK_MAJOR_VERSION == 1) +# include +# endif +#else +# include +# include +# include +# ifndef SOCKADDR_IN +# define SOCKADDR_IN struct sockaddr_in +# endif +# ifndef SOCKET +# define SOCKET int +# endif +#endif + +#include "G3D/g3dmath.h" + +namespace G3D { + +class NetAddress { +private: + friend class NetworkDevice; + friend class LightweightConduit; + friend class ReliableConduit; + + /** Host byte order */ + void init(uint32 host, uint16 port); + void init(const std::string& hostname, uint16 port); + NetAddress(const SOCKADDR_IN& a); + NetAddress(const struct in_addr& addr, uint16 port = 0); + + SOCKADDR_IN addr; + +public: + /** + In host byte order + */ + NetAddress(uint32 host, uint16 port = 0); + + /** + @param port Specified in host byte order (i.e., don't worry about endian issues) + */ + NetAddress(const std::string& hostname, uint16 port); + + /** + @param hostnameAndPort in the form "hostname:port" or "ip:port" + */ + NetAddress(const std::string& hostnameAndPort); + + /** + @deprecated Use G3D::NetworkDevice::broadcastAddressArray() + + @brief Creates a UDP broadcast address for use with a + G3D::LightweightConduit. + + UDP broadcast allows one machine to send a packet to all machines + on the same local network. The IP portion of the address is + 0xFFFFFFFF, which indicates "broadcast" to the underlying socket + API. This feature is not available with the connection-based TCP + protocol abstracted by G3D::ReliableConduit; use multisend + instead. + */ + static NetAddress broadcastAddress(uint16 port); + + NetAddress(); + + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + + /** @brief Returns true if this is not an illegal address. */ + bool ok() const; + + /** @brief Returns a value in host format (i.e., don't worry about + endian issues) */ + inline uint32 ip() const { + return ntohl(addr.sin_addr.s_addr); + //return ntohl(addr.sin_addr.S_un.S_addr); + } + + inline uint16 port() const { + return ntohs(addr.sin_port); + } + + std::string ipString() const; + std::string toString() const; + +}; + +std::ostream& operator<<(std::ostream& os, const NetAddress&); + +} // namespace G3D + +template <> struct HashTrait { + static size_t hashCode(const G3D::NetAddress& key) { + return static_cast(key.ip() + (static_cast(key.port()) << 16)); + } +}; + +namespace G3D { + +/** + Two addresses may point to the same computer but be != because + they have different IP's. + */ +inline bool operator==(const NetAddress& a, const NetAddress& b) { + return (a.ip() == b.ip()) && (a.port() == b.port()); +} + + +inline bool operator!=(const NetAddress& a, const NetAddress& b) { + return !(a == b); +} + +} // namespace G3D + +#endif diff --git a/externals/g3dlite/G3D/NetworkDevice.h b/externals/g3dlite/G3D/NetworkDevice.h new file mode 100644 index 00000000000..ea3290cbc09 --- /dev/null +++ b/externals/g3dlite/G3D/NetworkDevice.h @@ -0,0 +1,738 @@ +/** + @file NetworkDevice.h + + These classes abstract networking from the socket level to a + serialized messaging style that is more appropriate for games. The + performance has been tuned for sending many small messages. The + message protocol contains a header that prevents them from being used + with raw UDP/TCP (e.g. connecting to an HTTP server). + + LightweightConduit and ReliableConduits have different interfaces + because they have different semantics. You would never want to + interchange them without rewriting the surrounding code. + + NetworkDevice creates conduits because they need access to a global + log pointer and because I don't want non-reference counted conduits + being created. + + Be careful with threads and reference counting. The reference + counters are not threadsafe, and are also not updated correctly if a + thread is explicitly killed. Since the conduits will be passed by + const XConduitRef& most of the time this doesn't appear as a major + problem. With non-blocking conduits, you should need few threads + anyway. + + LightweightConduits preceed each message with a 4-byte host order + unsigned integer that is the message type. This does not appear in + the message serialization/deserialization. + + ReliableConduits preceed each message with two 4-byte host order + unsigned integers. The first is the message type and the second + indicates the length of the rest of the data. The size does not + include the size of the header itself. The minimum message is 9 + bytes:a 4-byte type, a 4-byte header equal to "1", and one byte of data. + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @created 2002-11-22 + @edited 2006-11-25 + */ + +#ifndef G3D_NETWORKDEVICE_H +#define G3D_NETWORKDEVICE_H + +#include "G3D/platform.h" +#include "G3D/NetAddress.h" + +#include +#include +#include "G3D/g3dmath.h" + +#include "G3D/ReferenceCount.h" +#include "G3D/Array.h" +#include "G3D/BinaryOutput.h" + +namespace G3D { + +class TextOutput; + +class Conduit : public ReferenceCountedObject { +protected: + friend class NetworkDevice; + friend class NetListener; + + uint64 mSent; + uint64 mReceived; + uint64 bSent; + uint64 bReceived; + + SOCKET sock; + + /** + Used for serialization. One per socket + to make this threadsafe. + */ + BinaryOutput binaryOutput; + + Conduit(); + +public: + + virtual ~Conduit(); + uint64 bytesSent() const; + uint64 messagesSent() const; + uint64 bytesReceived() const; + uint64 messagesReceived() const; + + /** + If true, receive will return true. + */ + virtual bool messageWaiting(); + + /** + Returns the type of the waiting message (i.e. the type supplied + with send). The return value is zero when there is no message + waiting. + + One way to use this is to have a Table mapping message types to + pre-allocated subclasses so receiving looks like: + +
+         // My base class for messages.
+         class Message {
+             virtual void serialize(BinaryOutput&) const;
+             virtual void deserialize(BinaryInput&);
+             virtual void process() = 0;
+         };
+
+         Message* m = table[conduit->waitingMessageType()];
+         conduit->receive(m);
+         m->process();
+     
+ + Another is to simply switch on the message type: + +
+         switch (conduit->waitingMessageType()) {
+         case 0:
+            // No message
+            break;
+
+         case ENTITY_SPAWN_MSG:
+            {
+               EntitySpawnMsg m;
+               condiut->receive(m);
+               spawnEntity(m.id, m.position, m.modelID);
+            }
+            break;
+            ...
+         }
+      
+ */ + virtual uint32 waitingMessageType() = 0; + + /** Returns true if the connection is ok. */ + bool ok() const; +}; + +typedef ReferenceCountedPointer ReliableConduitRef; + +#ifdef __GNUC__ +// Workaround for a known bug in gcc 4.x where htonl produces +// a spurrious warning. +// http://gcc.gnu.org/ml/gcc-bugs/2005-10/msg03270.html +uint32 gcchtonl(uint32); +#endif + +// Messaging and stream APIs must be supported on a single class because +// sometimes an application will switch modes on a single socket. For +// example, when transferring 3D level geometry during handshaking with +// a game server. +/** + A conduit that guarantees messages will arrive, intact and in order. + Create on the client using NetworkDevice::createReliableConduit and + on the server using NetListener::waitForConnection. Set the reference + counted pointer to NULL to disconnect. + + To construct a ReliableConduit: +
    +
  1. Create a G3D::NetworkDevice (if you are using G3D::GApp, it creates + one for you) on the client and on the server. +
  2. On the server, create a G3D::NetListener using + G3D::NetworkDevice::createListener +
  3. On the server, invoke G3D::NetListener::waitForConnection. +
  4. On the client, call G3D::NetworkDevice::createReliableConduit. + You will need the server's G3D::NetAddress. Consider using + G3D::Discovery::Client to find it via broadcasting. +
+ + */ +class ReliableConduit : public Conduit { +private: + friend class NetworkDevice; + friend class NetListener; + + enum State {RECEIVING, HOLDING, NO_MESSAGE} state; + + NetAddress addr; + + /** + Type of the incoming message. + */ + uint32 messageType; + + /** + Total size of the incoming message (read from the header). + */ + uint32 messageSize; + + /** Shared buffer for receiving messages. */ + void* receiveBuffer; + + /** Total size of the receiveBuffer. */ + size_t receiveBufferTotalSize; + + /** Size occupied by the current message... so far. This will be + equal to messageSize when the whole message has arrived. + */ + size_t receiveBufferUsedSize; + + ReliableConduit(const NetAddress& addr); + + ReliableConduit(const SOCKET& sock, + const NetAddress& addr); + + template static void serializeMessage + (uint32 t, const T& m, BinaryOutput& b) { + + b.writeUInt32(t); + + // Reserve space for the 4 byte size header + b.writeUInt32(0); + + size_t L = b.length(); + m.serialize(b); + if ((size_t)b.length() == L) { + // No data was created by serialization. + // We need to send at least one byte because receive assumes that + // a zero length message is an error. + b.writeUInt8(0xFF); + } + + uint32 len = b.size() - 8; + + // We send the length first to tell recv how much data to read. + // Here we abuse BinaryOutput a bit and write directly into + // its buffer, violating the abstraction. + // Note that we write to the second set of 4 bytes, which is + // the size field. + uint32* lenPtr = ((uint32*)b.getCArray()) + 1; + #if defined(__GNUC__) + *lenPtr = gcchtonl(len); + #else + *lenPtr = htonl(len); + #endif + } + + + void sendBuffer(const BinaryOutput& b); + + /** Accumulates whatever part of the message (not the header) is + still waiting on the socket into the receiveBuffer during + state = RECEIVING mode. Closes the socket if anything goes + wrong. When receiveBufferUsedSize == messageSize, the entire + message has arrived. */ + void receiveIntoBuffer(); + + /** Receives the messageType and messageSize from the socket. */ + void receiveHeader(); + +public: + + /** + Client invokes this to connect to a server. The call blocks until the + conduit is opened. The conduit will not be ok() if it fails. + */ + static ReliableConduitRef create(const NetAddress& address); + + /** Closes the socket. */ + ~ReliableConduit(); + + + // The message is actually copied from the socket to an internal buffer during + // this call. Receive only deserializes. + virtual bool messageWaiting(); + + /** + Serializes the message and schedules it to be sent as soon as possible, + and then returns immediately. The message can be any class with + a serialize and deserialize method. On the receiving side, + use G3D::ReliableConduit::waitingMessageType() to detect the incoming + message and then invoke G3D::ReliableConduit::receive(msg) where msg + is of the same class as the message that was sent. + + The actual data sent across the network is preceeded by the + message type and the size of the serialized message as a 32-bit + integer. The size is sent because TCP is a stream protocol and + doesn't have a concept of discrete messages. + */ + template inline void send(uint32 type, const T& message) { + binaryOutput.reset(); + serializeMessage(type, message, binaryOutput); + sendBuffer(binaryOutput); + } + + /** Sends an empty message with the given type. Useful for sending + commands that have no parameters. */ + void send(uint32 type); + + /** Send the same message to a number of conduits. Useful for sending + data from a server to many clients (only serializes once). */ + template + inline static void multisend( + const Array& array, + uint32 type, + const T& m) { + + if (array.size() > 0) { + array[0]->binaryOutput.reset(); + serializeMessage(type, m, array[0]->binaryOutput); + + for (int i = 0; i < array.size(); ++i) { + array[i]->sendBuffer(array[0]->binaryOutput); + } + } + } + + virtual uint32 waitingMessageType(); + + /** + If a message is waiting, deserializes the waiting message into + message and returns true, otherwise returns false. You can + determine the type of the message (and therefore, the class + of message) using G3D::ReliableConduit::waitingMessageType(). + */ + template inline bool receive(T& message) { + if (! messageWaiting()) { + return false; + } + + debugAssert(state == HOLDING); + // Deserialize + BinaryInput b((uint8*)receiveBuffer, receiveBufferUsedSize, G3D_LITTLE_ENDIAN, BinaryInput::NO_COPY); + message.deserialize(b); + + // Don't let anyone read this message again. We leave the buffer + // allocated for the next caller, however. + receiveBufferUsedSize = 0; + state = NO_MESSAGE; + messageType = 0; + messageSize = 0; + + // Potentially read the next message. + messageWaiting(); + + return true; + } + + /** Removes the current message from the queue. */ + inline void receive() { + if (! messageWaiting()) { + return; + } + receiveBufferUsedSize = 0; + state = NO_MESSAGE; + messageType = 0; + messageSize = 0; + + // Potentially read the next message. + messageWaiting(); + } + + NetAddress address() const; +}; + + +typedef ReferenceCountedPointer LightweightConduitRef; + +/** + Provides fast but unreliable transfer of messages. On a LAN, + LightweightConduit will probably never drop messages but you + might get your messages out of order. On an internet + connection it might drop messages altogether. Messages are never + corrupted, however. LightweightConduit requires a little less setup + and overhead than ReliableConduit. ReliableConduit guarantees + message delivery and order but requires a persistent connection. + + To set up a LightweightConduit (assuming you have already made + subclasses of G3D::NetMessage based on your application's + pcommunication protocol): + +[Server Side] +
    +
  1. Call LightweightConduit::create(port, true, false), +where port is the port on which you will receive messages. + +
  2. Poll LightweightConduit::messageWaiting from your main loop. When +it is true (or, equivalently, when LightweightConduit::waitingMessageType +is non-zero) there is an incoming message. + +
  3. To read the incoming message, call LightweightConduit::receive with +the appropriate class type, which mist have a deserialize method. +LightweightConduit::waitingMessageType tells you what class is +needed (you make up your own message constants for your program; numbers +under 1000 are reserved for G3D's internal use). + +
  4. When done, simply set the G3D::LightweightConduitRef to NULL or let +it go out of scope and the conduit cleans itself up automatically. +
+ +[Client Side] +
    +
  1. Call G3D::LightweightConduit::create(). If you will +broadcast to all servers on a LAN, set the third optional argument to +true (the default is false for no broadcast). You can also set up the +receive port as if it was a server to send and receive from a single +LightweightConduit. + +
  2. To send, call G3D::LightweightConduit::send with the target address +and a pointer to an instance of the message you want to send. + +
  3. When done, simply set the G3D::LightweightConduitRef to NULL or let +it go out of scope and the conduit cleans itself up automatically. + +
+ */ +class LightweightConduit : public Conduit { +private: + friend class NetworkDevice; + + /** + True when waitingForMessageType has read the message + from the network into messageType/messageStream. + */ + bool alreadyReadMessage; + + /** + Origin of the received message. + */ + NetAddress messageSender; + + /** + The type of the last message received. + */ + uint32 messageType; + + /** + The message received (the type has already been read off). + */ + Array messageBuffer; + + LightweightConduit(uint16 receivePort, bool enableReceive, bool enableBroadcast); + + void sendBuffer(const NetAddress& a, BinaryOutput& b); + + /** Maximum transmission unit (packet size in bytes) for this socket. + May vary between sockets. */ + int MTU; + + + template + void serializeMessage( + uint32 type, + const T& m, + BinaryOutput& b) const { + + debugAssert(type != 0); + b.writeUInt32(type); + m.serialize(b); + b.writeUInt32(1); + + debugAssertM(b.size() < MTU, + format("This LightweightConduit is limited to messages of " + "%d bytes (Ethernet hardware limit; this is the " + "'UDP MTU')", maxMessageSize())); + + if (b.size() >= MTU) { + throw LightweightConduit::PacketSizeException( + format("This LightweightConduit is limited to messages of " + "%d bytes (Ethernet hardware limit; this is the " + "'UDP MTU')", maxMessageSize()), + b.size() - 4, // Don't count the type header + maxMessageSize()); + } + } + +public: + + static LightweightConduitRef create(uint16 receivePort, bool enableReceive, bool enableBroadcast); + + class PacketSizeException { + public: + std::string message; + int serializedPacketSize; + int maxMessageSize; + + inline PacketSizeException(const std::string& m, int s, int b) : + message(m), + serializedPacketSize(s), + maxMessageSize(b) {} + }; + + /** Closes the socket. */ + ~LightweightConduit(); + + /** The maximum length of a message that can be sent + (G3D places a small header at the front of each UDP packet; + this is already taken into account by the value returned). + */ + inline int maxMessageSize() const { + return MTU - 4; + } + + + template inline void send(const NetAddress& a, uint32 type, const T& msg) { + binaryOutput.reset(); + serializeMessage(type, msg, binaryOutput); + sendBuffer(a, binaryOutput); + } + + /** Send the same message to multiple addresses (only serializes once). + Useful when server needs to send to a known list of addresses + (unlike direct UDP broadcast to all addresses on the subnet) */ + template inline void send(const Array& a, uint32 type, const T& m) { + binaryOutput.reset(); + serializeMessage(type, m, binaryOutput); + + for (int i = 0; i < a.size(); ++i) { + sendBuffer(a[i], binaryOutput); + } + } + + bool receive(NetAddress& sender); + + template inline bool receive(NetAddress& sender, T& message) { + bool r = receive(sender); + if (r) { + BinaryInput b((messageBuffer.getCArray() + 4), + messageBuffer.size() - 4, + G3D_LITTLE_ENDIAN, BinaryInput::NO_COPY); + message.deserialize(b); + } + + return r; + } + + inline bool receive() { + static NetAddress ignore; + return receive(ignore); + } + + virtual uint32 waitingMessageType(); + + + virtual bool messageWaiting(); +}; + +/////////////////////////////////////////////////////////////////////////////// + +typedef ReferenceCountedPointer NetListenerRef; + +/** + Runs on the server listening for clients trying to make reliable connections. + */ +class NetListener : public ReferenceCountedObject { +private: + + friend class NetworkDevice; + + SOCKET sock; + + /** Port is in host byte order. */ + NetListener(uint16 port); + +public: + + static NetListenerRef create(const uint16 port); + + ~NetListener(); + + /** Block until a connection is received. Returns NULL if + something went wrong. */ + ReliableConduitRef waitForConnection(); + + /** True if a client is waiting (i.e. waitForConnection will + return immediately). */ + bool clientWaiting() const; + + bool ok() const; +}; + + +/////////////////////////////////////////////////////////////////////////////// + +/** + @brief Abstraction of network (socket) functionality. + + An abstraction over sockets that provides a message-based network + infrastructure optimized for sending many small (~500 bytes) messages. + All functions always return immediately. + + Create only one NetworkDevice per process (a WinSock restriction). + + NetworkDevice is technically not thread safe. However, as long as + you use different conduits on different threads (or lock conduits + before sending), you will encounter no problems sharing the single + NetworkDevice across multiple threads. That is, do not invoke the same + Conduit's send or receive method on two threads at once. + + This assumes that the underlying WinSock/BSD sockets implementation + is thread safe. That is not guaranteed, but in practice seems + to always be true (see + http://tangentsoft.net/wskfaq/intermediate.html#threadsafety) + +
+ + IP networks use "network byte order" (big-endian) for + communicating integers. "Host byte order" is the endian-ness of + the local machine (typically little-endian; see + System::endian). The C functions htonl() and ntohl() convert 32-bit + values between these formats. G3D only ever exposes host byte order, + so programmers rarely need to be aware of the distinction. + + */ +class NetworkDevice { +public: + + /** @brief Description of an ethernet or wireless ethernet adapter.*/ + class EthernetAdapter { + public: + /** Reverse-DNS of the ip address.*/ + std::string hostname; + + /** Name of the adapter */ + std::string name; + + /** IP address in host byte order.*/ + uint32 ip; + + /** Subnet mask in host byte order.*/ + uint32 subnet; + + /** UDP broadcast address in host byte order.*/ + uint32 broadcast; + + /** MAC (hardware) address, if known */ + uint8 mac[6]; + + EthernetAdapter(); + + /** Produces a text description of this adapter */ + void describe(TextOutput& t) const; + }; + +private: + + friend class Conduit; + friend class LightweightConduit; + friend class ReliableConduit; + friend class NetListener; + + bool initialized; + + Array m_adapterArray; + + /** Broadcast addresses available on this machine, + extracted from m_adapterArray.*/ + Array m_broadcastAddresses; + + /** Utility method. */ + void closesocket(SOCKET& sock) const; + + /** Utility method. Returns true on success.*/ + bool bind(SOCKET sock, const NetAddress& addr) const; + + /** The global instance */ + static NetworkDevice* s_instance; + + NetworkDevice(); + + bool init(); + + void _cleanup(); + + /** Called from init to update m_adapterArray and + m_broadcastAddresses. */ + void addAdapter(const EthernetAdapter& a); + +public: + + /** Prints an IP address to a string. + @param ip In host byte order.*/ + static std::string formatIP(uint32 ip); + + /** Prints a MAC address to a string. */ + static std::string formatMAC(const uint8 mac[6]); + + ~NetworkDevice(); + + /** Returns the available ethernet adapters for the current + machine that are online. Does not include the loopback adapter + for localhost.*/ + inline const Array& adapterArray() const { + return m_adapterArray; + } + + /** Returns the (unique) IP addresses for UDP broadcasting + extracted from adapterArray(). All are in host byte order. */ + inline const Array& broadcastAddressArray() const { + return m_broadcastAddresses; + } + + /** + Returns NULL if there was a problem initializing the network. + */ + static NetworkDevice* instance(); + + /** + Shuts down the network device (destroying the global instance). + */ + static void cleanup(); + + /** + Prints a human-readable description of this machine + to the text output stream. + */ + void describeSystem( + TextOutput& t); + + void describeSystem( + std::string& s); + + /** Returns the name (or one of the names) of this computer */ + std::string localHostName() const; + + /** There is often more than one address for the local host. This + returns all of them. + @deprecated Use adapterArray() + */ + void localHostAddresses(Array& array) const; +}; + + +#ifdef __GNUC__ +inline uint32 gcchtonl(uint32 x) { + // This pragma fools gcc into surpressing all error messages, + // including the bogus one that it creates for htonl +# pragma GCC system_header + return htonl(x); +} +#endif + +} // G3D namespace + +#ifndef _WIN32 +#undef SOCKADDR_IN +#undef SOCKET +#endif + +#endif diff --git a/externals/g3dlite/G3D/ParseError.h b/externals/g3dlite/G3D/ParseError.h new file mode 100644 index 00000000000..f02948e3d29 --- /dev/null +++ b/externals/g3dlite/G3D/ParseError.h @@ -0,0 +1,59 @@ +/** + @file ParseError.h + + @maintainer Morgan McGuire + + @created 2009-11-15 + @edited 2009-11-15 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ +#ifndef G3D_ParseError_h +#define G3D_ParseError_h + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include + +namespace G3D { + +/** Thrown by TextInput, Any, and other parsers on unexpected input. */ +class ParseError { +public: + enum {UNKNOWN = -1}; + + /** Empty means unknown */ + std::string filename; + + /** For a binary file, the location of the parse error. -1 if unknown.*/ + int64 byte; + + /** For a text file, the line number is the line number of start of token which caused the exception. 1 is + the first line of the file. -1 means unknown. Note that you can use + TextInput::Settings::startingLineNumberOffset to shift the effective line + number that is reported by that class. + */ + int line; + + /** Character number (in the line) of the start of the token which caused the + exception. 1 is the character in the line. May be -1 if unknown. + */ + int character; + + std::string message; + + ParseError() : byte(UNKNOWN), line(UNKNOWN), character(UNKNOWN) {} + + virtual ~ParseError() {} + + ParseError(const std::string& f, int l, int c, const std::string& m) : + filename (f), byte(UNKNOWN), line(l), character(c), message(m) {} + + ParseError(const std::string& f, int64 b, const std::string& m) : + filename (f), byte(b), line(UNKNOWN), character(UNKNOWN), message(m) {} +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/PhysicsFrame.h b/externals/g3dlite/G3D/PhysicsFrame.h new file mode 100644 index 00000000000..a5a9305b83e --- /dev/null +++ b/externals/g3dlite/G3D/PhysicsFrame.h @@ -0,0 +1,74 @@ +/** + @file PhysicsFrame.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2002-07-08 + @edited 2006-01-10 +*/ + +#ifndef G3D_PHYSICSFRAME_H +#define G3D_PHYSICSFRAME_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Matrix3.h" +#include "G3D/Quat.h" +#include "G3D/CoordinateFrame.h" +#include +#include + + +namespace G3D { + +/** + An RT transformation using a quaternion; suitable for + physics integration. + + This interface is in "Beta" and will change in the next release. + */ +class PhysicsFrame { +public: + + Quat rotation; + + /** + Takes object space points to world space. + */ + Vector3 translation; + + /** + Initializes to the identity frame. + */ + PhysicsFrame(); + + /** + Purely translational force + */ + PhysicsFrame(const Vector3& translation) : translation(translation) {} + + PhysicsFrame(const CoordinateFrame& coordinateFrame); + + /** Compose: create the transformation that is other followed by this.*/ + PhysicsFrame operator*(const PhysicsFrame& other) const; + + virtual ~PhysicsFrame() {} + + CoordinateFrame toCoordinateFrame() const; + + /** + Linear interpolation (spherical linear for the rotations). + */ + PhysicsFrame lerp( + const PhysicsFrame& other, + float alpha) const; + + void deserialize(class BinaryInput& b); + + void serialize(class BinaryOutput& b) const; + +}; + +} // namespace + +#endif diff --git a/externals/g3dlite/G3D/Plane.h b/externals/g3dlite/G3D/Plane.h new file mode 100644 index 00000000000..360bcd2bc75 --- /dev/null +++ b/externals/g3dlite/G3D/Plane.h @@ -0,0 +1,161 @@ +/** + @file Plane.h + + Plane class + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2001-06-02 + @edited 2004-07-18 +*/ + +#ifndef G3D_PLANE_H +#define G3D_PLANE_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Vector4.h" +#include "G3D/debugAssert.h" + +namespace G3D { + +/** + An infinite 2D plane in 3D space. + */ +class Plane { +private: + + /** normal.Dot(x,y,z) = distance */ + Vector3 _normal; + float _distance; + + /** + Assumes the normal has unit length. + */ + Plane(const Vector3& n, float d) : _normal(n), _distance(d) { + } + +public: + + Plane() : _normal(Vector3::unitY()), _distance(0) { + } + + /** + Constructs a plane from three points. + */ + Plane( + const Vector3& point0, + const Vector3& point1, + const Vector3& point2); + + /** + Constructs a plane from three points, where at most two are + at infinity (w = 0, not xyz = inf). + */ + Plane( + Vector4 point0, + Vector4 point1, + Vector4 point2); + + /** + The normal will be unitized. + */ + Plane( + const Vector3& __normal, + const Vector3& point); + + static Plane fromEquation(float a, float b, float c, float d); + + Plane(class BinaryInput& b); + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + + virtual ~Plane() {} + + /** + Returns true if point is on the side the normal points to or + is in the plane. + */ + inline bool halfSpaceContains(Vector3 point) const { + // Clamp to a finite range for testing + point = point.clamp(Vector3::minFinite(), Vector3::maxFinite()); + + // We can get away with putting values *at* the limits of the float32 range into + // a dot product, since the dot product is carried out on float64. + return _normal.dot(point) >= _distance; + } + + /** + Returns true if point is on the side the normal points to or + is in the plane. + */ + inline bool halfSpaceContains(const Vector4& point) const { + if (point.w == 0) { + return _normal.dot(point.xyz()) > 0; + } else { + return halfSpaceContains(point.xyz() / point.w); + } + } + + /** + Returns true if point is on the side the normal points to or + is in the plane. Only call on finite points. Faster than halfSpaceContains. + */ + inline bool halfSpaceContainsFinite(const Vector3& point) const { + debugAssert(point.isFinite()); + return _normal.dot(point) >= _distance; + } + + /** + Returns true if the point is nearly in the plane. + */ + inline bool fuzzyContains(const Vector3 &point) const { + return fuzzyEq(point.dot(_normal), _distance); + } + + inline const Vector3& normal() const { + return _normal; + } + + /** + Returns distance from point to plane. Distance is negative if point is behind (not in plane in direction opposite normal) the plane. + */ + inline float distance(const Vector3& x) const { + return (_normal.dot(x) - _distance); + } + + inline Vector3 closestPoint(const Vector3& x) const { + return x + (_normal * (-distance(x))); + } + + /** Returns normal * distance from origin */ + Vector3 center() const { + return _normal * _distance; + } + + /** + Inverts the facing direction of the plane so the new normal + is the inverse of the old normal. + */ + void flip(); + + /** + Returns the equation in the form: + + normal.Dot(Vector3(x, y, z)) + d = 0 + */ + void getEquation(Vector3 &normal, double& d) const; + void getEquation(Vector3 &normal, float& d) const; + + /** + ax + by + cz + d = 0 + */ + void getEquation(double& a, double& b, double& c, double& d) const; + void getEquation(float& a, float& b, float& c, float& d) const; + + std::string toString() const; +}; + +} // namespace + +#endif diff --git a/externals/g3dlite/G3D/PointHashGrid.h b/externals/g3dlite/G3D/PointHashGrid.h new file mode 100644 index 00000000000..0db9e677321 --- /dev/null +++ b/externals/g3dlite/G3D/PointHashGrid.h @@ -0,0 +1,917 @@ +/** + @file PointHashGrid.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @created 2008-07-01 + @edited 2009-05-28 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. +*/ +#ifndef G3D_PointHashGrid_h +#define G3D_PointHashGrid_h + +#include "G3D/platform.h" +#include "G3D/EqualsTrait.h" +#include "G3D/HashTrait.h" +#include "G3D/Vector3.h" +#include "G3D/Vector3int32.h" +#include "G3D/Array.h" +#include "G3D/Table.h" +#include "G3D/AABox.h" +#include "G3D/Sphere.h" +#include "G3D/SmallArray.h" + +namespace G3D { + +/** + Storage of data in a sparse 3D grid of point-based data. The + space cost for n elements is O(n). For data with + approximately uniform density (with respect to the radius hint), + the time cost of searching for neighbors is O(1). + + Value must be supported by a G3D::PositionTrait, + G3D::EqualsTrait, and G3D::HashFunc. overrides are provided for + common G3D classes like G3D::Vector3. +*/ +template, + class EqualsFunc = EqualsTrait, + class HashFunc = HashTrait > +class PointHashGrid { +private: + +#define ThisType PointHashGrid + + /** A value annotated with precomputed position and hash code.*/ + class Entry { + public: + Vector3 position; + Value value; + }; + + /** One cell of the grid. */ + typedef Array Cell; + typedef Table CellTable; + + /** The cube of +/-1 along each dimension. Initialized by initOffsetArray.*/ + Vector3int32 m_offsetArray[3*3*3]; + + /** Incremented every time the data structure is mutated. + Used by the iterators to determine if the data structure + has changed since iteration began. */ + int m_epoch; + + /** Extent of a cell along one dimension. */ + float m_cellWidth; + + /** 1.0 / cell width */ + float m_invCellWidth; + + /** Conservative bounds; the actual data may be smaller. */ + AABox m_bounds; + + /** Number of elements. */ + int m_size; + + /** Non-empty cells indexed by grid position. Actual 3D position is + position * m_cellWidth*/ + CellTable m_data; + + MemoryManager::Ref m_memoryManager; + + /** Intentionally unimplemented: prevent copy construction. */ + PointHashGrid(const ThisType&); + + + /** Intentionally unimplemented: prevent assignment. */ + PointHashGrid& operator=(const ThisType&); + + + /** Locate the cell and index within that cell containing v. Called by + remove() and contains(). */ + bool find(const Value& v, + Vector3int32& foundCellCoord, + Cell*& foundCell, + int& index) { + + Vector3 pos; + PosFunc::getPosition(v, pos); + + Vector3int32 cellCoord; + getCellCoord(pos, cellCoord); + for (int i = 0; i < 27; ++i) { + Vector3int32 c = cellCoord + m_offsetArray[i]; + Cell* cell = m_data.getPointer(c); + if (cell != NULL) { + // The cell exists + for (int j = 0; j < cell->size(); ++j) { + if (EqualsFunc::equals((*cell)[j].value, v)) { + foundCell = cell; + index = j; + foundCellCoord = c; + return true; + } + } + } + } + + // Not found + return false; + } + + /** Given a real-space position, returns the cell coord + containing it.*/ + inline void getCellCoord(const Vector3& pos, Vector3int32& cellCoord) const { + for (int a = 0; a < 3; ++a) { + cellCoord[a] = iFloor(pos[a] * m_invCellWidth); + } + } + + /** Initializes m_offsetArray. */ + void initOffsetArray() { + int i = 0; + Vector3int32 d; + for (d.x = -1; d.x <= +1; ++d.x) { + for (d.y = -1; d.y <= +1; ++d.y) { + for (d.z = -1; d.z <= +1; ++d.z) { + m_offsetArray[i] = d; + ++i; + } + } + } + + // Put (0, 0, 0) first, so that contains() is most likely to find + // the value quickly. + i = (1 * 3 + 1) * 3 + 1; + debugAssert(m_offsetArray[i] == Vector3int32(0,0,0)); + Vector3int32 temp = m_offsetArray[0]; + m_offsetArray[0] = m_offsetArray[i]; + m_offsetArray[i] = temp; + } + +public: + + /** + @param radiusHint the radius that will typically be used with + beginSphereIntersection and beginBoxIntersection. If two Values are equal, + their positions must be within this radius as well. + */ + PointHashGrid(float radiusHint, const MemoryManager::Ref& m = MemoryManager::create()) : m_size(0), m_memoryManager(m) { + initOffsetArray(); + m_data.clearAndSetMemoryManager(m_memoryManager); + + debugAssertM(radiusHint > 0, "Cell radius must be positive"); + m_cellWidth = radiusHint; + m_invCellWidth = 1.0f / m_cellWidth; + } + + /** + If radiusHint is negative, it is automatically chosen to put + about 5 values in each grid cell (which means about 27 * 5 + values for each beginIntersection call). + */ + PointHashGrid(const Array& init, float radiusHint = -1.0f, const MemoryManager::Ref& m = MemoryManager::create()) : m_size(0), m_memoryManager(m) { + initOffsetArray(); + m_data.clearAndSetMemoryManager(m_memoryManager); + + Vector3 lo(Vector3::inf()); + Vector3 hi(-lo); + + // Compute bounds + Array entry(init.size()); + for (int i = 0; i < entry.size(); ++i) { + const Value& value = init[i]; + Vector3 pos = m_posFunc(value); + + entry[i].value = value; + entry[i].hashCode = m_hashFunc(value); + entry[i].position = pos; + + lo = lo.min(pos); + hi = hi.max(pos); + } + + m_bounds = AABox(lo, hi); + + if (radiusHint <= 0) { + // Compute a good cell width based on the bounds. + // + // N numPerCell + // ----- = --------- + // volume r^3 + + float numPerCell = 5; + radiusHint = + (float)pow(numPerCell * m_bounds.volume() / init.size(), 1.0 / 3.0); + + if (radiusHint == 0) { + // Volume must have been zero because all points were colocated. + radiusHint = 0.1f; + } + } + + insert(init); + } + + /** Returns the number of elements. */ + inline int size() const { + return m_size; + } + + /** Returns a conservative bounding box around the contents. This is + conservative because it is not updated when elements are removed. */ + const AABox& conservativeBoxBounds() const { + return m_bounds; + } + + /** Insert @a v at position @a p given by getPosition(v, p). + Multiple elements that are equal may be inserted; all copies will be + in the data structure. */ + void insert(const Value& v) { + Vector3 pos; + PosFunc::getPosition(v, pos); + Vector3int32 cellCoord; + getCellCoord(pos, cellCoord); + + // See if the cell already exists + Cell& cell = m_data.getCreate(cellCoord); + + if (cell.size() == 0) { + // Use the same memory manager as for the whole class + cell.clearAndSetMemoryManager(m_memoryManager); + } + + Entry& entry = cell.next(); + entry.value = v; + entry.position = pos; + + // Update the bounds + if (size() == 0) { + m_bounds = AABox(pos); + } else { + m_bounds.merge(pos); + } + + ++m_size; + ++m_epoch; + } + + + /** Inserts all elements of the array. */ + void insert(const Array& v) { + for (int i = 0; i < v.size(); ++i) { + insert(v[i]); + } + } + + + /** If there are multiple copies of an element, you must + delete them multiple times. + + @param shrinkIfNecessary If true, deallocate underlying data + structures as they are emptied. False increases performace at + the cost of memory overhead for dynamic structures. + + @return true if the element was found. + */ + bool remove(const Value& v, bool shrinkIfNecessary = true) { + Cell* cell = NULL; + int index = 0; + Vector3int32 cellCoord; + + if (find(v, cellCoord, cell, index)) { + cell->fastRemove(index, shrinkIfNecessary); + --m_size; + ++m_epoch; + + if ((cell->size() == 0) && shrinkIfNecessary) { + // Remove the cell itself + + // Drop our pointer, which is about to dangle + cell = NULL; + bool success = m_data.remove(cellCoord); + debugAssertM(success, "Data structure corrupt: " + "tried to remove a cell that doesn't exist."); + } + + return true; + + } else { + return false; + } + } + + /** Removes all elements of @v. */ + void remove(const Array& v, bool shrink = true) { + for (int i = 0; i < v.size(); ++i) { + remove(v[i], shrink); + } + } + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + class Iterator { + private: + friend class ThisType; + + bool m_isEnd; + + const ThisType* m_grid; + + typename CellTable::Iterator m_tableIterator; + + /** Index within m_tableIterator->value of the current value. */ + int m_arrayIndex; + + const int m_epoch; + + /** End iterator. Note that the m_tableIterator is initialized to the end iterator + of a temporary value! This is ok because we'll never look at the value of the + m_tableIterator, since we're initializing the "end" Iterator.*/ + Iterator() : m_isEnd(true), m_grid(NULL), m_tableIterator(CellTable().end()), + m_arrayIndex(0), m_epoch(0) {} + + Iterator(const ThisType* grid) : + m_isEnd(false), + m_grid(grid), + m_tableIterator( grid->m_data.begin() ), + m_arrayIndex(0), + m_epoch(grid->m_epoch) { } + + private: + + const Value& value() const { + debugAssert(! m_isEnd); + debugAssertM(m_tableIterator->value.size() > m_arrayIndex, + "No more elements"); + return m_tableIterator->value[m_arrayIndex].value; + } + + public: + + inline bool operator!=(const Iterator& other) const { + if (other.m_isEnd && m_isEnd) { + return false; + } else { + return (m_isEnd != other.m_isEnd) || + (m_tableIterator != other.m_tableIterator) || + (m_arrayIndex != other.m_arrayIndex); + } + } + + bool operator==(const Iterator& other) const { + return !(*this != other); + } + + /** Preincrement */ + Iterator& operator++() { + debugAssert(! m_isEnd); + debugAssertM(m_epoch == m_grid->m_epoch, + "It is illegal to mutate the HashGrid " + "while iterating through it."); + + ++m_arrayIndex; + + if (m_arrayIndex >= m_tableIterator->value.size()) { + // Move on to the next cell + ++m_tableIterator; + m_arrayIndex = 0; + + // Check to see if we're at the end + m_isEnd = (m_tableIterator == m_grid->m_data.end()); + } + + return *this; + } + + /** Post increment (slower) */ + Iterator operator++(int) { + debugAssert(! m_isEnd); + Iterator old = *this; + ++(*this); + return old; + } + + const Value& operator*() const { return value(); } + const Value* operator->() const { return &value(); } + operator Value*() const { return &value(); } + }; // Iterator + + + /** Iterate through all members. It is an error to mutate the HashGrid + while iterating through it. Each member can be accessed by "dereferencing" + the iterator: + +
+        for (Grid::Iterator i = grid.begin(); i != grid.end(), ++i) {
+        const Value& = *i;
+        ...
+        }
+        
+ */ + Iterator begin() const { + return Iterator(this); + } + + const Iterator& end() const { + static const Iterator it; + return it; + } + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + // Forward declaration required by older gcc versions for friend declaration in BoxIterator + class SphereIterator; + class BoxIterator { + private: + friend class ThisType; + friend class SphereIterator; + + bool m_isEnd; + + const ThisType* m_grid; + + /** Lower bound on the boxes covered, inclusive. */ + Vector3int32 m_lo; + + /** Upper bound on the boxes covered, inclusive.*/ + Vector3int32 m_hi; + + /** If true, test values against m_box before returning them.*/ + bool m_exact; + + /** The underlying box in 3D space */ + AABox m_box; + + /** The iterator winds through the 3D grid between m_lo and (m_lo + m_extent) in + Z,Y,X-major order. This is the index keeping track of how + far it has come */ + Vector3int32 m_current; + + /** The current cell. */ + Cell* m_cell; + + /** Index within m_cell of the current value */ + int m_arrayIndex; + + const int m_epoch; + + + /** Called from advance() */ + void advanceCell() { + do { + ++m_current.x; + if (m_current.x > m_hi.x) { + m_current.x = m_lo.x; + ++m_current.y; + if (m_current.y > m_hi.y) { + m_current.y = m_lo.y; + ++m_current.z; + if (m_current.z > m_hi.z) { + m_isEnd = true; + return; + } + } + } + + // Pick up the new cell + m_cell = m_grid->m_data.getPointer(m_current); + // Keep advancing if the cell does not exist + } while ((m_cell == NULL) || (m_cell->size() == 0)); + } + + /** Advance to the next value */ + void advance() { + debugAssert(! m_isEnd); + + do { + ++m_arrayIndex; + bool inConstructor = (m_cell == NULL); + if (inConstructor || m_arrayIndex >= m_cell->size()) { + advanceCell(); + m_arrayIndex = 0; + + if (m_isEnd) { + // Ran out of values + return; + } + debugAssert(m_cell != NULL); + } + + // Advance until we have a value that can be returned, either + // because we don't care about exactness or because it is + // guaranteed to be within the box. + } while (m_exact && ! m_box.contains(position())); + } + + + /** End iterator */ + BoxIterator() : m_isEnd(true), m_grid(NULL), m_exact(true), m_current(0,0,0), m_cell(NULL), m_arrayIndex(0), m_epoch(0) {} + + /** Begin iterator */ + BoxIterator(const ThisType* grid, bool exact, const AABox& box) : + m_isEnd(false), + m_grid(grid), + m_exact(exact), + m_box(box), + m_current(-1, 0 ,0), + m_cell(NULL), + m_arrayIndex(0), + m_epoch(grid->m_epoch) { + + m_grid->getCellCoord(box.low(), m_lo); + m_grid->getCellCoord(box.high(), m_hi); + + // Get to the first value + m_current = m_lo; + // Back up one so that advancing takes us to the first + --m_current.x; + advance(); + } + + const Value& value() const { + debugAssert(! m_isEnd); + return (*m_cell)[m_arrayIndex].value; + } + + /** Used by SphereIterator::advance() */ + const Vector3& position() const { + debugAssert(! m_isEnd); + return (*m_cell)[m_arrayIndex].position; + } + + // Intentionally unimplemented + BoxIterator& operator=(const BoxIterator&); + + public: + + inline bool operator!=(const BoxIterator& other) const { + if (other.m_isEnd && m_isEnd) { + return false; + } else { + return (m_isEnd != other.m_isEnd) || + (m_cell != other.m_cell) || + (m_arrayIndex != other.m_arrayIndex); + } + } + + bool operator==(const BoxIterator& other) const { + return !(*this != other); + } + + /** Preincrement */ + BoxIterator& operator++() { + debugAssert(! m_isEnd); + debugAssertM(m_epoch == m_grid->m_epoch, + "It is illegal to mutate the HashGrid " + "while iterating through it."); + + advance(); + + return *this; + } + + /** Post increment (slower) */ + BoxIterator operator++(int) { + Iterator old = *this; + ++(*this); + return old; + } + + const Value& operator*() const { return value(); } + const Value* operator->() const { return &value(); } + operator Value*() const { return &value(); } + + bool hasMore() const { + return ! m_isEnd; + } + }; // BoxIterator + + /** + Finds all values whose positions are within @a box. It is an error to + mutate the PointHashGrid while iterating through it. + + @param exact If false, the iterator will execute more quickly but will likely return some + values that lie outside the box. Set exact = false if you are going to test the + results against the yourself box anyway. + */ + BoxIterator beginBoxIntersection(const AABox& box, bool exact = true) const { + return BoxIterator(this, exact, box); + } + + const BoxIterator& endBoxIntersection() const { + static const BoxIterator it; + return it; + } + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + class SphereIterator { + private: + + friend class ThisType; + + bool m_isEnd; + Sphere m_sphere; + BoxIterator m_boxIterator; + + SphereIterator() : m_isEnd(true) {} + + void advance() { + if (! m_boxIterator.hasMore()) { + m_isEnd = true; + return; + } + + while (! m_sphere.contains(m_boxIterator.position())) { + ++m_boxIterator; + + if (! m_boxIterator.hasMore()) { + m_isEnd = true; + return; + } + } + } + + static AABox getBoundingBox(const Sphere& s) { + AABox box; + s.getBounds(box); + return box; + } + + SphereIterator(const ThisType* grid, const Sphere& sphere) : + m_isEnd(false), + m_sphere(sphere), + m_boxIterator(grid, false, getBoundingBox(sphere)) { + + // Find the first element that is actually in the sphere, + // not just the box. + advance(); + } + + const Value& value() const { + return *m_boxIterator; + } + + // TODO: if the sphere is very big compared to radius, check each + // cell's box to see if the cell itself is actually inside the sphere + // before iterating through it, since there may be many boxes outside the sphere. + + // Intentionally unimplemented + SphereIterator& operator=(const SphereIterator&); + public: + + inline bool operator!=(const SphereIterator& other) const { + if (other.m_isEnd && m_isEnd) { + return false; + } else { + return + (m_isEnd != other.m_isEnd) || + (m_sphere != other.m_sphere) || + (m_boxIterator != other.m_boxIterator); + } + } + + bool operator==(const SphereIterator& other) const { + return !(*this != other); + } + + + + /** Preincrement */ + SphereIterator& operator++() { + debugAssert(! m_isEnd); + + ++m_boxIterator; + advance(); + + return *this; + } + + /** Post increment (slower) */ + SphereIterator operator++(int) { + Iterator old = *this; + ++(*this); + return old; + } + + const Value& operator*() const { return value(); } + const Value* operator->() const { return &value(); } + operator Value*() const { return &value(); } + + bool hasMore() const { + return ! m_isEnd; + } + }; // SphereIterator + + /** + Finds all values whose positions are within @a sphere. It is an error + to mutate the HashGrid while iterating through it. + */ + SphereIterator beginSphereIntersection(const Sphere& sphere) const { + return SphereIterator(this, sphere); + } + + const SphereIterator& endSphereIntersection() const { + static const SphereIterator it; + return it; + } + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + /** + Dereference to access the bounds() and size() [element count] of the underlying + cell objet. + + Example: +
+       for(PointHashGrid::CellIterator iter = grid.beginCells(); iter != grid.endCells(); ++iter) {	
+       entriesFound += iter->size();
+       }
+       
+ */ + class CellIterator { + private: + friend class ThisType; + + bool m_isEnd; + const ThisType* m_grid; + typename CellTable::Iterator m_tableIterator; + const int m_epoch; + + + Cell& cell() { + return m_tableIterator->value; + } + + public: + + class CellObject { + friend class CellIterator; + private: + const CellIterator* m_parent; + + CellObject() : m_parent(NULL) {} + + public: + + /** Returns the bounds on this cell */ + AABox bounds() const { + const Vector3int32& k = m_parent->m_tableIterator->key; + return AABox(Vector3(k) * m_parent->m_cellWidth, + Vector3(k + Vector3int32(1, 1, 1)) * m_parent->m_cellWidth); + } + + /** Number of elements inside this cell */ + int size() const { + debugAssert(! m_parent->m_isEnd); + return m_parent->m_tableIterator->value.size(); + } + }; + + private: + /** Used to make the indirection work.*/ + CellObject m_indirection; + + /** End iterator. Note that the m_tableIterator is initialized to the end iterator + of a temporary value! This is ok because we'll never look at the value of the + m_tableIterator, since we're initializing the "end" Iterator.*/ + CellIterator() : + m_isEnd(true), + m_grid(NULL), + m_tableIterator( CellTable().end() ), + m_epoch(0) {} + + CellIterator(const ThisType* grid) : + m_isEnd(false), + m_grid(grid), + m_tableIterator( grid->m_data.begin()), + m_epoch(grid->m_epoch) { + m_indirection.m_parent = this; + m_isEnd = ! m_tableIterator.hasMore(); + } + + // Intentionally unimplemented + CellIterator& operator=(const CellIterator&); + + public: + + const CellObject& operator*() const { return m_indirection; } + const CellObject* operator->() const { return &m_indirection; } + operator CellObject*() const { return &m_indirection; } + + inline bool operator!=(const CellIterator& other) const { + // != is called more often than == during iteration + return !( + (m_isEnd && other.m_isEnd) || + ((m_isEnd == other.m_isEnd) && + (m_tableIterator != other.m_tableIterator))); + } + + bool operator==(const CellIterator& other) const { + return !(*this != other); + } + + /** Preincrement */ + CellIterator& operator++() { + debugAssertM(m_epoch == m_grid->m_epoch, + "It is illegal to mutate the HashGrid while " + "iterating through it."); + ++m_tableIterator; + m_isEnd = ! m_tableIterator.hasMore(); + return *this; + } + + /** Post increment (slower) */ + CellIterator operator++(int) { + Iterator old = *this; + ++(*this); + return old; + } + + bool hasMore() const { + return ! m_isEnd; + } + }; // CellIterator + + /** Iterates through the non-empty cells. This is intended primarily for + debugging and visualizing the data structure.*/ + CellIterator beginCells() const { + return CellIterator(this); + } + + const CellIterator& endCells() const { + static const CellIterator it; + return it; + } + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + /** Returns true if there is a value that is exactly equal to @a v. This will + check all neighboring cells to avoid roundoff error at cell boundaries. + */ + bool contains(const Value& v) const { + Cell* cell = NULL; + int index = 0; + Vector3int32 cellCoord; + return const_cast(this)->find(v, cellCoord, cell, index); + } + + /** Calls delete on all of the values, which are assumed to be pointers. + This is a helper to avoid requiring you to iterate through the data + structure, removing and deleting each one. Clears the PointHashGrid at the + end. + + Using objects (instead of pointers) or reference counted pointers is + recommended over using pointers and this deleteAll method.*/ + void deleteAll() { + for (Iterator it = begin(); it.hasMore(); ++it) { + delete *it; + } + clear(); + } + + void clearAndSetMemoryManager(const MemoryManager::Ref& m) { + ++m_epoch; + m_size = 0; + m_bounds = AABox(); + + m_data.clearAndSetMemoryManager(m); + m_memoryManager = m; + } + + /** Removes all data. + @param shrink If true, underlying structures are deallocated as + they are freed.*/ + void clear(bool shrink = true) { + m_size = 0; + m_bounds = AABox(); + if (! shrink) { + // Remove all data + for (CellIterator it = beginCells(); it.hasMore(); ++it) { + it.cell().clear(true); + } + } else { + m_data.clear(); + } + ++m_epoch; + } + + int debugGetDeepestBucketSize() const { + return m_data.debugGetDeepestBucketSize(); + } + + float debugGetAverageBucketSize() const { + return m_data.debugGetAverageBucketSize(); + } +#undef ThisType +}; + +} // G3D +#endif diff --git a/externals/g3dlite/G3D/PointKDTree.h b/externals/g3dlite/G3D/PointKDTree.h new file mode 100644 index 00000000000..151cbd5f2f3 --- /dev/null +++ b/externals/g3dlite/G3D/PointKDTree.h @@ -0,0 +1,1185 @@ +/** + @file PointKDTree.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2004-01-11 + @edited 2008-11-02 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + + */ + +#ifndef X_PointKDTree_H +#define X_PointKDTree_H + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/Table.h" +#include "G3D/Vector2.h" +#include "G3D/Vector3.h" +#include "G3D/Vector4.h" +#include "G3D/AABox.h" +#include "G3D/Sphere.h" +#include "G3D/Box.h" +#include "G3D/BinaryInput.h" +#include "G3D/BinaryOutput.h" +#include "G3D/CollisionDetection.h" +#include "G3D/GCamera.h" +#include "G3D/PositionTrait.h" +#include + +namespace G3D { + +/** + A set data structure that supports spatial queries using an axis-aligned + BSP tree for speed. + + PointKDTree allows you to quickly find points in 3D that lie within + a box or sphere. For large sets of objects it is much faster + than testing each object for a collision. See also G3D::KDTree; this class + is optimized for point sets, e.g.,for use in photon mapping and mesh processing. + + Template Parameters + +
+ +
The template parameter T must be one for which + the following functions are overloaded: + +
+      T::T(); (public constructor of no arguments)
+
+       template<> struct PositionTrait {
+         static void getPosition(const T& v, G3D::Vector3& p);};
+
+       template <> struct HashTrait {
+         static size_t hashCode(const T& key);};
+
+       template<> struct EqualsTrait {
+           static bool equals(const T& a, const T& b); };
+    
+ +

+ + G3D provides these for the Vector2, Vector3, and Vector4 classes. + If you use a custom class, or a pointer to a custom class, you will need + to define those functions. + + Moving %Set Members +

It is important that objects do not move without updating the + PointKDTree. If the position of an object is about + to change, PointKDTree::remove it before they change and + PointKDTree::insert it again afterward. For objects + where the hashCode and == operator are invariant with respect + to the 3D position, + you can use the PointKDTree::update method as a shortcut to + insert/remove an object in one step after it has moved. + + + Note: Do not mutate any value once it has been inserted into PointKDTree. Values + are copied interally. All PointKDTree iterators convert to pointers to constant + values to reinforce this. + + If you want to mutate the objects you intend to store in a PointKDTree + simply insert pointers to your objects instead of the objects + themselves, and ensure that the above operations are defined. (And + actually, because values are copied, if your values are large you may + want to insert pointers anyway, to save space and make the balance + operation faster.) + + Dimensions + Although designed as a 3D-data structure, you can use the PointKDTree + for data distributed along 2 or 1 axes by simply returning bounds + that are always zero along one or more dimensions. + +*/ +template, + class HashFunc = HashTrait, + class EqualsFunc = EqualsTrait > +class PointKDTree { +protected: +#define TreeType PointKDTree + + // Unlike the KDTree, the PointKDTree assumes that T elements are + // small and keeps the handle and cached position together instead of + // placing them in separate bounds arrays. Also note that a copy of T + // is kept in the member table and that there is no indirection. + class Handle { + private: + Vector3 m_position; + + public: + T value; + + inline Handle() {} + inline Handle(const T& v) : value(v) { + PositionFunc::getPosition(v, m_position); + } + + /** Used by makeNode to create fake handles for partitioning. */ + void setPosition(const Vector3& v) { + m_position = v; + } + + inline const Vector3& position() const { + return m_position; + } + }; + + /** Returns the bounds of the sub array. Used by makeNode. */ + static AABox computeBounds( + const Array& point) { + + if (point.size() == 0) { + return AABox(Vector3::inf(), Vector3::inf()); + } + + AABox bounds(point[0].position()); + + for (int p = 0; p < point.size(); ++p) { + bounds.merge(point[p].position()); + } + + return bounds; + } + + class Node { + public: + + /** Spatial bounds on all values at this node and its children, based purely on + the parent's splitting planes. May be infinite */ + AABox splitBounds; + + Vector3::Axis splitAxis; + + /** Location along the specified axis */ + float splitLocation; + + /** child[0] contains all values strictly + smaller than splitLocation along splitAxis. + + child[1] contains all values strictly + larger. + + Both may be NULL if there are not enough + values to bother recursing. + */ + Node* child[2]; + + /** Values if this is a leaf node). */ + Array valueArray; + + /** Creates node with NULL children */ + Node() { + splitAxis = Vector3::X_AXIS; + splitLocation = 0; + splitBounds = AABox(-Vector3::inf(), Vector3::inf()); + for (int i = 0; i < 2; ++i) { + child[i] = NULL; + } + } + + /** + Doesn't clone children. + */ + Node(const Node& other) : valueArray(other.valueArray) { + splitAxis = other.splitAxis; + splitLocation = other.splitLocation; + splitBounds = other.splitBounds; + for (int i = 0; i < 2; ++i) { + child[i] = NULL; + } + } + + /** Copies the specified subarray of pt into point, NULLs the children. + Assumes a second pass will set splitBounds. */ + Node(const Array& pt) { + splitAxis = Vector3::X_AXIS; + splitLocation = 0; + for (int i = 0; i < 2; ++i) { + child[i] = NULL; + } + valueArray = pt; + } + + + /** Deletes the children (but not the values) */ + ~Node() { + for (int i = 0; i < 2; ++i) { + delete child[i]; + } + } + + + /** Returns true if this node is a leaf (no children) */ + inline bool isLeaf() const { + return (child[0] == NULL) && (child[1] == NULL); + } + + + /** + Recursively appends all handles and children's handles + to the array. + */ + void getHandles(Array& handleArray) const { + handleArray.append(valueArray); + for (int i = 0; i < 2; ++i) { + if (child[i] != NULL) { + child[i]->getHandles(handleArray); + } + } + } + + + void verifyNode(const Vector3& lo, const Vector3& hi) { + // debugPrintf("Verifying: split %d @ %f [%f, %f, %f], [%f, %f, %f]\n", + // splitAxis, splitLocation, lo.x, lo.y, lo.z, hi.x, hi.y, hi.z); + + debugAssert(lo == splitBounds.low()); + debugAssert(hi == splitBounds.high()); + + for (int i = 0; i < valueArray.length(); ++i) { + const Vector3& b = valueArray[i].position(); + debugAssert(splitBounds.contains(b)); + } + + if (child[0] || child[1]) { + debugAssert(lo[splitAxis] < splitLocation); + debugAssert(hi[splitAxis] > splitLocation); + } + + Vector3 newLo = lo; + newLo[splitAxis] = splitLocation; + Vector3 newHi = hi; + newHi[splitAxis] = splitLocation; + + if (child[0] != NULL) { + child[0]->verifyNode(lo, newHi); + } + + if (child[1] != NULL) { + child[1]->verifyNode(newLo, hi); + } + } + + + /** + Stores the locations of the splitting planes (the structure but not the content) + so that the tree can be quickly rebuilt from a previous configuration without + calling balance. + */ + static void serializeStructure(const Node* n, BinaryOutput& bo) { + if (n == NULL) { + bo.writeUInt8(0); + } else { + bo.writeUInt8(1); + n->splitBounds.serialize(bo); + serialize(n->splitAxis, bo); + bo.writeFloat32(n->splitLocation); + for (int c = 0; c < 2; ++c) { + serializeStructure(n->child[c], bo); + } + } + } + + /** Clears the member table */ + static Node* deserializeStructure(BinaryInput& bi) { + if (bi.readUInt8() == 0) { + return NULL; + } else { + Node* n = new Node(); + n->splitBounds.deserialize(bi); + deserialize(n->splitAxis, bi); + n->splitLocation = bi.readFloat32(); + for (int c = 0; c < 2; ++c) { + n->child[c] = deserializeStructure(bi); + } + } + } + + /** Returns the deepest node that completely contains bounds. */ + Node* findDeepestContainingNode(const Vector3& point) { + + // See which side of the splitting plane the bounds are on + if (point[splitAxis] < splitLocation) { + // Point is on the low side. Recurse into the child + // if it exists. + if (child[0] != NULL) { + return child[0]->findDeepestContainingNode(point); + } + } else if (point[splitAxis] > splitLocation) { + // Point is on the high side, recurse into the child + // if it exists. + if (child[1] != NULL) { + return child[1]->findDeepestContainingNode(point); + } + } + + // There was no containing child, so this node is the + // deepest containing node. + return this; + } + + /** Appends all members that intersect the box. + If useSphere is true, members are tested against the sphere instead. */ + void getIntersectingMembers( + const AABox& sphereBounds, + const Sphere& sphere, + Array& members) const { + + // Test all values at this node. Extract the + // underlying C array for speed + const int N = valueArray.size(); + const Handle* handleArray = valueArray.getCArray(); + + const float r2 = square(sphere.radius); + + // Copy the sphere center so that it is on the stack near the radius + const Vector3 center = sphere.center; + for (int v = 0; v < N; ++v) { + if ((center - handleArray[v].position()).squaredLength() <= r2) { + members.append(handleArray[v].value); + } + } + + // If the left child overlaps the box, recurse into it + if (child[0] && (sphereBounds.low()[splitAxis] < splitLocation)) { + child[0]->getIntersectingMembers(sphereBounds, sphere, members); + } + + // If the right child overlaps the box, recurse into it + if (child[1] && (sphereBounds.high()[splitAxis] > splitLocation)) { + child[1]->getIntersectingMembers(sphereBounds, sphere, members); + } + } + + /** Appends all members that intersect the box. + If useSphere is true, members are tested against the sphere instead. + + Implemented using both box and sphere tests to simplify the implementation + of a future beginSphereInteresection iterator using the same underlying + BoxIterator class. + */ + void getIntersectingMembers( + const AABox& box, + const Sphere& sphere, + Array& members, + bool useSphere) const { + + // Test all values at this node + for (int v = 0; v < valueArray.size(); ++v) { + if ((useSphere && sphere.contains(valueArray[v].position())) || + (! useSphere && box.contains(valueArray[v].position()))) { + members.append(valueArray[v].value); + } + } + + // If the left child overlaps the box, recurse into it + if ((child[0] != NULL) && (box.low()[splitAxis] < splitLocation)) { + child[0]->getIntersectingMembers(box, sphere, members, useSphere); + } + + // If the right child overlaps the box, recurse into it + if ((child[1] != NULL) && (box.high()[splitAxis] > splitLocation)) { + child[1]->getIntersectingMembers(box, sphere, members, useSphere); + } + } + + /** + Recurse through the tree, assigning splitBounds fields. + */ + void assignSplitBounds(const AABox& myBounds) { + splitBounds = myBounds; + +# ifdef G3D_DEBUG + if (child[0] || child[1]) { + debugAssert(splitBounds.high()[splitAxis] > splitLocation); + debugAssert(splitBounds.low()[splitAxis] < splitLocation); + } +# endif + + AABox childBounds[2]; + myBounds.split(splitAxis, splitLocation, childBounds[0], childBounds[1]); + + for (int c = 0; c < 2; ++c) { + if (child[c]) { + child[c]->assignSplitBounds(childBounds[c]); + } + } + } + }; + + class AxisComparator { + private: + Vector3::Axis sortAxis; + + public: + + AxisComparator(Vector3::Axis s) : sortAxis(s) {} + + inline int operator()(const Handle& A, const Handle& B) const { + if (A.position()[sortAxis] > B.position()[sortAxis]) { + return -1; + } else if (A.position()[sortAxis] < B.position()[sortAxis]) { + return 1; + } else { + return 0; + } + } + }; + + /** + Recursively subdivides the subarray. + + The source array will be cleared after it is used + + Call assignSplitBounds() on the root node after making a tree. + */ + Node* makeNode( + Array& source, + Array& temp, + int valuesPerNode, + int numMeanSplits) { + + Node* node = NULL; + + if (source.size() <= valuesPerNode) { + // Make a new leaf node + node = new Node(source); + + // Set the pointers in the memberTable + for (int i = 0; i < source.size(); ++i) { + memberTable.set(source[i].value, node); + } + + } else { + // Make a new internal node + node = new Node(); + + const AABox bounds = computeBounds(source); + const Vector3 extent = bounds.high() - bounds.low(); + + Vector3::Axis splitAxis = extent.primaryAxis(); + + float splitLocation; + + Array lt, gt; + + if (numMeanSplits <= 0) { + source.medianPartition(lt, node->valueArray, gt, temp, AxisComparator(splitAxis)); + splitLocation = node->valueArray[0].position()[splitAxis]; + + if ((node->valueArray.size() > source.size() / 2) && + (source.size() > 10)) { + // Our median split put an awful lot of points on the splitting plane. Try a mean + // split instead + numMeanSplits = 1; + } + } + + if (numMeanSplits > 0) { + // Compute the mean along the axis + + splitLocation = (bounds.high()[splitAxis] + + bounds.low()[splitAxis]) / 2.0; + + Handle splitHandle; + Vector3 v; + v[splitAxis] = splitLocation; + splitHandle.setPosition(v); + + source.partition(splitHandle, lt, node->valueArray, gt, AxisComparator(splitAxis)); + } + +# if defined(G3D_DEBUG) && defined(VERIFY_TREE) + for (int i = 0; i < lt.size(); ++i) { + const Vector3& v = lt[i].position(); + debugAssert(v[splitAxis] < splitLocation); + } + for (int i = 0; i < gt.size(); ++i) { + debugAssert(gt[i].position()[splitAxis] > splitLocation); + } + for (int i = 0; i < node->valueArray.size(); ++i) { + debugAssert(node->valueArray[i].position()[splitAxis] == splitLocation); + } +# endif + + node->splitAxis = splitAxis; + node->splitLocation = splitLocation; + + // Throw away the source array to save memory + source.fastClear(); + + if (lt.size() > 0) { + node->child[0] = makeNode(lt, temp, valuesPerNode, numMeanSplits - 1); + } + + if (gt.size() > 0) { + node->child[1] = makeNode(gt, temp, valuesPerNode, numMeanSplits - 1); + } + + // Add the values stored at this interior node to the member table + for(int i = 0; i < node->valueArray.size(); ++i) { + memberTable.set(node->valueArray[i].value, node); + } + + } + + return node; + } + + /** + Recursively clone the passed in node tree, setting + pointers for members in the memberTable as appropriate. + called by the assignment operator. + */ + Node* cloneTree(Node* src) { + Node* dst = new Node(*src); + + // Make back pointers + for (int i = 0; i < dst->valueArray.size(); ++i) { + memberTable.set(dst->valueArray[i].value, dst); + } + + // Clone children + for (int i = 0; i < 2; ++i) { + if (src->child[i] != NULL) { + dst->child[i] = cloneTree(src->child[i]); + } + } + + return dst; + } + + /** Maps members to the node containing them */ + typedef Table MemberTable; + MemberTable memberTable; + + Node* root; + +public: + + /** To construct a balanced tree, insert the elements and then call + PointKDTree::balance(). */ + PointKDTree() : root(NULL) {} + + + PointKDTree(const PointKDTree& src) : root(NULL) { + *this = src; + } + + + PointKDTree& operator=(const PointKDTree& src) { + delete root; + // Clone tree takes care of filling out the memberTable. + root = cloneTree(src.root); + return *this; + } + + + ~PointKDTree() { + clear(); + } + + /** + Throws out all elements of the set and erases the structure of the tree. + */ + void clear() { + memberTable.clear(); + delete root; + root = NULL; + } + + /** Removes all elements of the set while maintaining the structure of the tree */ + void clearData() { + memberTable.clear(); + Array stack; + stack.push(root); + while (stack.size() > 0) { + Node* node = stack.pop(); + node->valueArray.fastClear(); + + for (int i = 0; i < 2; ++i) { + if (node->child[i] != NULL) { + stack.push(node->child[i]); + } + } + } + } + + + int size() const { + return memberTable.size(); + } + + /** + Inserts an object into the set if it is not + already present. O(log n) time. Does not + cause the tree to be balanced. + */ + void insert(const T& value) { + if (contains(value)) { + // Already in the set + return; + } + + Handle h(value); + + if (root == NULL) { + // This is the first node; create a root node + root = new Node(); + } + + Node* node = root->findDeepestContainingNode(h.position()); + + // Insert into the node + node->valueArray.append(h); + + // Insert into the node table + memberTable.set(value, node); + } + + /** Inserts each elements in the array in turn. If the tree + begins empty (no structure and no elements), this is faster + than inserting each element in turn. You still need to balance + the tree at the end.*/ + void insert(const Array& valueArray) { + // Pre-size the member table to avoid multiple allocations + memberTable.setSizeHint(valueArray.size() + size()); + + if (root == NULL) { + // Optimized case for an empty tree; don't bother + // searching or reallocating the root node's valueArray + // as we incrementally insert. + root = new Node(); + root->valueArray.resize(valueArray.size()); + for (int i = 0; i < valueArray.size(); ++i) { + // Insert in opposite order so that we have the exact same + // data structure as if we inserted each (i.e., order is reversed + // from array). + root->valueArray[valueArray.size() - i - 1] = Handle(valueArray[i]); + memberTable.set(valueArray[i], root); + } + } else { + // Insert at appropriate tree depth. + for (int i = 0; i < valueArray.size(); ++i) { + insert(valueArray[i]); + } + } + } + + + /** + Returns true if this object is in the set, otherwise + returns false. O(1) time. + */ + bool contains(const T& value) { + return memberTable.containsKey(value); + } + + + /** + Removes an object from the set in O(1) time. + It is an error to remove members that are not already + present. May unbalance the tree. + + Removing an element never causes a node (split plane) to be removed... + nodes are only changed when the tree is rebalanced. This behavior + is desirable because it allows the split planes to be serialized, + and then deserialized into an empty tree which can be repopulated. + */ + void remove(const T& value) { + debugAssertM(contains(value), + "Tried to remove an element from a " + "PointKDTree that was not present"); + + Array& list = memberTable[value]->valueArray; + + // Find the element and remove it + for (int i = list.length() - 1; i >= 0; --i) { + if (list[i].value == value) { + list.fastRemove(i); + break; + } + } + memberTable.remove(value); + } + + + /** + If the element is in the set, it is removed. + The element is then inserted. + + This is useful when the == and hashCode methods + on T are independent of the bounds. In + that case, you may call update(v) to insert an + element for the first time and call update(v) + again every time it moves to keep the tree + up to date. + */ + void update(const T& value) { + if (contains(value)) { + remove(value); + } + insert(value); + } + + + /** + Rebalances the tree (slow). Call when objects + have moved substantially from their original positions + (which unbalances the tree and causes the spatial + queries to be slow). + + @param valuesPerNode Maximum number of elements to put at + a node. + + @param numMeanSplits numMeanSplits = 0 gives a + fully axis aligned BSP-tree, where the balance operation attempts to balance + the tree so that every splitting plane has an equal number of left + and right children (i.e. it is a median split along that axis). + This tends to maximize average performance; all querries will return in the same amount of time. + + You can override this behavior by + setting a number of mean (average) splits. numMeanSplits = MAX_INT + creates a full oct-tree, which tends to optimize peak performance (some areas of the scene will terminate after few recursive splits) at the expense of + peak performance. + */ + void balance(int valuesPerNode = 40, int numMeanSplits = 3) { + if (root == NULL) { + // Tree is empty + return; + } + + Array handleArray; + root->getHandles(handleArray); + + // Delete the old tree + clear(); + + Array temp; + root = makeNode(handleArray, temp, valuesPerNode, numMeanSplits); + temp.fastClear(); + + // Walk the tree, assigning splitBounds. We start with unbounded + // space. + root->assignSplitBounds(AABox::maxFinite()); + +# ifdef _DEBUG + root->verifyNode(Vector3::minFinite(), Vector3::maxFinite()); +# endif + } + +private: + + /** + Returns the elements + + @param parentMask The mask that this node returned from culledBy. + */ + static void getIntersectingMembers( + const Array& plane, + Array& members, + Node* node, + uint32 parentMask) { + + int dummy; + + if (parentMask == 0) { + // None of these planes can cull anything + for (int v = node->valueArray.size() - 1; v >= 0; --v) { + members.append(node->valueArray[v].value); + } + + // Iterate through child nodes + for (int c = 0; c < 2; ++c) { + if (node->child[c]) { + getIntersectingMembers(plane, members, node->child[c], 0); + } + } + } else { + + if (node->valueArray.size() > 0) { + // This is a leaf; check the points + debugAssertM(node->child[0] == NULL, "Malformed Point tree"); + debugAssertM(node->child[1] == NULL, "Malformed Point tree"); + + // Test values at this node against remaining planes + for (int p = 0; p < plane.size(); ++p) { + if ((parentMask >> p) & 1 != 0) { + // Test against this plane + const Plane& curPlane = plane[p]; + for (int v = node->valueArray.size() - 1; v >= 0; --v) { + if (curPlane.halfSpaceContains(node->valueArray[v].position())) { + members.append(node->valueArray[v].value); + } + } + } + } + } else { + + uint32 childMask = 0xFFFFFF; + + // Iterate through child nodes + for (int c = 0; c < 2; ++c) { + if (node->child[c] && + ! node->child[c]->splitBounds.culledBy(plane, dummy, parentMask, childMask)) { + // This node was not culled + getIntersectingMembers(plane, members, node->child[c], childMask); + } + } + } + } + } + +public: + + /** + Returns all members inside the set of planes. + @param members The results are appended to this array. + */ + void getIntersectingMembers(const Array& plane, Array& members) const { + if (root == NULL) { + return; + } + + getIntersectingMembers(plane, members, root, 0xFFFFFF); + } + + /** + Typically used to find all visible + objects inside the view frustum (see also GCamera::getClipPlanes)... i.e. all objects + not culled by frustum. + + Example: +
+        Array  visible;
+        tree.getIntersectingMembers(camera.frustum(), visible);
+        // ... Draw all objects in the visible array.
+      
+ @param members The results are appended to this array. + */ + void getIntersectingMembers(const GCamera::Frustum& frustum, Array& members) const { + Array plane; + + for (int i = 0; i < frustum.faceArray.size(); ++i) { + plane.append(frustum.faceArray[i].plane); + } + + getIntersectingMembers(plane, members); + } + + /** + C++ STL style iterator variable. See beginBoxIntersection(). + The iterator overloads the -> (dereference) operator, so this + acts like a pointer to the current member. + */ + // This iterator turns Node::getIntersectingMembers into a + // coroutine. It first translates that method from recursive to + // stack based, then captures the system state (analogous to a Scheme + // continuation) after each element is appended to the member array, + // and allowing the computation to be restarted. + class BoxIntersectionIterator { + private: + friend class TreeType; + + /** True if this is the "end" iterator instance */ + bool isEnd; + + /** The box that we're testing against. */ + AABox box; + + /** Node that we're currently looking at. Undefined if isEnd + is true. */ + Node* node; + + /** Nodes waiting to be processed */ + // We could use backpointers within the tree and careful + // state management to avoid ever storing the stack-- but + // it is much easier this way and only inefficient if the + // caller uses post increment (which they shouldn't!). + Array stack; + + /** The next index of current->valueArray to return. + Undefined when isEnd is true.*/ + int nextValueArrayIndex; + + BoxIntersectionIterator() : isEnd(true) {} + + BoxIntersectionIterator(const AABox& b, const Node* root) : + isEnd(root == NULL), box(b), + node(const_cast(root)), nextValueArrayIndex(-1) { + + // We intentionally start at the "-1" index of the current + // node so we can use the preincrement operator to move + // ourselves to element 0 instead of repeating all of the + // code from the preincrement method. Note that this might + // cause us to become the "end" instance. + ++(*this); + } + + public: + + inline bool operator!=(const BoxIntersectionIterator& other) const { + return ! (*this == other); + } + + bool operator==(const BoxIntersectionIterator& other) const { + if (isEnd) { + return other.isEnd; + } else if (other.isEnd) { + return false; + } else { + // Two non-end iterators; see if they match. This is kind of + // silly; users shouldn't call == on iterators in general unless + // one of them is the end iterator. + if ((box != other.box) || (node != other.node) || + (nextValueArrayIndex != other.nextValueArrayIndex) || + (stack.length() != other.stack.length())) { + return false; + } + + // See if the stacks are the same + for (int i = 0; i < stack.length(); ++i) { + if (stack[i] != other.stack[i]) { + return false; + } + } + + // We failed to find a difference; they must be the same + return true; + } + } + + /** + Pre increment. + */ + BoxIntersectionIterator& operator++() { + ++nextValueArrayIndex; + + bool foundIntersection = false; + while (! isEnd && ! foundIntersection) { + + // Search for the next node if we've exhausted this one + while ((! isEnd) && (nextValueArrayIndex >= node->valueArray.length())) { + // If we entered this loop, then the iterator has exhausted the elements at + // node (possibly because it just switched to a child node with no members). + // This loop continues until it finds a node with members or reaches + // the end of the whole intersection search. + + // If the right child overlaps the box, push it onto the stack for + // processing. + if ((node->child[1] != NULL) && + (box.high()[node->splitAxis] > node->splitLocation)) { + stack.push(node->child[1]); + } + + // If the left child overlaps the box, push it onto the stack for + // processing. + if ((node->child[0] != NULL) && + (box.low()[node->splitAxis] < node->splitLocation)) { + stack.push(node->child[0]); + } + + if (stack.length() > 0) { + // Go on to the next node (which may be either one of the ones we + // just pushed, or one from farther back the tree). + node = stack.pop(); + nextValueArrayIndex = 0; + } else { + // That was the last node; we're done iterating + isEnd = true; + } + } + + // Search for the next intersection at this node until we run out of children + while (! isEnd && ! foundIntersection && (nextValueArrayIndex < node->valueArray.length())) { + if (box.intersects(node->valueArray[nextValueArrayIndex].bounds)) { + foundIntersection = true; + } else { + ++nextValueArrayIndex; + // If we exhaust this node, we'll loop around the master loop + // to find a new node. + } + } + } + + return *this; + } + + /** + Post increment (much slower than preincrement!). + */ + BoxIntersectionIterator operator++(int) { + BoxIntersectionIterator old = *this; + ++this; + return old; + } + + /** Overloaded dereference operator so the iterator can masquerade as a pointer + to a member */ + const T& operator*() const { + alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); + return node->valueArray[nextValueArrayIndex].value; + } + + /** Overloaded dereference operator so the iterator can masquerade as a pointer + to a member */ + T const * operator->() const { + alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); + return &(stack.last()->valueArray[nextValueArrayIndex].value); + } + + /** Overloaded cast operator so the iterator can masquerade as a pointer + to a member */ + operator T*() const { + alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator"); + return &(stack.last()->valueArray[nextValueArrayIndex].value); + } + }; + + + /** + Iterates through the members that intersect the box + */ + BoxIntersectionIterator beginBoxIntersection(const AABox& box) const { + return BoxIntersectionIterator(box, root); + } + + BoxIntersectionIterator endBoxIntersection() const { + // The "end" iterator instance + return BoxIntersectionIterator(); + } + + /** + Appends all members whose bounds intersect the box. + See also PointKDTree::beginBoxIntersection. + */ + void getIntersectingMembers(const AABox& box, Array& members) const { + if (root == NULL) { + return; + } + root->getIntersectingMembers(box, Sphere(Vector3::zero(), 0), members, false); + } + + + /** + @param members The results are appended to this array. + */ + void getIntersectingMembers(const Sphere& sphere, Array& members) const { + if (root == NULL) { + return; + } + + AABox box; + sphere.getBounds(box); + root->getIntersectingMembers(box, sphere, members); + + } + + + /** + Stores the locations of the splitting planes (the structure but not the content) + so that the tree can be quickly rebuilt from a previous configuration without + calling balance. + */ + void serializeStructure(BinaryOutput& bo) const { + Node::serializeStructure(root, bo); + } + + /** Clears the member table */ + void deserializeStructure(BinaryInput& bi) { + clear(); + root = Node::deserializeStructure(bi); + } + + /** + Returns an array of all members of the set. See also PointKDTree::begin. + */ + void getMembers(Array& members) const { + memberTable.getKeys(members); + } + + + /** + C++ STL style iterator variable. See begin(). + Overloads the -> (dereference) operator, so this acts like a pointer + to the current member. + */ + class Iterator { + private: + friend class TreeType; + + // Note: this is a Table iterator, we are currently defining + // Set iterator + typename MemberTable::Iterator it; + + Iterator(const typename MemberTable::Iterator& it) : it(it) {} + + public: + inline bool operator!=(const Iterator& other) const { + return !(*this == other); + } + + bool operator==(const Iterator& other) const { + return it == other.it; + } + + /** + Pre increment. + */ + Iterator& operator++() { + ++it; + return *this; + } + + /** + Post increment (slower than preincrement). + */ + Iterator operator++(int) { + Iterator old = *this; + ++(*this); + return old; + } + + const T& operator*() const { + return it->key; + } + + T* operator->() const { + return &(it->key); + } + + operator T*() const { + return &(it->key); + } + }; + + + /** + C++ STL style iterator method. Returns the first member. + Use preincrement (++entry) to get to the next element (iteration + order is arbitrary). + Do not modify the set while iterating. + */ + Iterator begin() const { + return Iterator(memberTable.begin()); + } + + + /** + C++ STL style iterator method. Returns one after the last iterator + element. + */ + Iterator end() const { + return Iterator(memberTable.end()); + } +#undef TreeType +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/Pointer.h b/externals/g3dlite/G3D/Pointer.h new file mode 100644 index 00000000000..6e35062a746 --- /dev/null +++ b/externals/g3dlite/G3D/Pointer.h @@ -0,0 +1,292 @@ +/** + @file Pointer.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2007-05-16 + @edited 2009-03-26 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ +#ifndef G3D_Pointer_h +#define G3D_Pointer_h + +#include "G3D/debugAssert.h" +#include "G3D/ReferenceCount.h" + +namespace G3D { + +/** + Acts like a pointer to a value of type ValueType (i.e., + ValueType*), but can operate through accessor methods as well as on + a value in memory. This is useful for implementing scripting + languages and other applications that need to connect existing APIs + by reference. + + Because the accessors require values to be passed by value (instead of by reference) + this is primarily useful for objects whose memory size is small. + +
+   class Foo {
+   public:
+      void setEnabled(bool b);
+      bool getEnabled() const;
+   };
+
+   Foo  f;
+   bool b;
+   
+   Pointer p1(&b);
+   Pointer p2(&f, &Foo::getEnabled, &Foo::setEnabled);
+
+   *p1 = true;
+   *p2 = false;
+   *p2 = *p1; \/\/ Value assignment
+   p2 = p1; \/\/ Pointer aliasing
+
+   \/\/ Or, equivalently:
+   p1.setValue(true);
+   p2.setValue(false);
+
+   p2.setValue(p1.getValue());
+   p2 = p1;
+   
+ + Note: Because of the way that dereference is implemented, you cannot pass *p through a function + that takes varargs (...), e.g., printf("%d", *p) will produce a compile-time error. Instead use + printf("%d",(bool)*p) or printf("%d", p.getValue()). + + */ +template +class Pointer { +private: + + class Interface { + public: + virtual ~Interface() {}; + virtual void set(ValueType b) = 0; + virtual ValueType get() const = 0; + virtual Interface* clone() const = 0; + virtual bool isNull() const = 0; + }; + + class Memory : public Interface { + private: + + ValueType* value; + + public: + + Memory(ValueType* value) : value(value) { + //debugAssert(value != NULL); + } + + virtual void set(ValueType v) { + *value = v; + } + + virtual ValueType get() const { + return *value; + } + + virtual Interface* clone() const { + return new Memory(value); + } + + virtual bool isNull() const { + return value == NULL; + } + }; + + template + class Accessor : public Interface { + private: + + T* object; + GetMethod getMethod; + SetMethod setMethod; + + public: + + Accessor(T* object, + GetMethod getMethod, + SetMethod setMethod) : object(object), getMethod(getMethod), setMethod(setMethod) { + debugAssert(object != NULL); + } + + virtual void set(ValueType v) { + (object->*setMethod)(v); + } + + virtual ValueType get() const { + return (object->*getMethod)(); + } + + virtual Interface* clone() const { + return new Accessor(object, getMethod, setMethod); + } + + virtual bool isNull() const { + return object == NULL; + } + }; + + + template + class RefAccessor : public Interface { + private: + + ReferenceCountedPointer object; + GetMethod getMethod; + SetMethod setMethod; + + public: + + RefAccessor( + const ReferenceCountedPointer& object, + GetMethod getMethod, + SetMethod setMethod) : object(object), getMethod(getMethod), setMethod(setMethod) { + + debugAssert(object != NULL); + } + + virtual void set(ValueType v) { + (object.pointer()->*setMethod)(v); + } + + virtual ValueType get() const { + return (object.pointer()->*getMethod)(); + } + + virtual Interface* clone() const { + return new RefAccessor(object, getMethod, setMethod); + } + + virtual bool isNull() const { + return object.isNull(); + } + }; + + + Interface* m_interface; + +public: + + Pointer() : m_interface(NULL) {}; + + /** Allows implicit cast from real pointer */ + Pointer(ValueType* v) : m_interface(new Memory(v)) {} + + inline bool isNull() const { + return (m_interface == NULL) || m_interface->isNull(); + } + + // Assignment + inline Pointer& operator=(const Pointer& r) { + delete m_interface; + if (r.m_interface != NULL) { + m_interface = r.m_interface->clone(); + } else { + m_interface = NULL; + } + return this[0]; + } + + Pointer(const Pointer& p) : m_interface(NULL) { + this[0] = p; + } + + template + Pointer(const ReferenceCountedPointer& object, + ValueType (Class::*getMethod)() const, + void (Class::*setMethod)(ValueType)) : + m_interface(new RefAccessor(object, getMethod, setMethod)) {} + + template + Pointer(const ReferenceCountedPointer& object, + const ValueType& (Class::*getMethod)() const, + void (Class::*setMethod)(ValueType)) : + m_interface(new RefAccessor(object, getMethod, setMethod)) {} + + template + Pointer(const ReferenceCountedPointer& object, + ValueType (Class::*getMethod)() const, + void (Class::*setMethod)(const ValueType&)) : + m_interface(new RefAccessor(object, getMethod, setMethod)) {} + + template + Pointer(const ReferenceCountedPointer& object, + const ValueType& (Class::*getMethod)() const, + void (Class::*setMethod)(const ValueType&)) : + m_interface(new RefAccessor(object, getMethod, setMethod)) {} + + template + Pointer(Class* object, + const ValueType& (Class::*getMethod)() const, + void (Class::*setMethod)(const ValueType&)) : + m_interface(new Accessor(object, getMethod, setMethod)) {} + + template + Pointer(Class* object, + ValueType (Class::*getMethod)() const, + void (Class::*setMethod)(const ValueType&)) : + m_interface(new Accessor(object, getMethod, setMethod)) {} + + template + Pointer(Class* object, + const ValueType& (Class::*getMethod)() const, + void (Class::*setMethod)(ValueType)) : + m_interface(new Accessor(object, getMethod, setMethod)) {} + + template + Pointer(Class* object, + ValueType (Class::*getMethod)() const, + void (Class::*setMethod)(ValueType)) : + m_interface(new Accessor(object, getMethod, setMethod)) {} + + ~Pointer() { + delete m_interface; + } + + inline const ValueType getValue() const { + debugAssert(m_interface != NULL); + return m_interface->get(); + } + + inline void setValue(const ValueType& v) { + debugAssert(m_interface != NULL); + m_interface->set(v); + } + + class IndirectValue { + private: + + friend class Pointer; + Pointer* pointer; + IndirectValue(Pointer* p) : pointer(p) {} + + public: + + void operator=(const ValueType& v) { + pointer->setValue(v); + } + + operator ValueType() const { + return pointer->getValue(); + } + + }; + + inline IndirectValue operator*() { + return IndirectValue(this); + } + + inline const ValueType operator*() const { + return getValue(); + } +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/PositionTrait.h b/externals/g3dlite/G3D/PositionTrait.h new file mode 100644 index 00000000000..67a4f64138a --- /dev/null +++ b/externals/g3dlite/G3D/PositionTrait.h @@ -0,0 +1,7 @@ +#ifndef G3D_POSITIONTRAIT_H +#define G3D_POSITIONTRAIT_H + +template +struct PositionTrait{}; + +#endif diff --git a/externals/g3dlite/G3D/PrecomputedRandom.h b/externals/g3dlite/G3D/PrecomputedRandom.h new file mode 100644 index 00000000000..411d128c582 --- /dev/null +++ b/externals/g3dlite/G3D/PrecomputedRandom.h @@ -0,0 +1,110 @@ +/** + @file PrecomputedRandom.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2009-03-31 + @edited 2009-03-31 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ +#ifndef G3D_PrecomputedRandom_h +#define G3D_PrecomputedRandom_h + +#include "G3D/platform.h" +#include "G3D/Random.h" + +namespace G3D { + +/** Fast random numbers using a precomputed data table. + + e.g., generates cosHemi about 13x faster than Random. + This is useful for quickly generating seeded random + numbers for reproducibility. G3D::Random takes a long + time to seed; this is instantaneous (providing the + precomputed data is already available.) + + Not threadsafe.*/ +class PrecomputedRandom : public Random { +public: + /** Put the cosHemi and the uniform together so that when + alternating between them we stay in cache. This is also packed + into a good size for SIMD and GPU operations.*/ + class HemiUniformData { + public: + float cosHemiX; + float cosHemiY; + float cosHemiZ; + float uniform; + }; + + class SphereBitsData { + public: + float sphereX; + float sphereY; + float sphereZ; + uint32 bits; + }; + +protected: + + /** Array of 2^n elements. */ + const HemiUniformData* m_hemiUniform; + const SphereBitsData* m_sphereBits; + + /** 2^n - 1; the AND mask for computing a fast modulo */ + int m_modMask; + + int m_index; + + /** If true, free m_hemiUniform and m_sphereBits in destructor */ + bool m_freeData; + +public: + + /* + \param dataSize Must be a power of 2 + \param data Will NOT be deleted by the destructor. + */ + PrecomputedRandom(const HemiUniformData* data1, const SphereBitsData* data2, int dataSize, uint32 seed = 0xF018A4D2); + + /** + \param dataSize Number of random numbers that can be requested before periodicity. Must be a power of 2. + */ + PrecomputedRandom(int dataSize, uint32 seed = 0xF018A4D2); + + ~PrecomputedRandom(); + + /** Each bit is random. Subclasses can choose to override just + this method and the other methods will all work automatically. */ + virtual uint32 bits(); + + // integer is inherited + + /** Uniform random float on the range [min, max] */ + virtual float uniform(float low, float high); + + /** Uniform random float on the range [0, 1] */ + virtual float uniform(); + + // gaussian is inherited + + /** Returns 3D unit vectors distributed according to + a cosine distribution about the z axis. */ + virtual void cosHemi(float& x, float& y, float& z); + + /** Returns 3D unit vectors distributed according to a cosine + power distribution (\f$ \mbox{cos}^k \theta \f$) about + the z-axis. */ + virtual void cosPowHemi(const float k, float& x, float& y, float& z); + + // hemi is inherited + + /** Returns 3D unit vectors uniformly distributed on the sphere */ + virtual void sphere(float& x, float& y, float& z); +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/Quat.h b/externals/g3dlite/G3D/Quat.h new file mode 100644 index 00000000000..9ef3d57b301 --- /dev/null +++ b/externals/g3dlite/G3D/Quat.h @@ -0,0 +1,725 @@ +/** + @file Quat.h + + Quaternion + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2002-01-23 + @edited 2009-05-10 + */ + +#ifndef G3D_Quat_h +#define G3D_Quat_h + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Vector3.h" +#include "G3D/Matrix3.h" +#include + +namespace G3D { + +/** + Unit quaternions are used in computer graphics to represent + rotation about an axis. Any 3x3 rotation matrix can + be stored as a quaternion. + + A quaternion represents the sum of a real scalar and + an imaginary vector: ix + jy + kz + w. A unit quaternion + representing a rotation by A about axis v has the form + [sin(A/2)*v, cos(A/2)]. For a unit quaternion, q.conj() == q.inverse() + is a rotation by -A about v. -q is the same rotation as q + (negate both the axis and angle). + + A non-unit quaterion q represents the same rotation as + q.unitize() (Dam98 pg 28). + + Although quaternion-vector operations (eg. Quat + Vector3) are + well defined, they are not supported by this class because + they typically are bugs when they appear in code. + + Do not subclass. + + BETA API -- subject to change + @cite Erik B. Dam, Martin Koch, Martin Lillholm, Quaternions, Interpolation and Animation. Technical Report DIKU-TR-98/5, Department of Computer Science, University of Copenhagen, Denmark. 1998. + */ +class Quat { +private: + // Hidden operators + bool operator<(const Quat&) const; + bool operator>(const Quat&) const; + bool operator<=(const Quat&) const; + bool operator>=(const Quat&) const; + +public: + + /** + q = [sin(angle / 2) * axis, cos(angle / 2)] + + In Watt & Watt's notation, s = w, v = (x, y, z) + In the Real-Time Rendering notation, u = (x, y, z), w = w + */ + float x, y, z, w; + + /** + Initializes to a zero degree rotation. + */ + inline Quat() : x(0), y(0), z(0), w(1) {} + + Quat( + const Matrix3& rot); + + inline Quat(float _x, float _y, float _z, float _w) : + x(_x), y(_y), z(_z), w(_w) {} + + /** Defaults to a pure vector quaternion */ + inline Quat(const Vector3& v, float _w = 0) : x(v.x), y(v.y), z(v.z), w(_w) { + } + + /** + The real part of the quaternion. + */ + inline const float& real() const { + return w; + } + + inline float& real() { + return w; + } + + /** Note: two quats can represent the Quat::sameRotation and not be equal. */ + bool fuzzyEq(const Quat& q) { + return G3D::fuzzyEq(x, q.x) && G3D::fuzzyEq(y, q.y) && G3D::fuzzyEq(z, q.z) && G3D::fuzzyEq(w, q.w); + } + + /** True if these quaternions represent the same rotation (note that every rotation is + represented by two values; q and -q). + */ + bool sameRotation(const Quat& q) { + return fuzzyEq(q) || fuzzyEq(-q); + } + + inline Quat operator-() const { + return Quat(-x, -y, -z, -w); + } + + /** + Returns the imaginary part (x, y, z) + */ + inline const Vector3& imag() const { + return *(reinterpret_cast(this)); + } + + inline Vector3& imag() { + return *(reinterpret_cast(this)); + } + + /** q = [sin(angle/2)*axis, cos(angle/2)] */ + static Quat fromAxisAngleRotation( + const Vector3& axis, + float angle); + + /** Returns the axis and angle of rotation represented + by this quaternion (i.e. q = [sin(angle/2)*axis, cos(angle/2)]) */ + void toAxisAngleRotation( + Vector3& axis, + double& angle) const; + + void toAxisAngleRotation( + Vector3& axis, + float& angle) const { + double d; + toAxisAngleRotation(axis, d); + angle = (float)d; + } + + Matrix3 toRotationMatrix() const; + + void toRotationMatrix( + Matrix3& rot) const; + + /** + Spherical linear interpolation: linear interpolation along the + shortest (3D) great-circle route between two quaternions. + + Note: Correct rotations are expected between 0 and PI in the right order. + + @cite Based on Game Physics -- David Eberly pg 538-540 + @param threshold Critical angle between between rotations at which + the algorithm switches to normalized lerp, which is more + numerically stable in those situations. 0.0 will always slerp. + */ + Quat slerp( + const Quat& other, + float alpha, + float threshold = 0.05f) const; + + /** Normalized linear interpolation of quaternion components. */ + Quat nlerp(const Quat& other, float alpha) const; + + /** + Negates the imaginary part. + */ + inline Quat conj() const { + return Quat(-x, -y, -z, w); + } + + inline float sum() const { + return x + y + z + w; + } + + inline float average() const { + return sum() / 4.0f; + } + + inline Quat operator*(float s) const { + return Quat(x * s, y * s, z * s, w * s); + } + + inline Quat& operator*=(float s) { + x *= s; + y *= s; + z *= s; + w *= s; + return *this; + } + + /** @cite Based on Watt & Watt, page 360 */ + friend Quat operator* (float s, const Quat& q); + + inline Quat operator/(float s) const { + return Quat(x / s, y / s, z / s, w / s); + } + + inline float dot(const Quat& other) const { + return (x * other.x) + (y * other.y) + (z * other.z) + (w * other.w); + } + + /** Note that q-1 = q.conj() for a unit quaternion. + @cite Dam99 page 13 */ + inline Quat inverse() const { + return conj() / dot(*this); + } + + Quat operator-(const Quat& other) const; + + Quat operator+(const Quat& other) const; + + /** + Quaternion multiplication (composition of rotations). + Note that this does not commute. + */ + Quat operator*(const Quat& other) const; + + /* (*this) * other.inverse() */ + Quat operator/(const Quat& other) const { + return (*this) * other.inverse(); + } + + + /** Is the magnitude nearly 1.0? */ + inline bool isUnit(float tolerance = 1e-5) const { + return abs(dot(*this) - 1.0f) < tolerance; + } + + + inline float magnitude() const { + return sqrtf(dot(*this)); + } + + inline Quat log() const { + if ((x == 0) && (y == 0) && (z == 0)) { + if (w > 0) { + return Quat(0, 0, 0, ::logf(w)); + } else if (w < 0) { + // Log of a negative number. Multivalued, any number of the form + // (PI * v, ln(-q.w)) + return Quat((float)pi(), 0, 0, ::logf(-w)); + } else { + // log of zero! + return Quat((float)nan(), (float)nan(), (float)nan(), (float)nan()); + } + } else { + // Partly imaginary. + float imagLen = sqrtf(x * x + y * y + z * z); + float len = sqrtf(imagLen * imagLen + w * w); + float theta = atan2f(imagLen, (float)w); + float t = theta / imagLen; + return Quat(t * x, t * y, t * z, ::logf(len)); + } + } + /** log q = [Av, 0] where q = [sin(A) * v, cos(A)]. + Only for unit quaternions + debugAssertM(isUnit(), "Log only defined for unit quaternions"); + // Solve for A in q = [sin(A)*v, cos(A)] + Vector3 u(x, y, z); + double len = u.magnitude(); + + if (len == 0.0) { + return + } + double A = atan2((double)w, len); + Vector3 v = u / len; + + return Quat(v * A, 0); + } + */ + + /** exp q = [sin(A) * v, cos(A)] where q = [Av, 0]. + Only defined for pure-vector quaternions */ + inline Quat exp() const { + debugAssertM(w == 0, "exp only defined for vector quaternions"); + Vector3 u(x, y, z); + float A = u.magnitude(); + Vector3 v = u / A; + return Quat(sinf(A) * v, cosf(A)); + } + + + /** + Raise this quaternion to a power. For a rotation, this is + the effect of rotating x times as much as the original + quaterion. + + Note that q.pow(a).pow(b) == q.pow(a + b) + @cite Dam98 pg 21 + */ + inline Quat pow(float x) const { + return (log() * x).exp(); + } + + inline void unitize() { + float mag2 = dot(*this); + if (! G3D::fuzzyEq(mag2, 1.0f)) { + *this *= rsq(mag2); + } + } + + /** + Returns a unit quaterion obtained by dividing through by + the magnitude. + */ + inline Quat toUnit() const { + Quat x = *this; + x.unitize(); + return x; + } + + /** + The linear algebra 2-norm, sqrt(q dot q). This matches + the value used in Dam's 1998 tech report but differs from the + n(q) value used in Eberly's 1999 paper, which is the square of the + norm. + */ + inline float norm() const { + return magnitude(); + } + + // access quaternion as q[0] = q.x, q[1] = q.y, q[2] = q.z, q[3] = q.w + // + // WARNING. These member functions rely on + // (1) Quat not having virtual functions + // (2) the data packed in a 4*sizeof(float) memory block + const float& operator[] (int i) const; + float& operator[] (int i); + + /** Generate uniform random unit quaternion (i.e. random "direction") + @cite From "Uniform Random Rotations", Ken Shoemake, Graphics Gems III. + */ + static Quat unitRandom(); + + void deserialize(class BinaryInput& b); + void serialize(class BinaryOutput& b) const; + + // 2-char swizzles + + Vector2 xx() const; + Vector2 yx() const; + Vector2 zx() const; + Vector2 wx() const; + Vector2 xy() const; + Vector2 yy() const; + Vector2 zy() const; + Vector2 wy() const; + Vector2 xz() const; + Vector2 yz() const; + Vector2 zz() const; + Vector2 wz() const; + Vector2 xw() const; + Vector2 yw() const; + Vector2 zw() const; + Vector2 ww() const; + + // 3-char swizzles + + Vector3 xxx() const; + Vector3 yxx() const; + Vector3 zxx() const; + Vector3 wxx() const; + Vector3 xyx() const; + Vector3 yyx() const; + Vector3 zyx() const; + Vector3 wyx() const; + Vector3 xzx() const; + Vector3 yzx() const; + Vector3 zzx() const; + Vector3 wzx() const; + Vector3 xwx() const; + Vector3 ywx() const; + Vector3 zwx() const; + Vector3 wwx() const; + Vector3 xxy() const; + Vector3 yxy() const; + Vector3 zxy() const; + Vector3 wxy() const; + Vector3 xyy() const; + Vector3 yyy() const; + Vector3 zyy() const; + Vector3 wyy() const; + Vector3 xzy() const; + Vector3 yzy() const; + Vector3 zzy() const; + Vector3 wzy() const; + Vector3 xwy() const; + Vector3 ywy() const; + Vector3 zwy() const; + Vector3 wwy() const; + Vector3 xxz() const; + Vector3 yxz() const; + Vector3 zxz() const; + Vector3 wxz() const; + Vector3 xyz() const; + Vector3 yyz() const; + Vector3 zyz() const; + Vector3 wyz() const; + Vector3 xzz() const; + Vector3 yzz() const; + Vector3 zzz() const; + Vector3 wzz() const; + Vector3 xwz() const; + Vector3 ywz() const; + Vector3 zwz() const; + Vector3 wwz() const; + Vector3 xxw() const; + Vector3 yxw() const; + Vector3 zxw() const; + Vector3 wxw() const; + Vector3 xyw() const; + Vector3 yyw() const; + Vector3 zyw() const; + Vector3 wyw() const; + Vector3 xzw() const; + Vector3 yzw() const; + Vector3 zzw() const; + Vector3 wzw() const; + Vector3 xww() const; + Vector3 yww() const; + Vector3 zww() const; + Vector3 www() const; + + // 4-char swizzles + + Vector4 xxxx() const; + Vector4 yxxx() const; + Vector4 zxxx() const; + Vector4 wxxx() const; + Vector4 xyxx() const; + Vector4 yyxx() const; + Vector4 zyxx() const; + Vector4 wyxx() const; + Vector4 xzxx() const; + Vector4 yzxx() const; + Vector4 zzxx() const; + Vector4 wzxx() const; + Vector4 xwxx() const; + Vector4 ywxx() const; + Vector4 zwxx() const; + Vector4 wwxx() const; + Vector4 xxyx() const; + Vector4 yxyx() const; + Vector4 zxyx() const; + Vector4 wxyx() const; + Vector4 xyyx() const; + Vector4 yyyx() const; + Vector4 zyyx() const; + Vector4 wyyx() const; + Vector4 xzyx() const; + Vector4 yzyx() const; + Vector4 zzyx() const; + Vector4 wzyx() const; + Vector4 xwyx() const; + Vector4 ywyx() const; + Vector4 zwyx() const; + Vector4 wwyx() const; + Vector4 xxzx() const; + Vector4 yxzx() const; + Vector4 zxzx() const; + Vector4 wxzx() const; + Vector4 xyzx() const; + Vector4 yyzx() const; + Vector4 zyzx() const; + Vector4 wyzx() const; + Vector4 xzzx() const; + Vector4 yzzx() const; + Vector4 zzzx() const; + Vector4 wzzx() const; + Vector4 xwzx() const; + Vector4 ywzx() const; + Vector4 zwzx() const; + Vector4 wwzx() const; + Vector4 xxwx() const; + Vector4 yxwx() const; + Vector4 zxwx() const; + Vector4 wxwx() const; + Vector4 xywx() const; + Vector4 yywx() const; + Vector4 zywx() const; + Vector4 wywx() const; + Vector4 xzwx() const; + Vector4 yzwx() const; + Vector4 zzwx() const; + Vector4 wzwx() const; + Vector4 xwwx() const; + Vector4 ywwx() const; + Vector4 zwwx() const; + Vector4 wwwx() const; + Vector4 xxxy() const; + Vector4 yxxy() const; + Vector4 zxxy() const; + Vector4 wxxy() const; + Vector4 xyxy() const; + Vector4 yyxy() const; + Vector4 zyxy() const; + Vector4 wyxy() const; + Vector4 xzxy() const; + Vector4 yzxy() const; + Vector4 zzxy() const; + Vector4 wzxy() const; + Vector4 xwxy() const; + Vector4 ywxy() const; + Vector4 zwxy() const; + Vector4 wwxy() const; + Vector4 xxyy() const; + Vector4 yxyy() const; + Vector4 zxyy() const; + Vector4 wxyy() const; + Vector4 xyyy() const; + Vector4 yyyy() const; + Vector4 zyyy() const; + Vector4 wyyy() const; + Vector4 xzyy() const; + Vector4 yzyy() const; + Vector4 zzyy() const; + Vector4 wzyy() const; + Vector4 xwyy() const; + Vector4 ywyy() const; + Vector4 zwyy() const; + Vector4 wwyy() const; + Vector4 xxzy() const; + Vector4 yxzy() const; + Vector4 zxzy() const; + Vector4 wxzy() const; + Vector4 xyzy() const; + Vector4 yyzy() const; + Vector4 zyzy() const; + Vector4 wyzy() const; + Vector4 xzzy() const; + Vector4 yzzy() const; + Vector4 zzzy() const; + Vector4 wzzy() const; + Vector4 xwzy() const; + Vector4 ywzy() const; + Vector4 zwzy() const; + Vector4 wwzy() const; + Vector4 xxwy() const; + Vector4 yxwy() const; + Vector4 zxwy() const; + Vector4 wxwy() const; + Vector4 xywy() const; + Vector4 yywy() const; + Vector4 zywy() const; + Vector4 wywy() const; + Vector4 xzwy() const; + Vector4 yzwy() const; + Vector4 zzwy() const; + Vector4 wzwy() const; + Vector4 xwwy() const; + Vector4 ywwy() const; + Vector4 zwwy() const; + Vector4 wwwy() const; + Vector4 xxxz() const; + Vector4 yxxz() const; + Vector4 zxxz() const; + Vector4 wxxz() const; + Vector4 xyxz() const; + Vector4 yyxz() const; + Vector4 zyxz() const; + Vector4 wyxz() const; + Vector4 xzxz() const; + Vector4 yzxz() const; + Vector4 zzxz() const; + Vector4 wzxz() const; + Vector4 xwxz() const; + Vector4 ywxz() const; + Vector4 zwxz() const; + Vector4 wwxz() const; + Vector4 xxyz() const; + Vector4 yxyz() const; + Vector4 zxyz() const; + Vector4 wxyz() const; + Vector4 xyyz() const; + Vector4 yyyz() const; + Vector4 zyyz() const; + Vector4 wyyz() const; + Vector4 xzyz() const; + Vector4 yzyz() const; + Vector4 zzyz() const; + Vector4 wzyz() const; + Vector4 xwyz() const; + Vector4 ywyz() const; + Vector4 zwyz() const; + Vector4 wwyz() const; + Vector4 xxzz() const; + Vector4 yxzz() const; + Vector4 zxzz() const; + Vector4 wxzz() const; + Vector4 xyzz() const; + Vector4 yyzz() const; + Vector4 zyzz() const; + Vector4 wyzz() const; + Vector4 xzzz() const; + Vector4 yzzz() const; + Vector4 zzzz() const; + Vector4 wzzz() const; + Vector4 xwzz() const; + Vector4 ywzz() const; + Vector4 zwzz() const; + Vector4 wwzz() const; + Vector4 xxwz() const; + Vector4 yxwz() const; + Vector4 zxwz() const; + Vector4 wxwz() const; + Vector4 xywz() const; + Vector4 yywz() const; + Vector4 zywz() const; + Vector4 wywz() const; + Vector4 xzwz() const; + Vector4 yzwz() const; + Vector4 zzwz() const; + Vector4 wzwz() const; + Vector4 xwwz() const; + Vector4 ywwz() const; + Vector4 zwwz() const; + Vector4 wwwz() const; + Vector4 xxxw() const; + Vector4 yxxw() const; + Vector4 zxxw() const; + Vector4 wxxw() const; + Vector4 xyxw() const; + Vector4 yyxw() const; + Vector4 zyxw() const; + Vector4 wyxw() const; + Vector4 xzxw() const; + Vector4 yzxw() const; + Vector4 zzxw() const; + Vector4 wzxw() const; + Vector4 xwxw() const; + Vector4 ywxw() const; + Vector4 zwxw() const; + Vector4 wwxw() const; + Vector4 xxyw() const; + Vector4 yxyw() const; + Vector4 zxyw() const; + Vector4 wxyw() const; + Vector4 xyyw() const; + Vector4 yyyw() const; + Vector4 zyyw() const; + Vector4 wyyw() const; + Vector4 xzyw() const; + Vector4 yzyw() const; + Vector4 zzyw() const; + Vector4 wzyw() const; + Vector4 xwyw() const; + Vector4 ywyw() const; + Vector4 zwyw() const; + Vector4 wwyw() const; + Vector4 xxzw() const; + Vector4 yxzw() const; + Vector4 zxzw() const; + Vector4 wxzw() const; + Vector4 xyzw() const; + Vector4 yyzw() const; + Vector4 zyzw() const; + Vector4 wyzw() const; + Vector4 xzzw() const; + Vector4 yzzw() const; + Vector4 zzzw() const; + Vector4 wzzw() const; + Vector4 xwzw() const; + Vector4 ywzw() const; + Vector4 zwzw() const; + Vector4 wwzw() const; + Vector4 xxww() const; + Vector4 yxww() const; + Vector4 zxww() const; + Vector4 wxww() const; + Vector4 xyww() const; + Vector4 yyww() const; + Vector4 zyww() const; + Vector4 wyww() const; + Vector4 xzww() const; + Vector4 yzww() const; + Vector4 zzww() const; + Vector4 wzww() const; + Vector4 xwww() const; + Vector4 ywww() const; + Vector4 zwww() const; + Vector4 wwww() const; +}; + +inline Quat exp(const Quat& q) { + return q.exp(); +} + +inline Quat log(const Quat& q) { + return q.log(); +} + +inline G3D::Quat operator*(double s, const G3D::Quat& q) { + return q * (float)s; +} + +inline G3D::Quat operator*(float s, const G3D::Quat& q) { + return q * s; +} + +inline float& Quat::operator[] (int i) { + debugAssert(i >= 0); + debugAssert(i < 4); + return ((float*)this)[i]; +} + +inline const float& Quat::operator[] (int i) const { + debugAssert(i >= 0); + debugAssert(i < 4); + return ((float*)this)[i]; +} + +inline Quat Quat::operator-(const Quat& other) const { + return Quat(x - other.x, y - other.y, z - other.z, w - other.w); +} + +inline Quat Quat::operator+(const Quat& other) const { + return Quat(x + other.x, y + other.y, z + other.z, w + other.w); +} + +} // Namespace G3D + +// Outside the namespace to avoid overloading confusion for C++ +inline G3D::Quat pow(const G3D::Quat& q, double x) { + return q.pow((float)x); +} + + +#endif diff --git a/externals/g3dlite/G3D/Quat.inl b/externals/g3dlite/G3D/Quat.inl new file mode 100644 index 00000000000..9e4c861d93b --- /dev/null +++ b/externals/g3dlite/G3D/Quat.inl @@ -0,0 +1,36 @@ +/** + Quat.inl + + @cite Quaternion implementation based on Watt & Watt page 363. + Thanks to Max McGuire for slerp optimizations. + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2002-01-23 + @edited 2004-03-04 + */ + +namespace G3D { + +inline float& Quat::operator[] (int i) { + debugAssert(i >= 0); + debugAssert(i < 4); + return ((float*)this)[i]; +} + +inline const float& Quat::operator[] (int i) const { + debugAssert(i >= 0); + debugAssert(i < 4); + return ((float*)this)[i]; +} + +inline Quat Quat::operator-(const Quat& other) const { + return Quat(x - other.x, y - other.y, z - other.z, w - other.w); +} + +inline Quat Quat::operator+(const Quat& other) const { + return Quat(x + other.x, y + other.y, z + other.z, w + other.w); +} + +} + diff --git a/externals/g3dlite/G3D/Queue.h b/externals/g3dlite/G3D/Queue.h new file mode 100644 index 00000000000..36573265d1a --- /dev/null +++ b/externals/g3dlite/G3D/Queue.h @@ -0,0 +1,364 @@ +/** + @file Queue.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2002-07-09 + @edited 2008-12-20 + */ + +#ifndef G3D_QUEUE_H +#define G3D_QUEUE_H + +#include "G3D/platform.h" +#include "G3D/System.h" +#include "G3D/debug.h" + +namespace G3D { + +/** + Locate the indices of the break between of the two + sections of the circular queue. These are used to + construct two for loops that iterate over the whole + sequence without using the modulo operator. + + [0 ... secondEnd) [head .... firstEnd) + */ +#define FIND_ENDS \ + int firstEnd = head + num;\ + int secondEnd = 0;\ + if (firstEnd > numAllocated) {\ + secondEnd = firstEnd - numAllocated;\ + firstEnd = numAllocated;\ + } + + +/** + Dynamic queue that uses a circular buffer for performance. + + Faster than std::deque for objects with constructors. + */ +template +class Queue { +private: + // + // |<---- num ---->| + // [ | | | | | | | | | | | | | ] + // ^ + // | + // head + // + // + + /** + Only num elements are initialized. + */ + T* data; + + /** + Index of the next element to be dequeue-d in data. + */ + int head; + + /** + Number of elements (including head) that are visible and initialized. + */ + int num; + + /** + Size of data array in elements. + */ + int numAllocated; + + /** If a clear was needed, assumes it already occured */ + void _copy(const Queue& other) { + debugAssert(data == NULL); + data = (T*)System::malloc(sizeof(T) * other.numAllocated); + debugAssert(data); + head = other.head; + num = other.num; + numAllocated = other.numAllocated; + + FIND_ENDS; + + for (int i = head; i < firstEnd; ++i) { + new (data + i)T(other.data[i]); + } + + for (int i = 0; i < secondEnd; ++i) { + new (data + i)T(other.data[i]); + } + } + + + /** + Computes a data array index from a queue position. The queue position + may be negative. + */ + inline int index(int i) const { + return (head + i + numAllocated) % numAllocated; + } + + /** + Allocates newSize elements and repacks the array. + */ + void repackAndRealloc(int newSize) { + // TODO: shrink queue + T* old = data; + data = (T*)System::malloc(newSize * sizeof(T)); + debugAssert(data != NULL); + + FIND_ENDS; + + int j = 0; + for (int i = head; i < firstEnd; ++i, ++j) { + new (data + j)T(old[i]); + (old + i)->~T(); + } + + for (int i = 0; i < secondEnd; ++i, ++j) { + new (data + j)T(old[i]); + (old + i)->~T(); + } + + head = 0; + System::free(old); + numAllocated = newSize; + } + + /** + Ensure that there is at least one element between + the tail and head, wrapping around in the circular + buffer. + */ + inline void reserveSpace() { + if (num == numAllocated) { + repackAndRealloc(numAllocated * 3 + 20); + } + } + +public: + + Queue() : + data(NULL), + head(0), + num(0), + numAllocated(0) { + } + + + /** + Copy constructor + */ + Queue(const Queue& other) : data(NULL) { + _copy(other); + } + + + /** + Destructor does not delete() the objects if T is a pointer type + (e.g. T = int*) instead, it deletes the pointers themselves and + leaves the objects. Call deleteAll if you want to dealocate + the objects referenced. + */ + virtual ~Queue() { + clear(); + } + + /** + Insert a new element into the front of the queue + (a traditional queue only uses pushBack). + */ + inline void pushFront(const T& e) { + reserveSpace(); + + // Get the index of head-1 + int i = index(-1); + + // Call the constructor on the newly exposed element. + new (data + i)T(e); + + // Reassign the head to point to this index + head = i; + ++num; + } + + /** + Insert a new element at the end of the queue. + */ + inline void pushBack(const T& e) { + reserveSpace(); + + // Get the index of 1+tail + int i = index(num); + + // Initialize that element + new (data + i)T(e); + ++num; + } + + /** + pushBack + */ + inline void enqueue(const T& e) { + pushBack(e); + } + + + /** + Remove the last element from the queue. The queue will never + shrink in size. (A typical queue only uses popFront). + */ + inline T popBack() { + int tail = index(num - 1); + T result(data[tail]); + + // Call the destructor + (data + tail)->~T(); + --num; + + return result; + } + + /** + Remove the next element from the head of the queue. The queue will never + shrink in size. */ + inline T popFront() { + T result(data[head]); + // Call the destructor + (data + head)->~T(); + head = (head + 1) % numAllocated; + --num; + return result; + } + + + /** + popFront + */ + inline T dequeue() { + return popFront(); + } + + /** + Removes all elements (invoking their destructors). + + @param freeStorage If false, the underlying array is not deallocated + (allowing fast push in the future), however, the size of the Queue + is reported as zero. + + */ + void clear(bool freeStorage = true) { + + FIND_ENDS; + + // Invoke the destructors on the elements + int i; + for (i = head; i < firstEnd; ++i) { + (data + i)->~T(); + } + + for (i = 0; i < secondEnd; ++i) { + (data + i)->~T(); + } + + num = 0; + head = 0; + if (freeStorage) { + numAllocated = 0; + System::free(data); + data = NULL; + } + } + + /** Clear without freeing the underlying array. */ + void fastClear() { + clear(false); + } + + /** + Assignment operator. + */ + Queue& operator=(const Queue& other) { + clear(); + _copy(other); + return *this; + } + + /** + Number of elements in the queue. + */ + inline int size() const { + return num; + } + + /** + Number of elements in the queue. + */ + inline int length() const { + return size(); + } + + /** + Performs bounds checks in debug mode + */ + inline T& operator[](int n) { + debugAssert((n >= 0) && (n < num)); + return data[index(n)]; + } + + /** + Performs bounds checks in debug mode + */ + inline const T& operator[](int n) const { + debugAssert((n >= 0) && (n < num)); + return data[index(n)]; + } + + + /** Returns the back element */ + inline const T& last() const { + return (*this)[size() - 1]; + } + + inline T& last() { + return (*this)[size() - 1]; + } + + /** + Returns true if the given element is in the queue. + */ + bool contains(const T& e) const { + for (int i = 0; i < size(); ++i) { + if ((*this)[i] == e) { + return true; + } + } + + return false; + } + + /** + Calls delete on all objects[0...size-1] + and sets the queue size to zero. + */ + void deleteAll() { + FIND_ENDS; + + int i; + for (i = 0; i < secondEnd; ++i) { + delete data[i]; + } + + for (i = head; i < firstEnd; ++i) { + delete data[i]; + } + clear(); + } +}; + +#undef FIND_ENDS + +}; // namespace + +#endif diff --git a/externals/g3dlite/G3D/Random.h b/externals/g3dlite/G3D/Random.h new file mode 100644 index 00000000000..54491d06f1b --- /dev/null +++ b/externals/g3dlite/G3D/Random.h @@ -0,0 +1,139 @@ +/** + @file Random.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2009-01-02 + @edited 2009-03-20 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ +#ifndef G3D_Random_h +#define G3D_Random_h + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/GMutex.h" + +namespace G3D { + +/** Random number generator. + + Threadsafe. + + Useful for generating consistent random numbers across platforms + and when multiple threads are involved. + + Uses the Fast Mersenne Twister (FMT-19937) algorithm. + + On average, uniform() runs about 2x-3x faster than rand(). + + @cite http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html + + On OS X, Random is about 10x faster than drand48() (which is + threadsafe) and 4x faster than rand() (which is not threadsafe). + */ +class Random { +protected: + + /** Constants (important for the algorithm; do not modify) */ + enum { + N = 624, + M = 397, + R = 31, + U = 11, + S = 7, + T = 15, + L = 18, + A = 0x9908B0DF, + B = 0x9D2C5680, + C = 0xEFC60000}; + + /** + Prevents multiple overlapping calls to generate(). + */ + Spinlock lock; + + /** State vector (these are the next N values that will be returned) */ + uint32* state; + + /** Index into state */ + int index; + + bool m_threadsafe; + + /** Generate the next N ints, and store them for readback later. + Called from bits() */ + virtual void generate(); + + /** For subclasses. The void* parameter is just to distinguish this from the + public constructor.*/ + Random(void*); + +public: + + /** \param threadsafe Set to false if you know that this random + will only be used on a single thread. This eliminates the + lock and improves performance on some platforms. + */ + Random(uint32 seed = 0xF018A4D2, bool threadsafe = true); + + virtual ~Random(); + + /** Each bit is random. Subclasses can choose to override just + this method and the other methods will all work automatically. */ + virtual uint32 bits(); + + /** Uniform random integer on the range [min, max] */ + virtual int integer(int min, int max); + + /** Uniform random float on the range [min, max] */ + virtual inline float uniform(float low, float high) { + // We could compute the ratio in double precision here for + // about 1.5x slower performance and slightly better + // precision. + return low + (high - low) * ((float)bits() / (float)0xFFFFFFFFUL); + } + + /** Uniform random float on the range [0, 1] */ + virtual inline float uniform() { + // We could compute the ratio in double precision here for + // about 1.5x slower performance and slightly better + // precision. + const float norm = 1.0f / (float)0xFFFFFFFFUL; + return (float)bits() * norm; + } + + /** Normally distributed reals. */ + virtual float gaussian(float mean, float stdev); + + /** Returns 3D unit vectors distributed according to + a cosine distribution about the z-axis. */ + virtual void cosHemi(float& x, float& y, float& z); + + /** Returns 3D unit vectors distributed according to a cosine + power distribution (\f$ \cos^k \theta \f$) about + the z-axis. */ + virtual void cosPowHemi(const float k, float& x, float& y, float& z); + + /** Returns 3D unit vectors uniformly distributed on the + hemisphere about the z-axis. */ + virtual void hemi(float& x, float& y, float& z); + + /** Returns 3D unit vectors uniformly distributed on the sphere */ + virtual void sphere(float& x, float& y, float& z); + + /** + A shared instance for when the performance and features but not + consistency of the class are desired. It is slightly (10%) + faster to use a distinct instance than to use the common one. + + Threadsafe. + */ + static Random& common(); +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/Ray.h b/externals/g3dlite/G3D/Ray.h new file mode 100644 index 00000000000..80df5828aff --- /dev/null +++ b/externals/g3dlite/G3D/Ray.h @@ -0,0 +1,371 @@ +/** + @file Ray.h + + Ray class + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2002-07-12 + @edited 2009-06-29 + */ + +#ifndef G3D_Ray_h +#define G3D_Ray_h + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Triangle.h" + +namespace G3D { + +/** + A 3D Ray. + */ +class Ray { +private: + friend class Intersect; + + Vector3 m_origin; + + /** Unit length */ + Vector3 m_direction; + + /** 1.0 / direction */ + Vector3 m_invDirection; + + + // The following are for the "ray slope" optimization from + // "Fast Ray / Axis-Aligned Bounding Box Overlap Tests using Ray Slopes" + // by Martin Eisemann, Thorsten Grosch, Stefan Müller and Marcus Magnor + // Computer Graphics Lab, TU Braunschweig, Germany and + // University of Koblenz-Landau, Germany*/ + enum Classification {MMM, MMP, MPM, MPP, PMM, PMP, PPM, PPP, POO, MOO, OPO, OMO, OOP, OOM, OMM, OMP, OPM, OPP, MOM, MOP, POM, POP, MMO, MPO, PMO, PPO}; Classification classification; + // ray slope + float ibyj, jbyi, kbyj, jbyk, ibyk, kbyi; + // Precomputed components + float c_xy, c_xz, c_yx, c_yz, c_zx, c_zy; + +public: + + void set(const Vector3& origin, const Vector3& direction); + + inline const Vector3& origin() const { + return m_origin; + } + + /** Unit direction vector. */ + inline const Vector3& direction() const { + return m_direction; + } + + /** Component-wise inverse of direction vector. May have inf() components */ + inline const Vector3& invDirection() const { + return m_invDirection; + } + + inline Ray() { + set(Vector3::zero(), Vector3::unitX()); + } + + inline Ray(const Vector3& origin, const Vector3& direction) { + set(origin, direction); + } + + Ray(class BinaryInput& b); + + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + + /** + Creates a Ray from a origin and a (nonzero) unit direction. + */ + static Ray fromOriginAndDirection(const Vector3& point, const Vector3& direction) { + return Ray(point, direction); + } + + /** Advances the origin along the direction by @a distance */ + inline Ray bump(float distance) const { + return Ray(m_origin + m_direction * distance, m_direction); + } + + /** Advances the origin along the @a bumpDirection by @a distance and returns the new ray*/ + inline Ray bump(float distance, const Vector3& bumpDirection) const { + return Ray(m_origin + bumpDirection * distance, m_direction); + } + + /** + Returns the closest point on the Ray to point. + */ + Vector3 closestPoint(const Vector3& point) const { + float t = m_direction.dot(point - m_origin); + if (t < 0) { + return m_origin; + } else { + return m_origin + m_direction * t; + } + } + + /** + Returns the closest distance between point and the Ray + */ + float distance(const Vector3& point) const { + return (closestPoint(point) - point).magnitude(); + } + + /** + Returns the point where the Ray and plane intersect. If there + is no intersection, returns a point at infinity. + + Planes are considered one-sided, so the ray will not intersect + a plane where the normal faces in the traveling direction. + */ + Vector3 intersection(const class Plane& plane) const; + + /** + Returns the distance until intersection with the sphere or the (solid) ball bounded by the sphere. + Will be 0 if inside the sphere, inf if there is no intersection. + + The ray direction is not normalized. If the ray direction + has unit length, the distance from the origin to intersection + is equal to the time. If the direction does not have unit length, + the distance = time * direction.length(). + + See also the G3D::CollisionDetection "movingPoint" methods, + which give more information about the intersection. + + \param solid If true, rays inside the sphere immediately intersect (good for collision detection). If false, they hit the opposite side of the sphere (good for ray tracing). + */ + float intersectionTime(const class Sphere& sphere, bool solid = false) const; + + float intersectionTime(const class Plane& plane) const; + + float intersectionTime(const class Box& box) const; + + float intersectionTime(const class AABox& box) const; + + /** + The three extra arguments are the weights of vertices 0, 1, and 2 + at the intersection point; they are useful for texture mapping + and interpolated normals. + */ + float intersectionTime( + const Vector3& v0, const Vector3& v1, const Vector3& v2, + const Vector3& edge01, const Vector3& edge02, + double& w0, double& w1, double& w2) const; + + /** + Ray-triangle intersection for a 1-sided triangle. Fastest version. + @cite http://www.acm.org/jgt/papers/MollerTrumbore97/ + http://www.graphics.cornell.edu/pubs/1997/MT97.html + */ + inline float intersectionTime( + const Vector3& vert0, + const Vector3& vert1, + const Vector3& vert2, + const Vector3& edge01, + const Vector3& edge02) const; + + + inline float intersectionTime( + const Vector3& vert0, + const Vector3& vert1, + const Vector3& vert2) const { + + return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0); + } + + + inline float intersectionTime( + const Vector3& vert0, + const Vector3& vert1, + const Vector3& vert2, + double& w0, + double& w1, + double& w2) const { + + return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0, w0, w1, w2); + } + + /* One-sided triangle + */ + inline float intersectionTime(const Triangle& triangle) const { + return intersectionTime( + triangle.vertex(0), triangle.vertex(1), triangle.vertex(2), + triangle.edge01(), triangle.edge02()); + } + + inline float intersectionTime( + const Triangle& triangle, + double& w0, + double& w1, + double& w2) const { + return intersectionTime(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2), + triangle.edge01(), triangle.edge02(), w0, w1, w2); + } + + /** Refracts about the normal + using G3D::Vector3::refractionDirection + and bumps the ray slightly from the newOrigin. */ + Ray refract( + const Vector3& newOrigin, + const Vector3& normal, + float iInside, + float iOutside) const; + + /** Reflects about the normal + using G3D::Vector3::reflectionDirection + and bumps the ray slightly from + the newOrigin. */ + Ray reflect( + const Vector3& newOrigin, + const Vector3& normal) const; +}; + + +#define EPSILON 0.000001 +#define CROSS(dest,v1,v2) \ + dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \ + dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \ + dest[2]=v1[0]*v2[1]-v1[1]*v2[0]; + +#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]) + +#define SUB(dest,v1,v2) \ + dest[0]=v1[0]-v2[0]; \ + dest[1]=v1[1]-v2[1]; \ + dest[2]=v1[2]-v2[2]; + +inline float Ray::intersectionTime( + const Vector3& vert0, + const Vector3& vert1, + const Vector3& vert2, + const Vector3& edge1, + const Vector3& edge2) const { + + (void)vert1; + (void)vert2; + + // Barycenteric coords + float u, v; + + float tvec[3], pvec[3], qvec[3]; + + // begin calculating determinant - also used to calculate U parameter + CROSS(pvec, m_direction, edge2); + + // if determinant is near zero, ray lies in plane of triangle + const float det = DOT(edge1, pvec); + + if (det < EPSILON) { + return finf(); + } + + // calculate distance from vert0 to ray origin + SUB(tvec, m_origin, vert0); + + // calculate U parameter and test bounds + u = DOT(tvec, pvec); + if ((u < 0.0f) || (u > det)) { + // Hit the plane outside the triangle + return finf(); + } + + // prepare to test V parameter + CROSS(qvec, tvec, edge1); + + // calculate V parameter and test bounds + v = DOT(m_direction, qvec); + if ((v < 0.0f) || (u + v > det)) { + // Hit the plane outside the triangle + return finf(); + } + + + // Case where we don't need correct (u, v): + const float t = DOT(edge2, qvec); + + if (t >= 0.0f) { + // Note that det must be positive + return t / det; + } else { + // We had to travel backwards in time to intersect + return finf(); + } +} + + +inline float Ray::intersectionTime( + const Vector3& vert0, + const Vector3& vert1, + const Vector3& vert2, + const Vector3& edge1, + const Vector3& edge2, + double& w0, + double& w1, + double& w2) const { + + (void)vert1; + (void)vert2; + + // Barycenteric coords + float u, v; + + float tvec[3], pvec[3], qvec[3]; + + // begin calculating determinant - also used to calculate U parameter + CROSS(pvec, m_direction, edge2); + + // if determinant is near zero, ray lies in plane of triangle + const float det = DOT(edge1, pvec); + + if (det < EPSILON) { + return finf(); + } + + // calculate distance from vert0 to ray origin + SUB(tvec, m_origin, vert0); + + // calculate U parameter and test bounds + u = DOT(tvec, pvec); + if ((u < 0.0f) || (u > det)) { + // Hit the plane outside the triangle + return finf(); + } + + // prepare to test V parameter + CROSS(qvec, tvec, edge1); + + // calculate V parameter and test bounds + v = DOT(m_direction, qvec); + if ((v < 0.0f) || (u + v > det)) { + // Hit the plane outside the triangle + return finf(); + } + + float t = DOT(edge2, qvec); + + if (t >= 0) { + const float inv_det = 1.0f / det; + t *= inv_det; + u *= inv_det; + v *= inv_det; + + w0 = (1.0f - u - v); + w1 = u; + w2 = v; + + return t; + } else { + // We had to travel backwards in time to intersect + return finf(); + } +} + +#undef EPSILON +#undef CROSS +#undef DOT +#undef SUB + +}// namespace + +#endif diff --git a/externals/g3dlite/G3D/Rect2D.h b/externals/g3dlite/G3D/Rect2D.h new file mode 100644 index 00000000000..2fb58c50465 --- /dev/null +++ b/externals/g3dlite/G3D/Rect2D.h @@ -0,0 +1,417 @@ +/** + @file Rect2D.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2003-11-13 + @created 2009-11-16 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_Rect2D_h +#define G3D_Rect2D_h + +// Linux defines this as a macro +#ifdef border +#undef border +#endif + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/Vector2.h" + +#ifdef _MSC_VER +// Turn off "conditional expression is constant" warning; MSVC generates this +// for debug assertions in inlined methods. +# pragma warning (disable : 4127) +#endif + + +namespace G3D { + +class Any; + +/** + If you are using this class for pixel rectangles, keep in mind that the last + pixel you can draw to is at x0() + width() - 1. + */ +class Rect2D { +private: + Vector2 min, max; + + /** + Returns true if the whole polygon is clipped. + @param p Value of the point + @param axis Index [0 or 1] of the axis to clip along? + @param clipGreater Are we clipping greater than or less than the line? + @param inPoly Polygon being clipped + @param outPoly The clipped polygon + */ + template + static bool clipSide2D( + const float p, bool clipGreater, int axis, + const Array& inPoly, Array& outPoly) { + + outPoly.clear(); + int i0 = -1; + + Vector2 pt1; + bool c1 = true; + + float negate = clipGreater ? -1 : 1; + + // Find a point that is not clipped + for (i0 = 0; (i0 < inPoly.length()) && c1; ++i0) { + pt1 = inPoly[i0]; + c1 = (negate * pt1[axis]) < (negate * p); + } + + // We incremented i0 one time to many + --i0; + + if (c1) { + // We could not find an unclipped point + return true; + } + + outPoly.append(pt1); + + // for each point in inPoly, + // if the point is outside the side and the previous one was also outside, continue + // if the point is outside the side and the previous one was inside, cut the line + // if the point is inside the side and the previous one was also inside, append the points + // if the point is inside the side and the previous one was outside, cut the line + for (int i = 1; i <= inPoly.length(); ++i) { + T pt2 = inPoly[(i + i0) % inPoly.length()]; + bool c2 = (negate * pt2[axis]) < (negate * p); + + if (c1 ^ c2) { + + if (!c1 && c2 && (i > 1)) { + // Unclipped to clipped trasition and not the first iteration + outPoly.append(pt1); + } + + // only one point is clipped, find where the line crosses the clipping plane + + + float alpha; + if (pt2[axis] == pt1[axis]) { + alpha = 0; + } else { + alpha = (p - pt1[axis]) / (pt2[axis] - pt1[axis]); + } + outPoly.append(pt1.lerp(pt2, alpha)); + } else if (! (c1 || c2) && (i != 1)) { + // neither point is clipped (don't do this the first time + // because we appended the first pt before the loop) + outPoly.append(pt1); + } + + pt1 = pt2; + c1 = c2; + } + + return false; + } + +public: + + /** \param any Must either Rect2D::xywh(#, #, #, #) or Rect2D::xyxy(#, #, #, #)*/ + Rect2D(const Any& any); + + /** Converts the Rect2D to an Any. */ + operator Any() const; + + Rect2D() : min(0, 0), max(0, 0) {} + + /** Creates a rectangle at 0,0 with the given width and height*/ + Rect2D(const Vector2& wh) : min(0, 0), max(wh.x, wh.y) {} + + /** Computes a rectangle that contains both @a a and @a b. + Note that even if @a or @b has zero area, its origin will be included.*/ + Rect2D(const Rect2D& a, const Rect2D& b) { + min = a.min.min(b.min); + max = a.max.max(b.max); + } + + /** @brief Uniformly random point on the interior */ + Vector2 randomPoint() const { + return Vector2(uniformRandom(0, max.x - min.x) + min.x, + uniformRandom(0, max.y - min.y) + min.y); + } + + float width() const { + return max.x - min.x; + } + + float height() const { + return max.y - min.y; + } + + float x0() const { + return min.x; + } + + float x1() const { + return max.x; + } + + float y0() const { + return min.y; + } + + float y1() const { + return max.y; + } + + /** Min, min corner */ + Vector2 x0y0() const { + return min; + } + + Vector2 x1y0() const { + return Vector2(max.x, min.y); + } + + Vector2 x0y1() const { + return Vector2(min.x, max.y); + } + + /** Max,max corner */ + Vector2 x1y1() const { + return max; + } + + /** Width and height */ + Vector2 wh() const { + return max - min; + } + + Vector2 center() const { + return (max + min) * 0.5; + } + + float area() const { + return width() * height(); + } + + bool isFinite() const { + return (min.isFinite() && max.isFinite()); + } + + Rect2D lerp(const Rect2D& other, float alpha) const { + Rect2D out; + + out.min = min.lerp(other.min, alpha); + out.max = max.lerp(other.max, alpha); + + return out; + } + + static Rect2D xyxy(float x0, float y0, float x1, float y1) { + Rect2D r; + + r.min.x = G3D::min(x0, x1); + r.min.y = G3D::min(y0, y1); + r.max.x = G3D::max(x0, x1); + r.max.y = G3D::max(y0, y1); + + return r; + } + + static Rect2D xyxy(const Vector2& v0, const Vector2& v1) { + Rect2D r; + + r.min = v0.min(v1); + r.max = v0.max(v1); + + return r; + } + + static Rect2D xywh(float x, float y, float w, float h) { + return xyxy(x, y, x + w, y + h); + } + + static Rect2D xywh(const Vector2& v, const Vector2& w) { + return xyxy(v.x, v.y, v.x + w.x, v.y + w.y); + } + + /** Constructs a Rect2D with infinite boundaries. + Use isFinite() to test either min or max. + */ + static Rect2D inf() { + return xyxy(Vector2::inf(), Vector2::inf()); + } + + bool contains(const Vector2& v) const { + return (v.x >= min.x) && (v.y >= min.y) && (v.x <= max.x) && (v.y <= max.y); + } + + bool contains(const Rect2D& r) const { + return (min.x <= r.min.x) && (min.y <= r.min.y) && + (max.x >= r.max.x) && (max.y >= r.max.y); + } + + /** True if there is non-zero area to the intersection between @a this and @a r. + Note that two rectangles that are adjacent do not intersect because there is + zero area to the overlap, even though one of them "contains" the corners of the other.*/ + bool intersects(const Rect2D& r) const { + return (min.x < r.max.x) && (min.y < r.max.y) && + (max.x > r.min.x) && (max.y > r.min.y); + } + + /** Like intersection, but counts the adjacent case as touching. */ + bool intersectsOrTouches(const Rect2D& r) const { + return (min.x <= r.max.x) && (min.y <= r.max.y) && + (max.x >= r.min.x) && (max.y >= r.min.y); + } + + Rect2D operator*(float s) const { + return xyxy(min.x * s, min.y * s, max.x * s, max.y * s); + } + + Rect2D operator/(float s) const { + return xyxy(min / s, max / s); + } + + Rect2D operator/(const Vector2& s) const { + return xyxy(min / s, max / s); + } + + Rect2D operator+(const Vector2& v) const { + return xyxy(min + v, max + v); + } + + Rect2D operator-(const Vector2& v) const { + return xyxy(min - v, max - v); + } + + bool operator==(const Rect2D& other) const { + return (min == other.min) && (max == other.max); + } + + bool operator!=(const Rect2D& other) const { + return (min != other.min) || (max != other.max); + } + + /** Returns the corners in the order: (min,min), (max,min), (max,max), (min,max). */ + Vector2 corner(int i) const { + debugAssert(i >= 0 && i < 4); + switch (i & 3) { + case 0: + return Vector2(min.x, min.y); + case 1: + return Vector2(max.x, min.y); + case 2: + return Vector2(max.x, max.y); + case 3: + return Vector2(min.x, max.y); + default: + // Should never get here + return Vector2(0, 0); + } + } + + + /** @deprecated + @sa expand() */ + Rect2D border(float delta) const { + return Rect2D::xywh(x0() + delta, + y0() + delta, + width() - 2.0f * delta, + height() - 2.0f * delta); + } + + /** Returns a new Rect2D that is bigger/smaller by the specified amount + (negative is shrink.) */ + Rect2D expand(float delta) const { + float newX = x0() - delta; + float newY = y0() - delta; + float newW = width() + 2.0f * delta; + float newH = height() + 2.0f * delta; + + if (newW < 0.0f) { + newX = (x0() + width()) / 2.0f; + newW = 0.0f; + } + + if (newH < 0.0f) { + newY = (y0() + height()) / 2.0f; + newH = 0.0f; + } + return Rect2D::xywh(newX, newY, newW, newH); + } + + /** + Clips so that the rightmost point of the outPoly is at rect.x1 (e.g. a 800x600 window produces + rightmost point 799, not 800). The results are suitable for pixel rendering if iRounded. + Templated so that it will work for Vector2,3,4 (the z and w components are interpolated linearly). + The template parameter must define T.lerp and contain x and y components. + + If the entire polygon is clipped by a single side, the result will be empty. + The result might also have zero area but not be empty. + */ + template + void clip(const Array& inPoly, Array& outPoly) const { + + const bool greaterThan = true; + const bool lessThan = false; + const int X = 0; + const int Y = 1; + + Array temp; + + bool entirelyClipped = + clipSide2D(x0(), lessThan, X, inPoly, temp) || + clipSide2D(x1(), greaterThan, X, temp, outPoly) || + clipSide2D(y0(), lessThan, Y, outPoly, temp) || + clipSide2D(y1(), greaterThan, Y, temp, outPoly); + + if (entirelyClipped) { + outPoly.clear(); + } + } + + + /** Returns the largest, centered Rect2D that can fit inside this + while maintaining the aspect ratio of x:y. Convenient for + displaying images in odd-shaped windows. + */ + Rect2D largestCenteredSubRect(float ww, float hh) const { + float textureAspect = hh / ww; + float viewAspect = height() / width(); + + if (viewAspect > textureAspect) { + // The view is too tall + float h = width() * textureAspect; + float y = (height() - h) / 2; + return Rect2D::xywh(0, y, width(), h) + corner(0); + } else { + // The view is too wide + float w = height() / textureAspect; + float x = (width() - w) / 2; + return Rect2D::xywh(x, 0, w, height()) + corner(0); + } + } + + /** + Returns the overlap region between the two rectangles. This may have zero area + if they do not intersect. See the two-Rect2D constructor for a way to compute + a union-like rectangle. + */ + Rect2D intersect(const Rect2D& other) const { + if (intersects(other)) { + return Rect2D::xyxy(min.max(other.min), max.min(other.max)); + }else{ + return Rect2D::xywh(0, 0, 0, 0); + } + } +}; + +typedef Rect2D AABox2D; +} + +#endif diff --git a/externals/g3dlite/G3D/ReferenceCount.h b/externals/g3dlite/G3D/ReferenceCount.h new file mode 100644 index 00000000000..84591c6d8e5 --- /dev/null +++ b/externals/g3dlite/G3D/ReferenceCount.h @@ -0,0 +1,570 @@ +/** + @file ReferenceCount.h + + Reference Counting Garbage Collector for C++ + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @cite Adapted and extended from Justin Miller's "RGC" class that appeared in BYTE magazine. + @cite See also http://www.jelovic.com/articles/cpp_without_memory_errors_slides.htm + + @created 2001-10-23 + @edited 2009-04-25 +*/ +#ifndef G3D_ReferenceCount_h +#define G3D_ReferenceCount_h + +#include "G3D/platform.h" +#include "G3D/debug.h" +#include "G3D/AtomicInt32.h" + +namespace G3D { + +#ifdef _MSC_VER +// Turn off "conditional expression is constant" warning; MSVC generates this +// for debug assertions in inlined methods. +# pragma warning (disable : 4127) +#endif + +/** Base class for WeakReferenceCountedPointer */ +class _WeakPtr { +public: + inline virtual ~_WeakPtr() {} + +protected: + friend class ReferenceCountedObject; + + /** Called by ReferenceCountedObject to tell a weak pointer that its underlying object was collected. */ + virtual void objectCollected() = 0; +}; + +/** Used internally by ReferenceCountedObject */ +class _WeakPtrLinkedList { +public: + _WeakPtr* weakPtr; + _WeakPtrLinkedList* next; + + inline _WeakPtrLinkedList() : weakPtr(NULL), next(NULL) {} + + /** Inserts this node into the head of the list that previously had n as its head. */ + inline _WeakPtrLinkedList(_WeakPtr* p, _WeakPtrLinkedList* n) : weakPtr(p), next(n) {} +}; + +/** + Objects that are reference counted inherit from this. Subclasses + must have a public destructor (the default destructor is fine) + and publicly inherit ReferenceCountedObject. + + Multiple inheritance from a reference counted object is dangerous-- use + at your own risk. + + ReferenceCountedPointer and ReferenceCountedObject are threadsafe. + You can create and drop references on multiple threads without + violating integrity. WeakReferenceCountedPointer is not + threadsafe. Introducing a weak pointer destroys all thread safety, + even for strong pointers to the same object (this is inherent in the + design of the class; we cannot fix it without slowing down the + performance of reference counted objects.) + + Usage Example + +
+
+class Foo : public G3D::ReferenceCountedObject {
+public:
+    int x;
+};
+
+class Bar : public Foo {};
+
+typedef G3D::ReferenceCountedPointer FooRef;
+typedef G3D::WeakReferenceCountedPointer WeakFooRef;
+typedef G3D::ReferenceCountedPointer BarRef;
+
+
+int main(int argc, char *argv[]) {
+
+    WeakFooRef x;
+
+    {
+        FooRef a = new Foo();
+
+        // Reference count == 1
+
+        x = a;
+        // Weak references do not increase count
+
+        {
+            FooRef b = a;
+            // Reference count == 2
+        }
+
+        // Reference count == 1
+    }
+    // No more strong references; object automatically deleted.
+    // x is set to NULL automatically.
+
+    // Example of using dynamic cast on reference counted objects
+    BarRef b = new Bar();
+
+    // No cast needed to go down the heirarchy.
+    FooRef f = b;
+
+    // We can't cast the reference object because it is a class.
+    // Instead we must extract the pointer and cast that:
+    b = dynamic_cast(&*f);
+
+    return 0;
+}
+
+ */ +class ReferenceCountedObject { +public: + + /** + The long name is to keep this from accidentally conflicting with + a subclass's variable name. Do not use or explicitly manipulate + this value--its type may change in the future and is not part + of the supported API. + */ + AtomicInt32 ReferenceCountedObject_refCount; + + /** + Linked list of all weak pointers that reference this (some may be + on the stack!). Do not use or explicitly manipulate this value. + */ + _WeakPtrLinkedList* ReferenceCountedObject_weakPointer; + +protected: + + ReferenceCountedObject(); + +public: + + /** Automatically called immediately before the object is deleted. + This is not called from the destructor because it needs to be invoked + before the subclass destructor. + */ + void ReferenceCountedObject_zeroWeakPointers(); + + virtual ~ReferenceCountedObject(); + + + /** + Note: copies will initially start out with 0 + references and 0 weak references like any other object. + */ + ReferenceCountedObject(const ReferenceCountedObject& notUsed); + + ReferenceCountedObject& operator=(const ReferenceCountedObject& other); +}; + + + +/** + Use ReferenceCountedPointer in place of T* in your program. + T must subclass ReferenceCountedObject. +@deprecated To be replaced by boost::shared_ptr in 7.0 + */ +template +class ReferenceCountedPointer { +private: + + T* m_pointer; + +public: + typedef T element_type; + + inline T* pointer() const { + return m_pointer; + } + +private: + + /** Nulls out the pointer and drops a reference. If the reference + count hits zero. */ + void zeroPointer() { + if (m_pointer != NULL) { + + ReferenceCountedObject* pointer = ((ReferenceCountedObject*)m_pointer); + debugAssert(G3D::isValidHeapPointer(m_pointer)); + debugAssertM(pointer->ReferenceCountedObject_refCount.value() > 0, + "Dangling reference detected."); + + // Only delete if this instance caused the count to hit + // exactly zero. If there is a race condition, the value + // may be zero after decrement returns, but only one of + // the instances will get a zero return value. + if (pointer->ReferenceCountedObject_refCount.decrement() == 0) { + // We held the last reference, so delete the object. + // This test is threadsafe because there is no way for + // the reference count to increase after the last + // reference was dropped (assuming the application does + // not voilate the class abstraction). + //debugPrintf(" delete 0x%x\n", m_pointer); + + // We must zero the weak pointers *before* deletion in case there + // are cycles of weak references. + // Note that since there are no strong references at this point, + // it is perfectly fair to zero the weak pointers anyway. + pointer->ReferenceCountedObject_zeroWeakPointers(); + delete pointer; + } + + m_pointer = NULL; + } + } + + /** Non-atomic (except for the referencec increment). Can only be + called in contexts like the copy constructor or initial + constructor where it is known that the reference count will + not hit zero on some other thread. */ + void setPointer(T* x) { + if (x != m_pointer) { + zeroPointer(); + + if (x != NULL) { + debugAssert(G3D::isValidHeapPointer(x)); + + m_pointer = x; + + // Note that the ref count can be zero if this is the + // first pointer to it + ReferenceCountedObject* pointer = (ReferenceCountedObject*)m_pointer; + debugAssertM(pointer->ReferenceCountedObject_refCount.value() >= 0, + "Negative reference count detected."); + pointer->ReferenceCountedObject_refCount.increment(); + } + } + } + +public: + + inline ReferenceCountedPointer() : m_pointer(NULL) {} + + /** + Allow silent cast to the base class. + +
+        SubRef  s = new Sub();
+        BaseRef b = s;
+      
+ + i.e., compile-time subtyping rule + RCP<T> <: RCP<S> if T <: S + */ + template + inline ReferenceCountedPointer(const ReferenceCountedPointer& p) : + m_pointer(NULL) { + setPointer(p.pointer()); + } + +# if (! defined(MSC_VER) || (MSC_VER >= 1300)) + /** + Explicit cast to a subclass. Acts like dynamic cast; the result will be NULL if + the cast cannot succeed. Not supported on VC6. +
+        SubRef  s = new Sub();
+        BaseRef b = s;
+        s = b.downcast();   // Note that the template argument is the object type, not the pointer type.
+      
+ */ + template + ReferenceCountedPointer downcast() { + return ReferenceCountedPointer(dynamic_cast(m_pointer)); + } + + template + const ReferenceCountedPointer downcast() const { + return ReferenceCountedPointer(dynamic_cast(m_pointer)); + } +# endif + + // We need an explicit version of the copy constructor as well or + // the default copy constructor will be used. + inline ReferenceCountedPointer(const ReferenceCountedPointer& p) : m_pointer(NULL) { + setPointer(p.m_pointer); + } + + /** Allows construction from a raw pointer. That object will thereafter be + reference counted -- do not call delete on it. + + Use of const allows downcast on const references */ + inline ReferenceCountedPointer(const T* p) : m_pointer(NULL) { + // only const constructor is defined to remove ambiguity using NULL + setPointer(const_cast(p)); + } + + + inline ~ReferenceCountedPointer() { + zeroPointer(); + } + + inline size_t hashCode() const { + return reinterpret_cast(m_pointer);; + } + + inline const ReferenceCountedPointer& operator=(const ReferenceCountedPointer& p) { + setPointer(p.m_pointer); + return *this; + } + + inline ReferenceCountedPointer& operator=(T* p) { + setPointer(p); + return *this; + } + + inline bool operator==(const ReferenceCountedPointer& y) const { + return (m_pointer == y.m_pointer); + } + + inline bool operator!=(const ReferenceCountedPointer& y) const { + return (m_pointer != y.m_pointer); + } + + bool operator < (const ReferenceCountedPointer& y) const { + return (m_pointer < y.m_pointer); + } + + bool operator > (const ReferenceCountedPointer& y) const { + return (m_pointer > y.m_pointer); + } + + bool operator <= (const ReferenceCountedPointer& y) const { + return (m_pointer <= y.m_pointer); + } + + bool operator >= (const ReferenceCountedPointer& y) const { + return (m_pointer >= y.m_pointer); + } + + inline T& operator*() const { + debugAssertM(m_pointer != NULL, "Dereferenced a NULL ReferenceCountedPointer"); + return (*m_pointer); + } + + inline T* operator->() const { + debugAssertM(m_pointer != NULL, "Dereferenced a NULL ReferenceCountedPointer"); + return m_pointer; + } + + inline bool isNull() const { + return (m_pointer == NULL); + } + + inline bool notNull() const { + return (m_pointer != NULL); + } + + // TODO: distinguish between last strong and last any pointer + /** + Returns true if this is the last reference to an object. + Useful for flushing memoization caches-- a cache that holds the last + reference is unnecessarily keeping an object alive. + + Not threadsafe. + + @deprecated Use WeakReferenceCountedPointer for caches + */ + inline int isLastReference() const { + return (m_pointer->ReferenceCountedObject_refCount.value() == 1); + } +}; + + +/** + A weak pointer allows the object it references to be garbage collected. + Weak pointers are commonly used in caches, where it is important to hold + a pointer to an object without keeping that object alive solely for the + cache's benefit (i.e., the object can be collected as soon as all + pointers to it outside the cache are gone). They are also convenient + for adding back-pointers in tree and list structures. + + Weak pointers may become NULL at any point (when their target is collected). + Therefore the only way to reference the target is to convert to a strong + pointer and then check that it is not NULL. + +@deprecated To be replaced by boost::weak_ptr in 7.0 + */ +template +class WeakReferenceCountedPointer : public _WeakPtr { +private: + + /** NULL if the object has been collected. */ + T* pointer; + +public: + /** + Creates a strong pointer, which prevents the object from being + garbage collected. The strong pointer may be NULL, which means + that the underlying. + */ + // There is intentionally no way to check if the + // WeakReferenceCountedPointer has a null reference without + // creating a strong pointer since there is no safe way to use + // that information-- the pointer could be collected by a + // subsequent statement. + ReferenceCountedPointer createStrongPtr() const { + // TODO: What if the object's destructor is called while we + // are in this method? + return ReferenceCountedPointer(pointer); + } + +private: + + /** Thread issues: safe because this is only called when another + object is guaranteed to keep p alive for the duration of this + call. */ + void setPointer(T* p) { + // TODO: must prevent the object from being collected while in + // this method + + zeroPointer(); + pointer = p; + + if (pointer != NULL) { + // TODO: threadsafe: must update the list atomically + + // Add myself to the head of my target's list of weak pointers + _WeakPtrLinkedList* head = + new _WeakPtrLinkedList + (this, + pointer->ReferenceCountedObject_weakPointer); + + pointer->ReferenceCountedObject_weakPointer = head; + } else { + + } + } + + + /** + Removes this from its target's list of weak pointers. Called + when the weak pointer goes out of scope. + + Thread issues: depends on the thread safety of createStrongPtr. + */ + void zeroPointer() { + // Grab a strong reference to prevent the object from being collected while we + // are traversing its list. + ReferenceCountedPointer strong = createStrongPtr(); + + // If the following test fails then the object was collected before we + // reached it. + if (strong.notNull()) { + debugAssertM(((ReferenceCountedObject*)pointer)->ReferenceCountedObject_weakPointer != NULL, + "Weak pointer exists without a backpointer from the object."); + + // Remove myself from my target's list of weak pointers + _WeakPtrLinkedList** node = &((ReferenceCountedObject*)pointer)->ReferenceCountedObject_weakPointer; + while ((*node)->weakPtr != this) { + node = &((*node)->next); + debugAssertM(*node != NULL, + "Weak pointer exists without a backpointer from the object (2)."); + } + + // Node must now point at the node for me. Remove node and + // close the linked list behind it. + _WeakPtrLinkedList* temp = *node; + *node = temp->next; + + // Now delete the node corresponding to me + delete temp; + } + + pointer = NULL; + } + +public: + + WeakReferenceCountedPointer() : pointer(0) {} + + /** + Allow compile time subtyping rule + RCP<T> <: RCP<S> if T <: S + */ + template + inline WeakReferenceCountedPointer(const WeakReferenceCountedPointer& p) : pointer(0) { + // Threadsafe: the object cannot be collected while the other pointer exists. + setPointer(p.pointer); + } + + template + inline WeakReferenceCountedPointer(const ReferenceCountedPointer& p) : pointer(0) { + // Threadsafe: the object cannot be collected while the other + // pointer exists. + setPointer(p.pointer()); + } + + // Gets called a *lot* when weak pointers are on the stack + WeakReferenceCountedPointer( + const WeakReferenceCountedPointer& weakPtr) : pointer(0) { + setPointer(weakPtr.pointer); + } + + WeakReferenceCountedPointer( + const ReferenceCountedPointer& strongPtr) : pointer(0) { + setPointer(strongPtr.pointer()); + } + + ~WeakReferenceCountedPointer() { + zeroPointer(); + } + + WeakReferenceCountedPointer& operator=(const WeakReferenceCountedPointer& other) { + // Threadsafe: the object cannot be collected while the other pointer exists. + + // I now point at other's target + setPointer(other.pointer); + + return *this; + } + + WeakReferenceCountedPointer& operator=(const ReferenceCountedPointer& other) { + + // Threadsafe: the object cannot be collected while the other pointer exists. + + // I now point at other's target + setPointer(other.pointer()); + + return *this; + } + + bool operator==(const WeakReferenceCountedPointer& other) const { + return pointer == other.pointer; + } + + bool operator!=(const WeakReferenceCountedPointer& other) const { + return pointer != other.pointer; + } + + bool operator < (const WeakReferenceCountedPointer& y) const { + return (pointer < y.pointer); + } + + bool operator > (const WeakReferenceCountedPointer& y) const { + return (pointer > y.pointer); + } + + bool operator <= (const WeakReferenceCountedPointer& y) const { + return (pointer <= y.pointer); + } + + bool operator >= (const ReferenceCountedPointer& y) const { + return (pointer >= y.pointer); + } + +protected: + + /** Invoked by the destructor on ReferenceCountedPointer. */ + void objectCollected() { + debugAssertM(pointer != NULL, + "Removed a weak pointer twice."); + pointer = NULL; + } + +}; + +} // namespace + +#endif + diff --git a/externals/g3dlite/G3D/RegistryUtil.h b/externals/g3dlite/G3D/RegistryUtil.h new file mode 100644 index 00000000000..4b47be5f4bd --- /dev/null +++ b/externals/g3dlite/G3D/RegistryUtil.h @@ -0,0 +1,97 @@ +/** + @file RegistryUtil.h + + @created 2006-04-06 + @edited 2006-04-06 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. +*/ + +#ifndef G3D_REGISTRYUTIL_H +#define G3D_REGISTRYUTIL_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" + +// This file is only used on Windows +#ifdef G3D_WIN32 + +#include + +namespace G3D { + +/** + Provides generalized Windows registry querying. + + All key names are one string in the format: + "[base key]\[sub-keys]" + + A value must now be provided for every query. + An empty value string will use the (Default) value. + + [base key] can be any of the following: + HKEY_CLASSES_ROOT + HKEY_CURRENT_CONFIG + HKEY_CURRENT_USER + HKEY_LOCAL_MACHINE + HKEY_PERFORMANCE_DATA + HKEY_PERFORMANCE_NLSTEXT + HKEY_PERFORMANCE_TEXT + HKEY_USERS + + valueExists() should be used to validate a key+value before reading or writing + to ensure that a debug assert or false return is for a different error during + reads and writes. + + All read and write calls will assert when a key will not open for reasons other + that it does not exist. All read and write calls will assert when the value cannot + be read or written for any reason. +*/ +class RegistryUtil { + +public: + /** returns true if the key exists and the current user has permission to read */ + static bool keyExists(const std::string& key); + + /** returns true if the key exists and the current user has permission to read */ + static bool valueExists(const std::string& key, const std::string& value); + + /** returns false if the key could not be read for any reason. */ + static bool readInt32(const std::string& key, const std::string& value, int32& data); + + /** + Reads an arbitrary amount of data from a binary registry key. + returns false if the key could not be read for any reason. + + @beta + @param data pointer to the output buffer of sufficient size. Pass NULL as data in order to have available data size returned in dataSize. + @param dataSize size of the output buffer. When NULL is passed for data, contains the size of available data on successful return. + */ + static bool readBytes(const std::string& key, const std::string& value, uint8* data, uint32& dataSize); + + /** returns false if the key could not be read for any reason. */ + static bool readString(const std::string& key, const std::string& value, std::string& data); + + /** returns false if the key could not be written for any reason. */ + static bool writeInt32(const std::string& key, const std::string& value, int32 data); + + /** + Writes an arbitrary amount of data to a binary registry key. + returns false if the key could not be written for any reason. + + @param data pointer to the input buffer + @param dataSize size of the input buffer that should be written + */ + static bool writeBytes(const std::string& key, const std::string& value, const uint8* data, uint32 dataSize); + + /** returns false if the key could not be written for any reason. */ + static bool writeString(const std::string& key, const std::string& value, const std::string& data); + +}; + +} // namespace G3D + +#endif // G3D_WIN32 + +#endif // G3D_REGISTRYTUIL_H diff --git a/externals/g3dlite/G3D/Set.h b/externals/g3dlite/G3D/Set.h new file mode 100644 index 00000000000..9a8e1b619bb --- /dev/null +++ b/externals/g3dlite/G3D/Set.h @@ -0,0 +1,186 @@ +/** + @file Set.h + + Hash set + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2001-12-09 + @edited 2009-06-10 + */ + +#ifndef G3D_Set_h +#define G3D_Set_h + +#include "G3D/platform.h" +#include "G3D/Table.h" +#include "G3D/MemoryManager.h" +#include +#include + +namespace G3D { + +/** + An unordered data structure that has at most one of each element. + Provides O(1) time insert, remove, and member test (contains). + + Set uses G3D::Table internally, which means that the template type T + must define a hashCode and operator== function. See G3D::Table for + a discussion of these functions. + */ +// There is not copy constructor or assignment operator defined because +// the default ones are correct for Set. +template, class EqualsFunc = EqualsTrait > +class Set { + + /** + If an object is a member, it is contained in + this table. + */ + Table memberTable; + +public: + + void clearAndSetMemoryManager(const MemoryManager::Ref& m) { + memberTable.clearAndSetMemoryManager(m); + } + + virtual ~Set() {} + + int size() const { + return (int)memberTable.size(); + } + + bool contains(const T& member) const { + return memberTable.containsKey(member); + } + + /** + Inserts into the table if not already present. + */ + void insert(const T& member) { + memberTable.set(member, true); + } + + /** + Returns true if the element was present and removed. Returns false + if the element was not present. + */ + bool remove(const T& member) { + return memberTable.remove(member); + } + + /** If @a member is present, sets @a removed to the element + being removed and returns true. Otherwise returns false + and does not write to @a removed. This is useful when building + efficient hashed data structures that wrap Set. + */ + bool getRemove(const T& member, T& removed) { + bool ignore; + return memberTable.getRemove(member, removed, ignore); + } + + /** If a value that is EqualsFunc to @a member is present, returns a pointer to the + version stored in the data structure, otherwise returns NULL. + */ + const T* getPointer(const T& member) const { + return memberTable.getKeyPointer(member); + } + + Array getMembers() const { + return memberTable.getKeys(); + } + + void getMembers(Array& keyArray) const { + memberTable.getKeys(keyArray); + } + + void clear() { + memberTable.clear(); + } + + void deleteAll() { + getMembers().deleteAll(); + clear(); + } + + /** + C++ STL style iterator variable. See begin(). + */ + class Iterator { + private: + friend class Set; + + // Note: this is a Table iterator, we are currently defining + // Set iterator + typename Table::Iterator it; + + Iterator(const typename Table::Iterator& it) : it(it) {} + + public: + inline bool operator!=(const Iterator& other) const { + return !(*this == other); + } + + bool hasMore() const { + return it.hasMore(); + } + + bool operator==(const Iterator& other) const { + return it == other.it; + } + + /** + Pre increment. + */ + Iterator& operator++() { + ++it; + return *this; + } + + /** + Post increment (slower than preincrement). + */ + Iterator operator++(int) { + Iterator old = *this; + ++(*this); + return old; + } + + const T& operator*() const { + return it->key; + } + + T* operator->() const { + return &(it->key); + } + + operator T*() const { + return &(it->key); + } + }; + + + /** + C++ STL style iterator method. Returns the first member. + Use preincrement (++entry) to get to the next element. + Do not modify the set while iterating. + */ + Iterator begin() const { + return Iterator(memberTable.begin()); + } + + + /** + C++ STL style iterator method. Returns one after the last iterator + element. + */ + const Iterator end() const { + return Iterator(memberTable.end()); + } +}; + +} + +#endif + diff --git a/externals/g3dlite/G3D/SmallArray.h b/externals/g3dlite/G3D/SmallArray.h new file mode 100644 index 00000000000..41f9959e264 --- /dev/null +++ b/externals/g3dlite/G3D/SmallArray.h @@ -0,0 +1,155 @@ +/** + @file SmallArray.h + + @created 2009-04-26 + @edited 2009-04-26 + + Copyright 2000-2009, Morgan McGuire, http://graphics.cs.williams.edu + All rights reserved. + */ +#ifndef G3D_SmallArray_h +#define G3D_SmallArray_h + +#include "G3D/platform.h" +#include "G3D/Array.h" + +namespace G3D { + +/** Embeds \a N elements to reduce allocation time and increase + memory coherence when working with arrays of arrays. + Offers a limited subset of the functionality of G3D::Array.*/ +template +class SmallArray { +private: + int m_size; + + /** First N elements */ + T m_embedded[N]; + + /** Remaining elements */ + Array m_rest; + +public: + + SmallArray() : m_size(0) {} + + inline int size() const { + return m_size; + } + + void resize(int n, bool shrinkIfNecessary = true) { + m_rest.resize(std::max(0, n - N), shrinkIfNecessary); + m_size = n; + } + + void clear(bool shrinkIfNecessary = true) { + resize(0, shrinkIfNecessary); + } + + inline T& operator[](int i) { + debugAssert(i < m_size && i >= 0); + if (i < N) { + return m_embedded[i]; + } else { + return m_rest[i - N]; + } + } + + inline const T& operator[](int i) const { + debugAssert(i < m_size && i >= 0); + if (i < N) { + return m_embedded[i]; + } else { + return m_rest[i - N]; + } + } + + inline void push(const T& v) { + ++m_size; + if (m_size <= N) { + m_embedded[m_size - 1] = v; + } else { + m_rest.append(v); + } + } + + inline void append(const T& v) { + push(v); + } + + void fastRemove(int i) { + debugAssert(i < m_size && i >= 0); + if (i < N) { + if (m_size <= N) { + // Exclusively embedded + m_embedded[i] = m_embedded[m_size - 1]; + } else { + // Move one down from the rest array + m_embedded[i] = m_rest.pop(); + } + } else { + // Removing from the rest array + m_rest.fastRemove(i - N); + } + --m_size; + } + + T pop() { + debugAssert(m_size > 0); + if (m_size <= N) { + // Popping from embedded, don't need a temporary + --m_size; + return m_embedded[m_size]; + } else { + // Popping from rest + --m_size; + return m_rest.pop(); + } + } + + inline void popDiscard() { + debugAssert(m_size > 0); + if (m_size > N) { + m_rest.popDiscard(); + } + --m_size; + } + + inline T& next() { + ++m_size; + if (m_size <= N) { + return m_embedded[m_size - 1]; + } else { + return m_rest.next(); + } + } + + bool contains(const T& value) const { + for (int i = std::min(m_size, N) - 1; i >= 0; --i) { + if (m_embedded[i] == value) { + return true; + } + } + return m_rest.contains(value); + } + + template + SmallArray& operator=(const Array& src) { + resize(src.size()); + for (int i = 0; i < src.size(); ++i) { + (*this)[i] = src[i]; + } + return *this; + } + + inline const T& last() const { + return (*this)[size() - 1]; + } + + inline T& last() { + return (*this)[size() - 1]; + } +}; + +} +#endif diff --git a/externals/g3dlite/G3D/Sphere.h b/externals/g3dlite/G3D/Sphere.h new file mode 100644 index 00000000000..595b61c4bf1 --- /dev/null +++ b/externals/g3dlite/G3D/Sphere.h @@ -0,0 +1,148 @@ +/** + @file Sphere.h + + Sphere class + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2001-06-02 + @edited 2008-10-07 + */ + +#ifndef G3D_SPHERE_H +#define G3D_SPHERE_H + +#include "G3D/platform.h" +#include "G3D/Vector3.h" +#include "G3D/Array.h" +#include "G3D/Sphere.h" + +namespace G3D { + +/** + Sphere. + */ +class Sphere { +private: + + static int32 dummy; + +public: + Vector3 center; + float radius; + + Sphere() { + center = Vector3::zero(); + radius = 0; + } + + Sphere(class BinaryInput& b); + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + + Sphere( + const Vector3& center, + float radius) { + + this->center = center; + this->radius = radius; + } + + virtual ~Sphere() {} + + bool operator==(const Sphere& other) const { + return (center == other.center) && (radius == other.radius); + } + + bool operator!=(const Sphere& other) const { + return !((center == other.center) && (radius == other.radius)); + } + + /** + Returns true if point is less than or equal to radius away from + the center. + */ + bool contains(const Vector3& point) const; + + bool contains(const Sphere& other) const; + + /** + @deprecated Use culledBy(Array&) + */ + bool culledBy( + const class Plane* plane, + int numPlanes, + int32& cullingPlaneIndex, + const uint32 testMask, + uint32& childMask) const; + + /** + @deprecated Use culledBy(Array&) + */ + bool culledBy( + const class Plane* plane, + int numPlanes, + int32& cullingPlaneIndex = dummy, + const uint32 testMask = 0xFFFFFFFF) const; + + /** + See AABox::culledBy + */ + bool culledBy( + const Array& plane, + int32& cullingPlaneIndex, + const uint32 testMask, + uint32& childMask) const; + + /** + Conservative culling test that does not produce a mask for children. + */ + bool culledBy( + const Array& plane, + int32& cullingPlaneIndex = dummy, + const uint32 testMask = 0xFFFFFFFF) const; + + virtual std::string toString() const; + + float volume() const; + + float area() const; + + /** + Uniformly distributed on the surface. + */ + Vector3 randomSurfacePoint() const; + + /** + Uniformly distributed on the interior (includes surface) + */ + Vector3 randomInteriorPoint() const; + + void getBounds(class AABox& out) const; + + bool intersects(const Sphere& other) const; + + /** Translates the sphere */ + Sphere operator+(const Vector3& v) const { + return Sphere(center + v, radius); + } + + /** Translates the sphere */ + Sphere operator-(const Vector3& v) const { + return Sphere(center - v, radius); + } + + /** Sets this to the smallest sphere that encapsulates both */ + void merge(const Sphere& s); +}; + +} + +template <> struct HashTrait { + static size_t hashCode(const G3D::Sphere& key) { + return static_cast(key.center.hashCode() + (key.radius * 13)); + } +}; + + +#endif diff --git a/externals/g3dlite/G3D/Spline.h b/externals/g3dlite/G3D/Spline.h new file mode 100644 index 00000000000..fdd29e69ce9 --- /dev/null +++ b/externals/g3dlite/G3D/Spline.h @@ -0,0 +1,367 @@ +/** + @file Spline.h + + @author Morgan McGuire, http://graphics.cs.williams.edu + */ + +#ifndef G3D_SPLINE_H +#define G3D_SPLINE_H + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/g3dmath.h" +#include "G3D/Matrix4.h" +#include "G3D/Vector4.h" + +namespace G3D { + +/** Common implementation code for all G3D::Spline template parameters */ +class SplineBase { +public: + + /** Times at which control points occur. Must have the same + number of elements as Spline::control. */ + Array time; + + /** If cyclic, then the control points will be assumed to wrap around. + If not cyclic, then the tangents at the ends of the spline + point to the final control points.*/ + bool cyclic; + + /** For a cyclic spline, this is the time elapsed between the last + control point and the first. If less than or equal to zero this is + assumed to be: + + (time[0] - time[1] + . + time[time.size() - 1] - time[time.size() - 2]) / 2. + */ + float finalInterval; + + SplineBase() : cyclic(true), finalInterval(-1) {} + + virtual ~SplineBase() {} + + /** See specification for Spline::finalInterval; this handles the + non-positive case. Returns 0 if not cyclic. */ + float getFinalInterval() const; + + /** Returns the amount of time covered by this spline in one + period. For a cyclic spline, this contains the final + interval.*/ + float duration() const; + + /** Computes the derivative spline basis from the control point version. */ + static Matrix4 computeBasis(); + +protected: + + /** Assumes that t0 <= s < tn. called by computeIndex. */ + void computeIndexInBounds(float s, int& i, float& u) const; + +public: + + /** + Given a time @a s, finds @a i and 0 <= @a u < 1 such that + @a s = time[@a i] * @a u + time[@a i + 1] * (1 - @a u). Note that + @a i may be outside the bounds of the time and control arrays; + use getControl to handle wraparound and extrapolation issues. + + This function takes expected O(1) time for control points with + uniform time sampled control points or for uniformly + distributed random time samples, but may take O( log time.size() ) time + in the worst case. + + Called from evaluate(). + */ + void computeIndex(float s, int& i, float& u) const; +}; + + +/** + Smooth parameteric curve implemented using a piecewise 3rd-order + Catmull-Rom spline curve. The spline is considered infinite and may + either continue linearly from the specified control points or cycle + through them. Control points are spaced uniformly in time at unit + intervals by default, but irregular spacing may be explicitly + specified. + + The dimension of the spline can be set by varying the Control + template parameter. For a 1D function, use Spline. For a + curve in the plane, Spline. Note that any template + parameter that supports operator+(Control) and operator*(float) can + be used; you can make splines out of G3D::Vector4, G3D::Matrix3, or + your own classes. + + To provide shortest-path interpolation, subclass G3D::Spline and + override ensureShortestPath(). To provide normalization of + interpolated points (e.g., projecting Quats onto the unit + hypersphere) override correct(). + + See Real Time Rendering, 2nd edition, ch 12 for a general discussion + of splines and their properties. + + @sa G3D::UprightSpline, G3D::QuatSpline + */ +template +class Spline : public SplineBase { +protected: + /** The additive identity control point. */ + Control zero; + +public: + + /** Control points. Must have the same number of elements as + Spline::time.*/ + Array control; + + Spline() { + static Control x; + // Hide the fact from C++ that we are using an + // uninitialized variable here by pointer arithmetic. + // This is ok because any type that is a legal control + // point also supports multiplication by float. + zero = *(&x) * 0.0f; + } + + /** Appends a control point at a specific time that must be + greater than that of the previous point. */ + void append(float t, const Control& c) { + debugAssertM((time.size() == 0) || (t > time.last()), + "Control points must have monotonically increasing times."); + time.append(t); + control.append(c); + debugAssert(control.size() == time.size()); + } + + + /** Appends control point spaced in time based on the previous + control point, or spaced at unit intervals if this is the + first control point. */ + void append(const Control& c) { + switch (time.size()) { + case 0: + append(0, c); + break; + + case 1: + if (time[0] == 0) { + append(1, c); + } else { + append(time[0], c); + } + break; + + default: + append(2 * time[time.size() - 1] - time[time.size() - 2], c); + } + debugAssert(control.size() == time.size()); + } + + /** Erases all control points and times, but retains the state of + cyclic and finalInterval. + */ + void clear() { + control.clear(); + time.clear(); + } + + + /** Number of control points */ + int size() const { + debugAssert(time.size() == control.size()); + return control.size(); + } + + + /** Returns the requested control point and time sample based on + array index. If the array index is out of bounds, wraps (for + a cyclic spline) or linearly extrapolates (for a non-cyclic + spline), assuming time intervals follow the first or last + sample recorded. + + Calls correct() on the control point if it was extrapolated. + + Returns 0 if there are no control points. + + @sa Spline::control and Spline::time for the underlying + control point array; Spline::computeIndex to find the index + given a time. + */ + void getControl(int i, float& t, Control& c) const { + int N = control.size(); + if (N == 0) { + c = zero; + t = 0; + } else if (cyclic) { + c = control[iWrap(i, N)]; + + if (i < 0) { + // Wrapped around bottom + + // Number of times we wrapped around the cyclic array + int wraps = (N + 1 - i) / N; + int j = (i + wraps * N) % N; + t = time[j] - wraps * duration(); + + } else if (i < N) { + + t = time[i]; + + } else { + // Wrapped around top + + // Number of times we wrapped around the cyclic array + int wraps = i / N; + int j = i % N; + t = time[j] + wraps * duration(); + } + + } else if (i < 0) { + // Are there enough points to extrapolate? + if (N >= 2) { + // Step away from control point 0 + float dt = time[1] - time[0]; + + // Extrapolate (note; i is negative) + c = control[1] * float(i) + control[0] * float(1 - i); + correct(c); + t = dt * i + time[0]; + + } else { + // Just clamp + c = control[0]; + + // Only 1 time; assume 1s intervals + t = time[0] + i; + } + + } else if (i >= N) { + if (N >= 2) { + float dt = time[N - 1] - time[N - 2]; + + // Extrapolate + c = control[N - 1] * float(i - N + 2) + control[N - 2] * -float(i - N + 1); + correct(c); + t = time[N - 1] + dt * (i - N + 1); + + } else { + // Return the last, clamping + c = control.last(); + // Only 1 time; assume 1s intervals + t = time[0] + i; + } + } else { + // In bounds + c = control[i]; + t = time[i]; + } + } + +protected: + + /** Returns a series of N control points and times, fixing + boundary issues. The indices may be assumed to be treated + cyclically. */ + void getControls(int i, float* T, Control* A, int N) const { + for (int j = 0; j < N; ++j) { + getControl(i + j, T[j], A[j]); + } + ensureShortestPath(A, N); + } + + /** + Mutates the array of N control points. It is useful to override this + method by one that wraps the values if they are angles or quaternions + for which "shortest path" interpolation is significant. + */ + virtual void ensureShortestPath(Control* A, int N) const { (void)A; (void) N;} + + /** Normalize or otherwise adjust this interpolated Control. */ + virtual void correct(Control& A) const { (void)A; } + +public: + + + /** + Return the position at time s. The spline is defined outside + of the time samples by extrapolation or cycling. + */ + Control evaluate(float s) const { + debugAssertM(control.size() == time.size(), "Corrupt spline: wrong number of control points."); + + /* + @cite http://www.gamedev.net/reference/articles/article1497.asp + Derivation of basis matrix follows. + + Given control points with positions p[i] at times t[i], 0 <= i <= 3, find the position + at time t[1] <= s <= t[2]. + + Let u = s - t[0] + Let U = [u^0 u^1 u^2 u^3] = [1 u u^2 u^3] + Let dt0 = t[0] - t[-1] + Let dt1 = t[1] - t[0] + Let dt2 = t[2] - t[1] + */ + + // Index of the first control point (i.e., the u = 0 point) + int i = 0; + // Fractional part of the time + float u = 0; + + computeIndex(s, i, u); + + Control p[4]; + float t[4]; + getControls(i - 1, t, p, 4); + float dt0 = t[1] - t[0]; + float dt1 = t[2] - t[1]; + float dt2 = t[3] - t[2]; + + static const Matrix4 basis = computeBasis(); + + // Powers of u + Vector4 uvec((float)(u*u*u), (float)(u*u), (float)u, 1.0f); + + // Compute the weights on each of the control points. + const Vector4& weights = uvec * basis; + + // Compute the weighted sum of the neighboring control points. + Control sum; + + const Control& p0 = p[0]; + const Control& p1 = p[1]; + const Control& p2 = p[2]; + const Control& p3 = p[3]; + + const Control& dp0 = p1 + (p0*-1.0f); + const Control& dp1 = p2 + (p1*-1.0f); + const Control& dp2 = p3 + (p2*-1.0f); + + // The factor of 1/2 from averaging two time intervals is + // already factored into the basis + + // tan1 = (dp0 / dt0 + dp1 / dt1) * ((dt0 + dt1) * 0.5); + // The last term normalizes for unequal time intervals + float x = (dt0 + dt1) * 0.5f; + float n0 = x / dt0; + float n1 = x / dt1; + float n2 = x / dt2; + const Control& dp1n1 = dp1 * n1; + const Control& tan1 = dp0 * n0 + dp1n1; + const Control& tan2 = dp1n1 + dp2 * n2; + + sum = + tan1 * weights[0]+ + p1 * weights[1] + + p2 * weights[2] + + tan2 * weights[3]; + + + correct(sum); + return sum; + } +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/Stopwatch.h b/externals/g3dlite/G3D/Stopwatch.h new file mode 100644 index 00000000000..3f2aa9c8d86 --- /dev/null +++ b/externals/g3dlite/G3D/Stopwatch.h @@ -0,0 +1,144 @@ +/** + @file Stopwatch.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2005-10-05 + @edited 2009-05-10 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_Stopwatch_h +#define G3D_Stopwatch_h + +#include "G3D/platform.h" +#include "G3D/Queue.h" +#include "G3D/G3DGameUnits.h" +#include "G3D/g3dmath.h" + +namespace G3D { + +/** + \brief Accurately measure durations and framerates. + + Example 1: For profiling code in the context of a rendering loop: +
+      sw.tick();
+      ...timed code...
+      sw.tock();
+
+      screenPrintf("%f\n", sw.smoothFPS());
+    
+ + + Example 2: For profiling pieces of a sequence: +
+    Stopwatch sw;
+    slowOperation();
+    sw.after("slowOperation");
+    kdTree.balance();
+    sw.after("Balance tree");
+   
+ */ +class Stopwatch { +private: + + std::string myName; + double startTime; + std::string prevMark; + double prevTime; + + /** True between tick and tock */ + bool inBetween; + + /** The initial cycle count. */ + uint64 cycleStart; + + /** The time at which tick was called. */ + RealTime timeStart; + + /** The time at which the previous tock was called, -1 if never. */ + RealTime lastTockTime; + + RealTime lastDuration; + int64 lastCycleCount; + + /** Frames per second. */ + double m_fps; + + /** Weighted fps */ + double emwaFPS; + double m_smoothFPS; + + /** Weighted duration */ + RealTime emwaDuration; + + /** The overhead for calling into the class. */ + int64 cycleOverhead; + + /** Called from the constructor. */ + void computeOverhead(); + +public: + + Stopwatch(const std::string& name = "Stopwatch"); + + /** Returns the number of times that tick was called per wall-clock second; + e.g. frames-per-second. */ + double FPS() const { + return m_fps; + } + + /** Amount of time between the most recent tick and tock calls. 0 if tick has + never been called. */ + RealTime elapsedTime() const { + return lastDuration; + } + + /** Time-smoothed value that is stable to the nearest 1%. + This is useful if you are displaying elapsed time in real-time + and want a stable number.*/ + RealTime smoothElapsedTime() const { + return emwaDuration; + } + + /** Time-smoothed value of fps that is stable to the nearest integer for fps > 10 and + to the first decimal place for fps <= 10. + This is useful if you + are displaying the frame rate in real-time and want a stable (readable) number.*/ + double smoothFPS() const { + return m_smoothFPS; + } + + /** The elapsed cycle time between tick and tock. An attempt is made to factor out all + tick/tock overhead, so that back-to-back calls should return zero. + Unreliable on non-x86 platforms.*/ + uint64 elapsedCycles() const { + return lastCycleCount; + } + + /** Call at the beginning of the period that you want timed. */ + void tick(); + + /** Call at the end of the period that you want timed. */ + void tock(); + + + /** Reset the start time used by after() and the emwa value.*/ + void reset(); + + /** Call after an operation has completed, with the name of the operation, to + print a debug message listing the time since the previous after() call. */ + void after(const std::string& s = ""); + +}; + +/** Because it is hard to remember the proper capitalization. */ +typedef Stopwatch StopWatch; + +} + +#endif + diff --git a/externals/g3dlite/G3D/System.h b/externals/g3dlite/G3D/System.h new file mode 100644 index 00000000000..56ef9c8e3dc --- /dev/null +++ b/externals/g3dlite/G3D/System.h @@ -0,0 +1,507 @@ +/** + @file System.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @cite Rob Wyatt http://www.gamasutra.com/features/wyatts_world/19990709/processor_detection_01.htm + @cite Benjamin Jurke http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-ProcessorDetectionClass&forum=cotd&id=-1 + @cite Michael Herf http://www.stereopsis.com/memcpy.html + + @created 2003-01-25 + @edited 2008-10-14 + */ + +#ifndef G3D_System_h +#define G3D_System_h + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/G3DGameUnits.h" +#include "G3D/BinaryFormat.h" +#include + +#ifdef G3D_OSX +# include +#endif + +namespace G3D { + +/** + Routine used by the demos to find the data. Searches in + ../data, ../../data, etc. up to 5 levels back. Checks + common locations like \verbatim c:\libraries\g3d-\data \endverbatim + and some hard-coded paths on the Brown University file + system. + + @deprecated + */ +std::string demoFindData(bool errorIfNotFound = true); + +/** G3D, SDL, and IJG libraries require license documentation + to be distributed with your program. This generates the + string that must appear in your documentation. + Your program can be commercial, closed-source under + any license you want. + @deprecated Use System::license +*/ +std::string license(); + +/** +@brief The order in which the bytes of an integer are stored on a +machine. + +Intel/AMD chips tend to be G3D_LITTLE_ENDIAN, Mac PPC's and Suns are +G3D_BIG_ENDIAN. However, this is primarily used to specify the byte +order of file formats, which are fixed. +*/ +enum G3DEndian { + G3D_BIG_ENDIAN, + G3D_LITTLE_ENDIAN +}; + +/** + @brief OS and processor abstraction. + + The first time any method is called the processor will be analyzed. + Future calls are then fast. + + Timing function overview: + System::getCycleCount + - actual cycle count + + System::getTick + - High-resolution time in seconds since program started + + System::getLocalTime + - High-resolution time in seconds since Jan 1, 1970 + (because it is stored in a double, this may be less + accurate than getTick) + */ +class System { +public: + /** + @param size Size of memory that the system was trying to allocate + + @param recoverable If true, the system will attempt to allocate again + if the callback returns true. If false, malloc is going to return + NULL and this invocation is just to notify the application. + + @return Return true to force malloc to attempt allocation again if the + error was recoverable. + */ + typedef bool (*OutOfMemoryCallback)(size_t size, bool recoverable); + +private: + + bool m_initialized; + int m_cpuSpeed; + bool m_hasCPUID; + bool m_hasRDTSC; + bool m_hasMMX; + bool m_hasSSE; + bool m_hasSSE2; + bool m_hasSSE3; + bool m_has3DNOW; + bool m_has3DNOW2; + bool m_hasAMDMMX; + std::string m_cpuVendor; + int m_numCores; + + /** this holds the data directory set by the application (currently + GApp) for use by findDataFile */ + std::string m_appDataDir; + + G3DEndian m_machineEndian; + std::string m_cpuArch; + std::string m_operatingSystem; + +# ifdef G3D_WIN32 + /** Used by getTick() for timing */ + LARGE_INTEGER m_start; + LARGE_INTEGER m_counterFrequency; +#else + struct timeval m_start; +#endif + + std::string m_version; + OutOfMemoryCallback m_outOfMemoryCallback; + +#ifdef G3D_OSX + /** In Cycles/Second */ + SInt32 m_OSXCPUSpeed; + double m_secondsPerNS; +#endif + + /** The Real-World time of System::getTick() time 0. Set by initTime */ + RealTime m_realWorldGetTickTime0; + + uint32 m_highestCPUIDFunction; + + /** @brief Used for the singleton instance only. */ + System(); + + /** @brief The singleton instance. + + Used instead of a global variable to ensure that the order of + intialization is correct, which is critical because other + globals may allocate memory using System::malloc. + */ + static System& instance(); + + enum CPUIDFunction { + CPUID_VENDOR_ID = 0x00000000, + CPUID_PROCESSOR_FEATURES = 0x00000001, + CPUID_NUM_CORES = 0x00000004, + CPUID_GET_HIGHEST_FUNCTION = 0x80000000, + CPUID_EXTENDED_FEATURES = 0x80000001}; + + /** Helper macro to call cpuid functions and return all values + + See http://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/ + or http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf + + for description of the arguments. + */ + static void cpuid(CPUIDFunction func, uint32& areg, uint32& breg, uint32& creg, uint32& dreg); + + void init(); + + /** Called from init() */ + void getStandardProcessorExtensions(); + + /** Called from init() */ + void initTime(); + +public: + + /** Returns the speed of processor 0 in MHz. + Always returns 0 on linux.*/ + inline static int cpuSpeedMHz() { + return instance().m_cpuSpeed; + } + + /** Returns the number of logical processor cores (i.e., the + number of execution units for threads) */ + inline static int numCores() { + return instance().m_numCores; + } + + inline static bool hasCPUID() { + return instance().m_hasCPUID; + } + + inline static bool hasRDTSC() { + return instance().m_hasRDTSC; + } + + inline static bool hasSSE() { + return instance().m_hasSSE; + } + + inline static bool hasSSE2() { + return instance().m_hasSSE2; + } + + inline static bool hasSSE3() { + return instance().m_hasSSE3; + } + + inline static bool hasMMX() { + return instance().m_hasMMX; + } + + inline static bool has3DNow() { + return instance().m_has3DNOW; + } + + inline static const std::string& cpuVendor() { + return instance().m_cpuVendor; + } + + /** + Returns the endianness of this machine. + */ + inline static G3DEndian machineEndian() { + return instance().m_machineEndian; + } + + /** e.g., "Windows", "GNU/Linux" */ + inline static const std::string& operatingSystem() { + return instance().m_operatingSystem; + } + + /** e.g., 80686 */ + inline static const std::string& cpuArchitecture() { + return instance().m_cpuArch; + } + + /** + Returns the current date as a string in the form YYYY-MM-DD + */ + static std::string currentDateString(); + + /** + Guarantees that the start of the array is aligned to the + specified number of bytes. + */ + static void* alignedMalloc(size_t bytes, size_t alignment); + + /** + Uses pooled storage to optimize small allocations (1 byte to 5 + kilobytes). Can be 10x to 100x faster than calling ::malloc or + new. + + The result must be freed with free. + + Threadsafe on Win32. + + @sa calloc realloc OutOfMemoryCallback free + */ + static void* malloc(size_t bytes); + + static void* calloc(size_t n, size_t x); + + /** + Version of realloc that works with System::malloc. + */ + static void* realloc(void* block, size_t bytes); + + /** Returns a string describing how well System::malloc is using + its internal pooled storage. "heap" memory was slow to + allocate; the other data sizes are comparatively fast.*/ + static std::string mallocPerformance(); + static void resetMallocPerformanceCounters(); + + /** + Returns a string describing the current usage of the buffer pools used for + optimizing System::malloc. + */ + static std::string mallocStatus(); + + /** + Free data allocated with System::malloc. + + Threadsafe on Win32. + */ + static void free(void* p); + + /** + Frees memory allocated with alignedMalloc. + */ + static void alignedFree(void* ptr); + + /** An implementation of memcpy that may be up to 2x as fast as the C library + one on some processors. Guaranteed to have the same behavior as memcpy + in all cases. */ + static void memcpy(void* dst, const void* src, size_t numBytes); + + /** An implementation of memset that may be up to 2x as fast as the C library + one on some processors. Guaranteed to have the same behavior as memset + in all cases. */ + static void memset(void* dst, uint8 value, size_t numBytes); + + /** + Returns the fully qualified filename for the currently running executable. + + This is more reliable than arg[0], which may be intentionally set + to an incorrect value by a calling program, relative to a now + non-current directory, or obfuscated by sym-links. + + @cite Linux version written by Nicolai Haehnle , http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-getexename&forum=cotd&id=-1 + */ + static std::string currentProgramFilename(); + + /** Name of this program. Note that you can mutate this string to + set your app name explicitly.*/ + static std::string& appName(); + + /** G3D Version string */ + inline static const std::string& version() { + return instance().m_version; + } + + /** + @brief The optimization status of the G3D library (not the program compiled against it) + + Either "Debug" or "Release", depending on whether _DEBUG was + defined at compile-time for the library. + */ + static const std::string& build(); + + /** + Causes the current thread to yield for the specified duration + and consume almost no CPU. + The sleep will be extremely precise; it uses System::time() + to calibrate the exact yeild time. + */ + static void sleep(RealTime t); + + /** + Clears the console. + Console programs only. + */ + static void consoleClearScreen(); + + /** + Returns true if a key is waiting. + Console programs only. + */ + static bool consoleKeyPressed(); + + /** + Blocks until a key is read (use consoleKeyPressed to determine if + a key is waiting to be read) then returns the character code for + that key. + */ + static int consoleReadKey(); + + /** + The actual time (measured in seconds since + Jan 1 1970 midnight). + + Adjusted for local timezone and daylight savings + time. This is as accurate and fast as getCycleCount(). + */ + static RealTime time(); + + /** + To count the number of cycles a given operation takes: + +
+     unsigned long count;
+     System::beginCycleCount(count);
+     ...
+     System::endCycleCount(count);
+     // count now contains the cycle count for the intervening operation.
+     
+ */ + /* static void beginCycleCount(uint64& cycleCount); + static void endCycleCount(uint64& cycleCount); + + static uint64 getCycleCount(); */ + + inline static void setOutOfMemoryCallback(OutOfMemoryCallback c) { + instance().m_outOfMemoryCallback = c; + } + + /** + When System::malloc fails to allocate memory because the system is + out of memory, it invokes this handler (if it is not NULL). + The argument to the callback is the amount of memory that malloc + was trying to allocate when it ran out. If the callback returns + true, System::malloc will attempt to allocate the memory again. + If the callback returns false, then System::malloc will return NULL. + + You can use outOfMemoryCallback to free data structures or to + register the failure. + */ + inline static OutOfMemoryCallback outOfMemoryCallback() { + return instance().m_outOfMemoryCallback; + } + + /** Set an environment variable for the current process */ + static void setEnv(const std::string& name, const std::string& value); + + /** Get an environment variable for the current process. Returns NULL if the variable doesn't exist. */ + static const char* getEnv(const std::string& name); + + /** + Prints a human-readable description of this machine + to the text output stream. Either argument may be NULL. + */ + static void describeSystem( + class TextOutput& t); + + static void describeSystem( + std::string& s); + + /** On Win32, returns the clipboard text contents. Does nothing on other + platforms (yet) */ + static std::string getClipboardText(); + + /** Copies the text to the clipboard on Win32. */ + static void setClipboardText(const std::string& s); + + /** + Tries to locate the resource by looking in related directories. + If found, returns the full path to the resource, otherwise + returns the empty string. + */ + static std::string findDataFile(const std::string& full, bool errorIfNotFound = true); + + /** + Sets the path that the application is using as its data directory. + Used by findDataDir as an initial search location. GApp sets this + upon constrution. + */ + static void setAppDataDir(const std::string& path); + +}; + +/* don't need that for MaNGOS, not portable to Win64... +#ifdef _MSC_VER + inline uint64 System::getCycleCount() { + uint32 timehi, timelo; + + // Use the assembly instruction rdtsc, which gets the current + // cycle count (since the process started) and puts it in edx:eax. + __asm + { + rdtsc; + mov timehi, edx; + mov timelo, eax; + } + + return ((uint64)timehi << 32) + (uint64)timelo; + } + +#elif defined(G3D_LINUX) + + inline uint64 System::getCycleCount() { + uint32 timehi, timelo; + + __asm__ __volatile__ ( + "rdtsc " + : "=a" (timelo), + "=d" (timehi) + : ); + + return ((uint64)timehi << 32) + (uint64)timelo; + } + +#elif defined(G3D_OSX) + + inline uint64 System::getCycleCount() { + //Note: To put off extra processing until the end, this does not + //return the actual clock cycle count. It is a bus cycle count. + //When endCycleCount() is called, it converts the two into a difference + //of clock cycles + + return (uint64) UnsignedWideToUInt64(UpTime()); + //return (uint64) mach_absolute_time(); + } + +#endif + +inline void System::beginCycleCount(uint64& cycleCount) { + cycleCount = getCycleCount(); +} + + +inline void System::endCycleCount(uint64& cycleCount) { +#ifndef G3D_OSX + cycleCount = getCycleCount() - cycleCount; +#else + AbsoluteTime end = UpTime(); + Nanoseconds diffNS = + AbsoluteDeltaToNanoseconds(end, UInt64ToUnsignedWide(cycleCount)); + cycleCount = + (uint64) ((double) (instance().m_OSXCPUSpeed) * + (double) UnsignedWideToUInt64(diffNS) * instance().m_secondsPerNS); +#endif +} + */ + +} // namespace + +#endif diff --git a/externals/g3dlite/G3D/Table.h b/externals/g3dlite/G3D/Table.h new file mode 100644 index 00000000000..287efa94d97 --- /dev/null +++ b/externals/g3dlite/G3D/Table.h @@ -0,0 +1,924 @@ +/** + @file Table.h + + Templated hash table class. + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @created 2001-04-22 + @edited 2010-01-28 + Copyright 2000-2010, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_Table_h +#define G3D_Table_h + +#include +#include + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/debug.h" +#include "G3D/System.h" +#include "G3D/g3dmath.h" +#include "G3D/EqualsTrait.h" +#include "G3D/HashTrait.h" +#include "G3D/MemoryManager.h" + +#ifdef _MSC_VER +# pragma warning (push) + // Debug name too long warning +# pragma warning (disable : 4786) +#endif + +namespace G3D { + +/** + An unordered data structure mapping keys to values. + + There are two ways of definining custom hash functions (G3D provides built-in ones for most classes): + +
+ class Foo {
+ public:
+     std::string     name;
+     int             index;
+     static size_t hashCode(const Foo& key) {
+          return HashTrait::hashCode(key.name) + key.index;
+     }
+  };
+
+  template<> struct HashTrait {
+       static size_t hashCode(const Foo& key) { return HashTrait::hashCode(key.name) + key.index; }
+  }; 
+
+
+  // Use Foo::hashCode
+  Table fooTable1;
+
+  // Use HashTrait
+  Table      fooTable2;
+  
+ + + Key must be a pointer, an int, a std::string or provide overloads for: + +
+    template<> struct HashTrait {
+        static size_t hashCode(const Key& key) { return reinterpret_cast( ... ); }
+    }; 
+  
+ + and one of + +
+    template<> struct EqualsTrait{
+         static bool equals(const Key& a, const Key& b) { return ... ; }
+    };
+
+
+    bool operator==(const Key&, const Key&);
+  
+ + G3D pre-defines HashTrait specializations for common types (like int and std::string). + If you use a Table with a different type you must write those functions yourself. For example, + an enum would use: + +
+    template<> struct HashTrait {
+        static size_t equals(const MyEnum& key) const { return reinterpret_cast( key ); }
+    };
+  
+ + And rely on the default enum operator==. + + + Periodically check that debugGetLoad() is low (> 0.1). When it gets near + 1.0 your hash function is badly designed and maps too many inputs to + the same output. + */ +template, class EqualsFunc = EqualsTrait > +class Table { +public: + + /** + The pairs returned by iterator. + */ + class Entry { + public: + Key key; + Value value; + Entry() {} + Entry(const Key& k) : key(k) {} + Entry(const Key& k, const Value& v) : key(k), value(v) {} + bool operator==(const Entry &peer) const { return (key == peer.key && value == peer.value); } + bool operator!=(const Entry &peer) const { return !operator==(peer); } + }; + +private: + + typedef Table ThisType; + + /** + Linked list nodes used internally by HashTable. + */ + class Node { + public: + Entry entry; + size_t hashCode; + Node* next; + + private: + + // Private to require use of the allocator + Node(const Key& k, const Value& v, size_t h, Node* n) + : entry(k, v), hashCode(h), next(n) { + } + + Node(const Key& k, size_t h, Node* n) + : entry(k), hashCode(h), next(n) { + } + + public: + + static Node* create(const Key& k, const Value& v, size_t h, Node* n, MemoryManager::Ref& mm) { + Node* node = (Node*)mm->alloc(sizeof(Node)); + return new (node) Node(k, v, h, n); + } + + static Node* create(const Key& k, size_t hashCode, Node* n, MemoryManager::Ref& mm) { + Node* node = (Node*)mm->alloc(sizeof(Node)); + return new (node) Node(k, hashCode, n); + } + + static void destroy(Node* n, MemoryManager::Ref& mm) { + n->~Node(); + mm->free(n); + } + + /** + Clones a whole chain; + */ + Node* clone(MemoryManager::Ref& mm) { + return create(this->entry.key, this->entry.value, hashCode, (next == NULL) ? NULL : next->clone(mm), mm); + } + }; + + void checkIntegrity() const { +# ifdef G3D_DEBUG + debugAssert(m_bucket == NULL || isValidHeapPointer(m_bucket)); + for (size_t b = 0; b < m_numBuckets; ++b) { + Node* node = m_bucket[b]; + debugAssert(node == NULL || isValidHeapPointer(node)); + while (node != NULL) { + debugAssert(node == NULL || isValidHeapPointer(node)); + node = node->next; + } + } +# endif + } + + /** Number of elements in the table.*/ + size_t m_size; + + /** + Array of Node*. + + We don't use Array because Table is lower-level than Array. + Some elements may be NULL. + */ + Node** m_bucket; + + /** + Length of the m_bucket array. + */ + size_t m_numBuckets; + + MemoryManager::Ref m_memoryManager; + + void* alloc(size_t s) const { + return m_memoryManager->alloc(s); + } + + void free(void* p) const { + return m_memoryManager->free(p); + } + + /** + Re-hashes for a larger m_bucket size. + */ + void resize(size_t newSize) { + + // Hang onto the old m_bucket array + Node** oldBucket = m_bucket; + + // Allocate a new m_bucket array with the new size + m_bucket = (Node**)alloc(sizeof(Node*) * newSize); + // Set all pointers to NULL + System::memset(m_bucket, 0, newSize * sizeof(Node*)); + debugAssertM(m_bucket != NULL, "MemoryManager::alloc returned NULL. Out of memory."); + // Move each node to its new hash location + for (size_t b = 0; b < m_numBuckets; ++b) { + Node* node = oldBucket[b]; + + // There is a linked list of nodes at this m_bucket + while (node != NULL) { + // Hang onto the old next pointer + Node* nextNode = node->next; + + // Insert at the head of the list for m_bucket[i] + size_t i = node->hashCode % newSize; + node->next = m_bucket[i]; + m_bucket[i] = node; + + // Move on to the next node + node = nextNode; + } + + // Drop the old pointer for cleanliness when debugging + oldBucket[b] = NULL; + } + + // Delete the old storage + free(oldBucket); + this->m_numBuckets = newSize; + + checkIntegrity(); + } + + + void copyFrom(const ThisType& h) { + if (&h == this) { + return; + } + + debugAssert(m_bucket == NULL); + m_size = h.m_size; + m_numBuckets = h.m_numBuckets; + m_bucket = (Node**)alloc(sizeof(Node*) * m_numBuckets); + // No need to NULL elements since we're about to overwrite them + + for (size_t b = 0; b < m_numBuckets; ++b) { + if (h.m_bucket[b] != NULL) { + m_bucket[b] = h.m_bucket[b]->clone(m_memoryManager); + } else { + m_bucket[b] = NULL; + } + } + + checkIntegrity(); + } + + /** + Frees the heap structures for the nodes. + */ + void freeMemory() { + checkIntegrity(); + + for (size_t b = 0; b < m_numBuckets; b++) { + Node* node = m_bucket[b]; + while (node != NULL) { + Node* next = node->next; + Node::destroy(node, m_memoryManager); + node = next; + } + m_bucket[b] = NULL; + } + free(m_bucket); + m_bucket = NULL; + m_numBuckets = 0; + m_size = 0; + } + +public: + + /** + Creates an empty hash table using the default MemoryManager. + */ + Table() : m_bucket(NULL) { + m_memoryManager = MemoryManager::create(); + m_numBuckets = 0; + m_size = 0; + m_bucket = NULL; + checkIntegrity(); + } + + /** Changes the internal memory manager to m */ + void clearAndSetMemoryManager(const MemoryManager::Ref& m) { + clear(); + debugAssert(m_bucket == NULL); + m_memoryManager = m; + } + + /** + Recommends that the table resize to anticipate at least this number of elements. + */ + void setSizeHint(size_t n) { + size_t s = n * 3; + if (s > m_numBuckets) { + resize(s); + } + } + + /** + Destroys all of the memory allocated by the table, but does not + call delete on keys or values if they are pointers. If you want to + deallocate things that the table points at, use getKeys() and Array::deleteAll() + to delete them. + */ + virtual ~Table() { + freeMemory(); + } + + /** Uses the default memory manager */ + Table(const ThisType& h) { + m_memoryManager = MemoryManager::create(); + m_numBuckets = 0; + m_size = 0; + m_bucket = NULL; + this->copyFrom(h); + checkIntegrity(); + } + + + Table& operator=(const ThisType& h) { + // No need to copy if the argument is this + if (this != &h) { + // Free the existing nodes + freeMemory(); + this->copyFrom(h); + checkIntegrity(); + } + return *this; + } + + /** + Returns the length of the deepest m_bucket. + */ + size_t debugGetDeepestBucketSize() const { + size_t deepest = 0; + + for (size_t b = 0; b < m_numBuckets; b++) { + size_t count = 0; + Node* node = m_bucket[b]; + while (node != NULL) { + node = node->next; + ++count; + } + + if (count > deepest) { + deepest = count; + } + } + + return deepest; + } + + /** + Returns the average size of non-empty buckets. + */ + float debugGetAverageBucketSize() const { + size_t num = 0; + size_t count = 0; + + for (size_t b = 0; b < m_numBuckets; b++) { + Node* node = m_bucket[b]; + if (node != NULL) { + ++num; + while (node != NULL) { + node = node->next; + ++count; + } + } + } + + return (float)((double)count / num); + } + + /** + A small load (close to zero) means the hash table is acting very + efficiently most of the time. A large load (close to 1) means + the hash table is acting poorly-- all operations will be very slow. + A large load will result from a bad hash function that maps too + many keys to the same code. + */ + double debugGetLoad() const { + return debugGetDeepestBucketSize() / (double)size(); + } + + /** + Returns the number of buckets. + */ + size_t debugGetNumBuckets() const { + return m_numBuckets; + } + + /** + C++ STL style iterator variable. See begin(). + */ + class Iterator { + private: + friend class Table; + + /** + Bucket index. + */ + size_t index; + + /** + Linked list node. + */ + Node* node; + ThisType* table; + size_t m_numBuckets; + Node** m_bucket; + bool isDone; + + /** + Creates the end iterator. + */ + Iterator(const ThisType* table) : table(const_cast(table)) { + isDone = true; + } + + Iterator(const ThisType* table, size_t m_numBuckets, Node** m_bucket) : + table(const_cast(table)), + m_numBuckets(m_numBuckets), + m_bucket(m_bucket) { + + if (m_numBuckets == 0) { + // Empty table + isDone = true; + return; + } + + index = 0; + node = m_bucket[index]; + isDone = false; + findNext(); + } + + /** + Finds the next element, setting isDone if one can't be found. + Looks at the current element first. + */ + void findNext() { + while (node == NULL) { + index++; + if (index >= m_numBuckets) { + isDone = true; + break; + } else { + node = m_bucket[index]; + } + } + } + + public: + inline bool operator!=(const Iterator& other) const { + return !(*this == other); + } + + bool operator==(const Iterator& other) const { + if (other.isDone || isDone) { + // Common case; check against isDone. + return (isDone == other.isDone) && (other.table == table); + } else { + return + (table == other.table) && + (node == other.node) && + (index == other.index); + } + } + + /** + Pre increment. + */ + Iterator& operator++() { + node = node->next; + findNext(); + return *this; + } + + /** + Post increment (slower than preincrement). + */ + Iterator operator++(int) { + Iterator old = *this; + ++(*this); + return old; + } + + const Entry& operator*() const { + return node->entry; + } + + Entry* operator->() const { + return &(node->entry); + } + + operator Entry*() const { + return &(node->entry); + } + + bool hasMore() const { + return ! isDone; + } + }; + + + /** + C++ STL style iterator method. Returns the first Entry, which + contains a key and value. Use preincrement (++entry) to get to + the next element. Do not modify the table while iterating. + */ + Iterator begin() const { + return Iterator(this, m_numBuckets, m_bucket); + } + + /** + C++ STL style iterator method. Returns one after the last iterator + element. + */ + const Iterator end() const { + return Iterator(this); + } + + /** + Removes all elements + */ + void clear() { + freeMemory(); + m_numBuckets = 0; + m_size = 0; + m_bucket = NULL; + } + + + /** + Returns the number of keys. + */ + size_t size() const { + return m_size; + } + + + /** + If you insert a pointer into the key or value of a table, you are + responsible for deallocating the object eventually. Inserting + key into a table is O(1), but may cause a potentially slow rehashing. + */ + void set(const Key& key, const Value& value) { + getCreateEntry(key).value = value; + } + +private: + + /** Helper for remove() and getRemove() */ + bool remove(const Key& key, Key& removedKey, Value& removedValue, bool updateRemoved) { + if (m_numBuckets == 0) { + return false; + } + size_t code = HashFunc::hashCode(key); + size_t b = code % m_numBuckets; + + // Go to the m_bucket + Node* n = m_bucket[b]; + + if (n == NULL) { + return false; + } + + Node* previous = NULL; + + // Try to find the node + do { + if ((code == n->hashCode) && EqualsFunc::equals(n->entry.key, key)) { + // This is the node; remove it + + // Replace the previous's next pointer + if (previous == NULL) { + m_bucket[b] = n->next; + } else { + previous->next = n->next; + } + + if (updateRemoved) { + removedKey = n->entry.key; + removedValue = n->entry.value; + } + // Delete the node + Node::destroy(n, m_memoryManager); + --m_size; + return true; + } + + previous = n; + n = n->next; + } while (n != NULL); + + return false; + //alwaysAssertM(false, "Tried to remove a key that was not in the table."); + } + +public: + + /** If @a member is present, sets @a removed to the element + being removed and returns true. Otherwise returns false + and does not write to @a removed. */ + bool getRemove(const Key& key, Key& removedKey, Value& removedValue) { + return remove(key, removedKey, removedValue, true); + } + + /** + Removes an element from the table if it is present. + @return true if the element was found and removed, otherwise false + */ + bool remove(const Key& key) { + Key x; + Value v; + return remove(key, x, v, false); + } + +private: + + Entry* getEntryPointer(const Key& key) const { + if (m_numBuckets == 0) { + return NULL; + } + + size_t code = HashFunc::hashCode(key); + size_t b = code % m_numBuckets; + + Node* node = m_bucket[b]; + + while (node != NULL) { + if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) { + return &(node->entry); + } + node = node->next; + } + + return NULL; + } + +public: + + /** If a value that is EqualsFunc to @a member is present, returns a pointer to the + version stored in the data structure, otherwise returns NULL. + */ + const Key* getKeyPointer(const Key& key) const { + const Entry* e = getEntryPointer(key); + if (e == NULL) { + return NULL; + } else { + return &(e->key); + } + } + + /** + Returns the value associated with key. + @deprecated Use get(key, val) or getPointer(key) + */ + Value& get(const Key& key) const { + Entry* e = getEntryPointer(key); + debugAssertM(e != NULL, "Key not found"); + return e->value; + } + + + /** Returns a pointer to the element if it exists, or NULL if it does not. + Note that if your value type is a pointer, the return value is + a pointer to a pointer. Do not remove the element while holding this + pointer. + + It is easy to accidentally mis-use this method. Consider making + a Table and using get(key, val) instead, which makes you manage + the memory for the values yourself and is less likely to result in + pointer errors. + */ + Value* getPointer(const Key& key) const { + if (m_numBuckets == 0) { + return NULL; + } + + size_t code = HashFunc::hashCode(key); + size_t b = code % m_numBuckets; + + Node* node = m_bucket[b]; + + while (node != NULL) { + if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) { + // found key + return &(node->entry.value); + } + node = node->next; + } + + // Failed to find key + return NULL; + } + + /** + If the key is present in the table, val is set to the associated value and returns true. + If the key is not present, returns false. + */ + bool get(const Key& key, Value& val) const { + Value* v = getPointer(key); + if (v != NULL) { + val = *v; + return true; + } else { + return false; + } + } + + + + /** Called by getCreate() and set() + + \param created Set to true if the entry was created by this method. + */ + Entry& getCreateEntry(const Key& key, bool& created) { + created = false; + + if (m_numBuckets == 0) { + resize(10); + } + + size_t code = HashFunc::hashCode(key); + size_t b = code % m_numBuckets; + + // Go to the m_bucket + Node* n = m_bucket[b]; + + // No m_bucket, so this must be the first + if (n == NULL) { + m_bucket[b] = Node::create(key, code, NULL, m_memoryManager); + ++m_size; + created = true; + return m_bucket[b]->entry; + } + + size_t bucketLength = 1; + + // Sometimes a bad hash code will cause all elements + // to collide. Detect this case and don't rehash when + // it occurs; nothing good will come from the rehashing. + bool allSameCode = true; + + // Try to find the node + do { + allSameCode = allSameCode && (code == n->hashCode); + + if ((code == n->hashCode) && EqualsFunc::equals(n->entry.key, key)) { + // This is the a pre-existing node + return n->entry; + } + + n = n->next; + ++bucketLength; + } while (n != NULL); + + const size_t maxBucketLength = 3; + // (Don't bother changing the size of the table if all entries + // have the same hashcode--they'll still collide) + if ((bucketLength > maxBucketLength) && + ! allSameCode && + (m_numBuckets < m_size * 15)) { + + // This m_bucket was really large; rehash if all elements + // don't have the same hashcode the number of buckets is + // reasonable. + + // Back off the scale factor as the number of buckets gets + // large + float f = 3.0f; + if (m_numBuckets > 1000000) { + f = 1.5f; + } else if (m_numBuckets > 100000) { + f = 2.0f; + } + int newSize = iMax((int)(m_numBuckets * f) + 1, (int)(m_size * f)); + resize(newSize); + } + + // Not found; insert at the head. + b = code % m_numBuckets; + m_bucket[b] = Node::create(key, code, m_bucket[b], m_memoryManager); + ++m_size; + created = true; + return m_bucket[b]->entry; + } + + Entry& getCreateEntry(const Key& key) { + bool ignore; + return getCreateEntry(key, ignore); + } + + + /** Returns the current value that key maps to, creating it if necessary.*/ + Value& getCreate(const Key& key) { + return getCreateEntry(key).value; + } + + /** \param created True if the element was created. */ + Value& getCreate(const Key& key, bool& created) { + return getCreateEntry(key, created).value; + } + + + /** + Returns true if key is in the table. + */ + bool containsKey(const Key& key) const { + if (m_numBuckets == 0) { + return false; + } + + size_t code = HashFunc::hashCode(key); + size_t b = code % m_numBuckets; + + Node* node = m_bucket[b]; + + while (node != NULL) { + if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) { + return true; + } + node = node->next; + } while (node != NULL); + + return false; + } + + + /** + Short syntax for get. + */ + inline Value& operator[](const Key &key) const { + return get(key); + } + + /** + Returns an array of all of the keys in the table. + You can iterate over the keys to get the values. + @deprecated + */ + Array getKeys() const { + Array keyArray; + getKeys(keyArray); + return keyArray; + } + + void getKeys(Array& keyArray) const { + keyArray.resize(0, DONT_SHRINK_UNDERLYING_ARRAY); + for (size_t i = 0; i < m_numBuckets; i++) { + Node* node = m_bucket[i]; + while (node != NULL) { + keyArray.append(node->entry.key); + node = node->next; + } + } + } + + /** + Calls delete on all of the keys and then clears the table. + */ + void deleteKeys() { + for (size_t i = 0; i < m_numBuckets; i++) { + Node* node = m_bucket[i]; + while (node != NULL) { + delete node->entry.key; + node = node->next; + } + } + clear(); + } + + /** + Calls delete on all of the values. This is unsafe-- + do not call unless you know that each value appears + at most once. + + Does not clear the table, so you are left with a table + of NULL pointers. + */ + void deleteValues() { + for (size_t i = 0; i < m_numBuckets; ++i) { + Node* node = m_bucket[i]; + while (node != NULL) { + delete node->entry.value; + node->entry.value = NULL; + node = node->next; + } + } + } +}; + +} // namespace + +#ifdef _MSC_VER +# pragma warning (pop) +#endif + +#endif diff --git a/externals/g3dlite/G3D/TextInput.h b/externals/g3dlite/G3D/TextInput.h new file mode 100644 index 00000000000..33eb8c48e53 --- /dev/null +++ b/externals/g3dlite/G3D/TextInput.h @@ -0,0 +1,801 @@ +/** + @file TextInput.h + + Simple text lexer/tokenizer. + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @cite Based on a lexer written by Aaron Orenstein. + + @created 2002-11-27 + @edited 2009-11-24 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_TextInput_h +#define G3D_TextInput_h + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/Set.h" +#include "G3D/ParseError.h" +#include +#include +#include +#include + +namespace G3D { + +/** + For use with TextInput. + */ +class Token { +public: + + /** + More detailed type information than Type. + */ + enum ExtendedType { + DOUBLE_QUOTED_TYPE, + SINGLE_QUOTED_TYPE, + SYMBOL_TYPE, + FLOATING_POINT_TYPE, + INTEGER_TYPE, + BOOLEAN_TYPE, + LINE_COMMENT_TYPE, + BLOCK_COMMENT_TYPE, + NEWLINE_TYPE, + END_TYPE + }; + + /** + Strings are enclosed in quotes, symbols are not. + */ + enum Type { + STRING = DOUBLE_QUOTED_TYPE, + SYMBOL = SYMBOL_TYPE, + NUMBER = FLOATING_POINT_TYPE, + BOOLEAN = BOOLEAN_TYPE, + COMMENT = LINE_COMMENT_TYPE, + NEWLINE = NEWLINE_TYPE, + END = END_TYPE + }; + +private: + + friend class TextInput; + + /** + Holds the actual value, which might be any type. If a number, it will be + parsed at runtime. + */ + std::string _string; + + bool _bool; + int _line; + int _character; + Type _type; + ExtendedType _extendedType; + +public: + + Token() : + _string(""), + _bool(false), + _line(0), + _character(0), + _type(END), + _extendedType(END_TYPE) {} + + Token(Type t, ExtendedType e, const std::string& s, int L, int c) + : _string(s), _bool(false), _line(L), _character(c), _type(t), _extendedType(e) {} + + Token(Type t, ExtendedType e, const std::string& s, bool b, int L, int c) + : _string(s), _bool(b), _line(L), _character(c), _type(t), _extendedType(e) {} + + Type type() const { + return _type; + } + + ExtendedType extendedType() const { + return _extendedType; + } + + /** + The value of a single or double quote string (not including the quotes), + the name of a symbol, or the exact textual representation of a number as + parsed from the input. + */ + const std::string& string() const { + return _string; + } + + bool boolean() const { + return _bool; + } + + /** + Starting line of the input from which this token was parsed. Starts + at 1. + */ + int line() const { + return _line; + } + + /** + Starting character position in the input line from which this token was + parsed. Starts at 1. + */ + int character() const { + return _character; + } + + /** Return the numeric value for a number type, or zero if this is + not a number type. + */ + double number() const; +}; + + +/** + A simple style tokenizer for reading text files. TextInput handles a + superset of C++,Java, Matlab, and Bash code text including single + line comments, block comments, quoted strings with escape sequences, + and operators. TextInput recognizes several categories of tokens, + which are separated by white space, quotation marks, or the end of a + recognized operator: + +
    +
  • Token::SINGLE_QUOTED_TYPE string of characters surrounded by single quotes, e.g., 'x', '\\0', 'foo'. +
  • Token::DOUBLE_QUOTED_TYPE string of characters surrounded by double quotes, e.g., "x", "abc\txyz", "b o b". +
  • Token::SYMBOL_TYPE legal C++ operators, keywords, and identifiers. e.g., >=, Foo, _X, class, { +
  • Token::INTEGER_TYPE numbers without decimal places or exponential notation. e.g., 10, 0x17F, 32, 0, -155 +
  • Token::FLOATING_POINT_TYPE numbers with decimal places or exponential notation. e.g., 1e3, -1.2, .4, 0.5 +
  • Token::BOOLEAN_TYPE special symbols like "true" and "false"; the exact details can be configured in TextInput::Settings +
  • Token::LINE_COMMENT_TYPE (disabled by default); generated for line comments as specified by TextInput::Settings +
  • Token::BLOCK_COMMENT_TYPE (disabled by default); generated for c-style block comments as specified by TextInput::Settings +
  • Token::NEWLINE_TYPE (disabled by default); generated for any of "\\r", "\\n" or "\\r\\n" +
+ +

The special ".." and "..." tokens are always recognized in + addition to normal C++ operators. Additional tokens can be made + available by changing the Settings. + + Negative numbers are handled specially because of the ambiguity between unary minus and negative numbers-- + see the note on TextInput::read. + + TextInput does not have helper functions for types with non-obvious + formatting, or helpers that would be redundant. Use the serialize + methods instead for parsing specific types like int, Vector3, and + Color3. + + Inside quoted strings escape sequences are converted. Thus the + string token for ["a\\nb"] is 'a', followed by a newline, followed by + 'b'. Outside of quoted strings, escape sequences are not converted, + so the token sequence for [a\\nb] is symbol 'a', symbol '\\', symbol + 'nb' (this matches what a C++ parser would do). The exception is + that a specified TextInput::Settings::otherCommentCharacter preceeded + by a backslash is assumed to be an escaped comment character and is + returned as a symbol token instead of being parsed as a comment + (this is what a LaTex or VRML parser would do). + + Examples + +

+  TextInput ti(TextInput::FROM_STRING, "name = \"Max\", height = 6");
+
+  Token t;
+
+  t = ti.read(); 
+  debugAssert(t.type == Token::SYMBOL);
+  debugAssert(t.sval == "name");
+
+  ti.read();
+  debugAssert(t.type == Token::SYMBOL);
+  debugAssert(t.sval == "=");
+
+  std::string name = ti.read().sval;
+  ti.read();
+  
+ +
+  TextInput ti(TextInput::FROM_STRING, "name = \"Max\", height = 6");
+  ti.readSymbols("name", "=");
+  std::string name = ti.readString();
+  ti.readSymbols(",", "height", "=");
+  double height = ti. readNumber();
+  
+ + Assumes that the file is not modified once opened. + */ +class TextInput { +public: + + /** Tokenizer configuration options. */ + class Settings { + public: + /** If true, C-style slash-star marks a multi-line comment. + + See generateCommentTokens for rules on how this is applied. + + Default is true. + */ + bool cppBlockComments; + + /** If true, // begins a single line comment. + + See generateCommentTokens for rules on how this is applied. + + Default is true. + */ + bool cppLineComments; + + /** If true, otherCommentCharacter and otherCommentCharacter2 + are used to begin single line comments in the same way + cppLineComments is. + + See generateCommentTokens for rules on how this is applied. + + Default is true. + */ + bool otherLineComments; + + /** If true, \\r, \\n, \\t, \\0, \\\\ and other escape sequences inside + strings are converted to the equivalent C++ escaped character. + If false, backslashes are treated literally. It is convenient to + set to false if reading Windows paths, for example, like + c:\\foo\\bar. + + Default is true. + */ + bool escapeSequencesInStrings; + + /** If not '\\0', specifies a character that begins single line + comments ('#' and '%' are popular choices). This is independent + of the cppLineComments flag. If the character appears in text with + a backslash in front of it, it is considered escaped and is not + treated as a comment character. + + Default is '\\0'. + */ + char otherCommentCharacter; + + /** Another (optional) 1-comment character. Useful for files that + support multiple comment syntaxes. Default is '\\0'. + */ + char otherCommentCharacter2; + + /** If true, comments enabled by cppBlockComments, cppLineComments + and otherLineComments will generate their respective tokens. + If false, the same settings will enable parsing and ignoring + comments + + Default is false. + */ + bool generateCommentTokens; + + /** If true, newlines will generate tokens. + If false, newlines will be discarded as whitespace when parsed + outside of other tokens. + + Default is false. + */ + bool generateNewlineTokens; + + /** If true, "-1" parses as the number -1 instead of the + symbol "-" followed by the number 1. Default is true.*/ + bool signedNumbers; + + /** If true, strings can be marked with single quotes (e.g., + 'aaa'). If false, the quote character is parsed as a + symbol. Default is true. Backquote (`) is always parsed + as a symbol. */ + bool singleQuotedStrings; + + /** The character to use as a single quote. Defaults to "'" (backquote), + occasionally useful to set to "`" (forward quote) or to "," (comma) for + reading CSV files. */ + char singleQuoteCharacter; + + /** If set to a non-empty string, that string will be used in + place of the real file name (or in place of a pseudonym + constructed from the buffer if given FROM_STRING) in + tokens and exceptions. + + Default is empty. + */ + std::string sourceFileName; + + + /** Added to the line number reported by peekLineNumber and in + exceptions. Useful for concatenating files that are + parsed separately. Default is zero. */ + int startingLineNumberOffset; + + /** + Parse -1.#IND00 as the floating point number returned by + nan(), -1.#INF00 as -inf(), and 1.#INF00 as inf(). Note + that the C99 standard specifies that a variety of formats + like "NaN" and "nan" are to be used; these are easier to + parse yourself and not currently supported by readNumber. + + An alternative to specifying msvcSpecials is to read numbers as: +
+            Token x = t.read();
+            Token y = t.peek();
+            if ((x.string() == "-1.") && 
+                (y.string() == "#INF00") && 
+                (y.character() == x.character() + 3) &&
+                (y.line() == x.line()) {
+                t.read();
+                return nan();
+            }
+            // ... similar cases for inf
+          
+ + If the single-comment character was #, the floating point + special format overrides the comment and will be parsed + instead. + + If signedNumbers is false msvcSpecials will not be parsed. + + Default is true. */ + bool msvcSpecials; + + /** + Parse the following set of useful proof symbols: + + => + ::> + <:: + :> + <: + |- + ::= + := + <- + + Default is false. + */ + bool proofSymbols; + + /** + When parsing booleans and msvcSpecials, is case significant? + Default is {true} + */ + bool caseSensitive; + + /** All symbols that will become the 'true' boolean token. See also caseSensitive. + Clear this value to disable parsing of true booleans. + + Default is {true}. + */ + Set trueSymbols; + + /** See trueSymbols. Default is {false}*/ + Set falseSymbols; + + Settings(); + }; + +private: + + std::deque stack; + + /** + Characters to be tokenized. + */ + Array buffer; + + /** + Offset of current character (the next character to consumed) in + input buffer. + */ + int currentCharOffset; + + /** + Line number of next character to be consumed from the input buffer. (1 + indicates first line of input.) + + Note that this is the line number of the @e next character to be + consumed from the input, not the line number of the @e last character + consumed! + */ + int lineNumber; + + /** + Character number (within the line) of the next character to be consumed + from the input buffer. (1 indicates first character of the line). + + Note that this is the character number of the @e next character to be + consumed from the input, not the character number of the @e last + character consumed! + */ + int charNumber; + + /** Configuration options. This includes the file name that will be + reported in tokens and exceptions. */ + Settings options; + + void init(); + + /** + Consumes the next character from the input buffer, and returns that + character. Updates lineNumber and charNumber to reflect the location of + the next character in the input buffer. + + Note: you shouldn't be using the return value of this function in most + cases. In general, you should peekInputChar() to get the next + character, determine what to do with it, then consume it with this + function (or with eatAndPeekInputChar()). Given that usage, in most + instances you already know what this function would return! + */ + int eatInputChar(); + + /** + Returns the next character from the input buffer, without consuming any + characters. Can also be used to look deeper into the input buffer. + Does not modify lineNumber or charNumber. + + @param distance Index of the character in the input buffer to peek at, + relative to the next character. Default is 0, for the next character in + the input buffer. + */ + int peekInputChar(int distance = 0); + + /** + Helper function to consume the next character in the input buffer and + peek at the one following (without consuming it). + */ + inline int eatAndPeekInputChar() { + eatInputChar(); + return peekInputChar(0); + } + + /** + Read the next token, returning an END token if no more input is + available. + */ + Token nextToken(); + + /** + Helper for nextToken. Appends characters to t._string until the end + delimiter is reached. + + When called, the next character in the input buffer should be first the + first character after the opening delimiter character. + */ + void parseQuotedString(unsigned char delimiter, Token& t); + +public: + + class TokenException : public ParseError { + public: + /** Name of file being parsed when exception occurred. + \deprecated Use filename + */ + std::string sourceFile; + + virtual ~TokenException() {} + + protected: + + TokenException( + const std::string& src, + int ln, + int ch); + + }; + + /** While parsing a number of the form 1.\#IN?00, ? was + not 'D' or 'F'. */ + class BadMSVCSpecial : public TokenException { + public: + + BadMSVCSpecial( + const std::string& src, + int ln, + int ch); + }; + + /** Thrown by the read methods. */ + class WrongTokenType : public TokenException { + public: + Token::Type expected; + Token::Type actual; + + WrongTokenType( + const std::string& src, + int ln, + int ch, + Token::Type e, + Token::Type a); + }; + + class WrongSymbol : public TokenException { + public: + std::string expected; + std::string actual; + + WrongSymbol( + const std::string& src, + int ln, + int ch, + const std::string& e, + const std::string& a); + }; + + + /** String read from input did not match expected string. */ + class WrongString : public TokenException { + public: + std::string expected; + std::string actual; + + WrongString( + const std::string& src, + int ln, + int ch, + const std::string& e, + const std::string& a); + }; + + TextInput(const std::string& filename, const Settings& settings = Settings()); + + enum FS {FROM_STRING}; + /** Creates input directly from a string. The first argument must be + TextInput::FROM_STRING. + */ + TextInput(FS fs, const std::string& str, const Settings& settings = Settings()); + + /** Returns true while there are tokens remaining. */ + bool hasMore(); + + /** Read the next token (which will be the END token if ! hasMore()). + + Signed numbers can be handled in one of two modes. If the option + TextInput::Settings::signedNumbers is true, + A '+' or '-' immediately before a number is prepended onto that number and + if there is intervening whitespace, it is read as a separate symbol. + + If TextInput::Settings::signedNumbers is false, + read() does not distinguish between a plus or minus symbol next + to a number and a positive/negative number itself. For example, "x - 1" and "x -1" + will be parsed the same way by read(). + + In both cases, readNumber() will contract a leading "-" or "+" onto + a number. + */ + Token read(); + + /** Calls read() until the result is not a newline or comment */ + Token readSignificant(); + + /** Read one token (or possibly two) as a number or throws + WrongTokenType, and returns the number. + + If the first token in the input is a number, it is returned directly. + + If TextInput::Settings::signedNumbers is false and the input stream + contains a '+' or '-' symbol token immediately followed by a number + token, both tokens will be consumed and a single token will be + returned by this method. + + WrongTokenType will be thrown if one of the input conditions + described above is not satisfied. When an exception is thrown, no + tokens are consumed. + */ + double readNumber(); + + bool readBoolean(); + + /** Reads a string token or throws WrongTokenType, and returns the token. + + Use this method (rather than readString) if you want the token's + location as well as its value. + + WrongTokenType will be thrown if the next token in the input stream + is not a string. When an exception is thrown, no tokens are + consumed. + */ + Token readStringToken(); + + /** Like readStringToken, but returns the token's string. + + Use this method (rather than readStringToken) if you want the token's + value but don't really care about its location in the input. Use of + readStringToken is encouraged for better error reporting. + */ + std::string readString(); + + /** Reads a specific string token or throws either WrongTokenType or + WrongString. If the next token in the input is a string matching @p + s, it will be consumed. + + Use this method if you want to match a specific string from the + input. In that case, typically error reporting related to the token + is only going to occur because of a mismatch, so no location + information is needed by the caller. + + WrongTokenType will be thrown if the next token in the input stream + is not a string. WrongString will be thrown if the next token in the + input stream is a string but does not match the @p s parameter. When + an exception is thrown, no tokens are consumed. + */ + void readString(const std::string& s); + + /** Reads a comment token or throws WrongTokenType, and returns the token. + + Use this method (rather than readComment) if you want the token's + location as well as its value. + + WrongTokenType will be thrown if the next token in the input stream + is not a comment. When an exception is thrown, no tokens are + consumed. + */ + Token readCommentToken(); + + /** Like readCommentToken, but returns the token's string. + + Use this method (rather than readCommentToken) if you want the token's + value but don't really care about its location in the input. Use of + readCommentToken is encouraged for better error reporting. + */ + std::string readComment(); + + /** Reads a specific comment token or throws either WrongTokenType or + WrongString. If the next token in the input is a comment matching @p + s, it will be consumed. + + Use this method if you want to match a specific comment from the + input. In that case, typically error reporting related to the token + is only going to occur because of a mismatch, so no location + information is needed by the caller. + + WrongTokenType will be thrown if the next token in the input stream + is not a comment. WrongString will be thrown if the next token in the + input stream is a comment but does not match the @p s parameter. When + an exception is thrown, no tokens are consumed. + */ + void readComment(const std::string& s); + + /** Reads a newline token or throws WrongTokenType, and returns the token. + + Use this method (rather than readNewline) if you want the token's + location as well as its value. + + WrongTokenType will be thrown if the next token in the input stream + is not a newline. When an exception is thrown, no tokens are + consumed. + */ + Token readNewlineToken(); + + /** Like readNewlineToken, but returns the token's string. + + Use this method (rather than readNewlineToken) if you want the token's + value but don't really care about its location in the input. Use of + readNewlineToken is encouraged for better error reporting. + */ + std::string readNewline(); + + /** Reads a specific newline token or throws either WrongTokenType or + WrongString. If the next token in the input is a newline matching @p + s, it will be consumed. + + Use this method if you want to match a specific newline from the + input. In that case, typically error reporting related to the token + is only going to occur because of a mismatch, so no location + information is needed by the caller. + + WrongTokenType will be thrown if the next token in the input stream + is not a newline. WrongString will be thrown if the next token in the + input stream is a newlin but does not match the @p s parameter. When + an exception is thrown, no tokens are consumed. + */ + void readNewline(const std::string& s); + + /** Reads a symbol token or throws WrongTokenType, and returns the token. + + Use this method (rather than readSymbol) if you want the token's + location as well as its value. + + WrongTokenType will be thrown if the next token in the input stream + is not a symbol. When an exception is thrown, no tokens are + consumed. + */ + Token readSymbolToken(); + + /** Like readSymbolToken, but returns the token's string. + + Use this method (rather than readSymbolToken) if you want the token's + value but don't really care about its location in the input. Use of + readSymbolToken is encouraged for better error reporting. + */ + std::string readSymbol(); + + /** Reads a specific symbol token or throws either WrongTokenType or + WrongSymbol. If the next token in the input is a symbol matching @p + symbol, it will be consumed. + + Use this method if you want to match a specific symbol from the + input. In that case, typically error reporting related to the token + is only going to occur because of a mismatch, so no location + information is needed by the caller. + + WrongTokenType will be thrown if the next token in the input stream + is not a symbol. WrongSymbol will be thrown if the next token in the + input stream is a symbol but does not match the @p symbol parameter. + When an exception is thrown, no tokens are consumed. + */ + void readSymbol(const std::string& symbol); + + + /** Read a series of two specific symbols. See readSymbol. */ + inline void readSymbols(const std::string& s1, const std::string& s2) { + readSymbol(s1); + readSymbol(s2); + } + + /** Read a series of three specific symbols. See readSymbol. */ + inline void readSymbols( + const std::string& s1, + const std::string& s2, + const std::string& s3) { + readSymbol(s1); + readSymbol(s2); + readSymbol(s3); + } + + /** Read a series of four specific symbols. See readSymbol. */ + inline void readSymbols( + const std::string& s1, + const std::string& s2, + const std::string& s3, + const std::string& s4) { + readSymbol(s1); + readSymbol(s2); + readSymbol(s3); + readSymbol(s4); + } + + /** Return a copy of the next token in the input stream, but don't remove + it from the input stream. + */ + Token peek(); + + /** Returns the line number for the @e next token. See also peek. */ + int peekLineNumber(); + + /** Returns the character number (relative to the line) for the @e next + token in the input stream. See also peek. + */ + int peekCharacterNumber(); + + /** Take a previously read token and push it back at the front of the + input stream. + + Can be used in the case where more than one token of read-ahead is + needed (i.e., when peek doesn't suffice). + */ + void push(const Token& t); + + /** Returns the filename from which this input is drawn, or the first few + characters of the string if created from a string. + If settings::filename is non-empty that will replace the + true filename.*/ + const std::string& filename() const; +}; + +void deserialize(bool& b, TextInput& ti); +void deserialize(int& b, TextInput& ti); +void deserialize(uint8& b, TextInput& ti); +void deserialize(double& b, TextInput& ti); +void deserialize(float& b, TextInput& ti); +void deserialize(std::string& b, TextInput& ti); + +} // namespace + +#endif + diff --git a/externals/g3dlite/G3D/TextOutput.h b/externals/g3dlite/G3D/TextOutput.h new file mode 100644 index 00000000000..4c22b7d5653 --- /dev/null +++ b/externals/g3dlite/G3D/TextOutput.h @@ -0,0 +1,249 @@ +/** + @file TextOutput.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @created 2004-06-21 + @edited 2006-10-24 + + Copyright 2000-2007, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_TEXTOUTPUT_H +#define G3D_TEXTOUTPUT_H + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include + +namespace G3D { + +/** + Convenient formatting of ASCII text written to a file. +

+ + The core writeString, writeNumber, and writeSymbol methods map to TextInput's + methods. Number and Symbol each print an additional space that is used to + separate adjacent tokens. + + TextOutput::printf allows arbitrary text to be conveniently dumped + en-masse. Use [de]serialize(bool, TextOutput) and other overloads to read/write + primitive types in a standardized manner and + +

+ When a word-wrap line break occurs, all whitespace between words is replaced + with a single newline (the newline may be two characters-- see + G3D::TextOutput::Options::NewlineStyle). Word wrapping occurs against + the number of columns specified by Options::numColumns, minus the current + indent level. + + Indenting adds the specified number of spaces immediately after a newline. + If a newline was followed by spaces in the original string, these are added + to the indent spaces. Indenting will indent blank lines and will leave + indents after the last newline of a file (if the indent level is non-zero at the end). + +

Serialization/Marshalling +

Text serialization is accomplished using TextOutput by defining the pair of + methods: + +
+  void serialize(TextOutput& to) const;
+  void deserialize(TextInput& ti);
+  
+ + See also G3D::TextInput. + +

+ BETA API +

This API is subject to change in future versions. + */ +class TextOutput { +public: + + class Settings { + public: + /** + WRAP_NONE Word wrapping is disabled + WRAP_WITHOUT_BREAKING Word-wrap, but don't break continuous lines that + are longer than numColumns (default) + WRAP_ALWAYS Wrap even if it means breaking a continuous line or + a quoted string. + + Word wrapping is only allowed at whitespaces ('\\n', '\\r', '\\t', ' '); it + will not occur after commas, punctuation, minus signs, or any other characters + */ + enum WordWrapMode {WRAP_NONE, WRAP_WITHOUT_BREAKING, WRAP_ALWAYS}; + + /** Defaults to WRAP_WITHOUT_BREAKING */ + WordWrapMode wordWrap; + + /** Is word-wrapping allowed to insert newlines inside double quotes? + Default: false */ + bool allowWordWrapInsideDoubleQuotes; + + /** Number of columns for word wrapping. Default: 8 */ + int numColumns; + + /** Number of spaces in each indent. Default: 4 */ + int spacesPerIndent; + + /** Style of newline used by word wrapping and by (optional) conversion. + default: Windows: NEWLINE_WINDOWS, Linux, OS X: NEWLINE_UNIX. + */ + enum NewlineStyle {NEWLINE_WINDOWS, NEWLINE_UNIX}; + + NewlineStyle newlineStyle; + + /** If true, all newlines are converted to NewlineStyle regardless of + how they start out. Default: true. */ + bool convertNewlines; + + /** Used by writeBoolean */ + std::string trueSymbol; + + /** Used by writeBoolean */ + std::string falseSymbol; + + Settings() : + wordWrap(WRAP_WITHOUT_BREAKING), + allowWordWrapInsideDoubleQuotes(false), + numColumns(80), + spacesPerIndent(4), + convertNewlines(true), + trueSymbol("true"), + falseSymbol("false") { + #ifdef G3D_WIN32 + newlineStyle = NEWLINE_WINDOWS; + #else + newlineStyle = NEWLINE_UNIX; + #endif + } + }; + +private: + + /** Used by indentAndAppend to tell when we are writing the + first character of a new line. + + So that push/popIndent work correctly, we cannot indent + immediately after writing a newline. Instead we must + indent on writing the first character after that + newline. + */ + bool startingNewLine; + + /** Number of characters at the end of the buffer since the last newline */ + int currentColumn; + + /** True if we have seen an open " and no close ".*/ + bool inDQuote; + + /** Empty if there is none */ + std::string filename; + + Array data; + + Settings option; + + /** Number of indents to prepend before each line. Always set using setIndentLevel.*/ + int indentLevel; + + void setIndentLevel(int i); + + /** Actual number of spaces to indent. */ + int indentSpaces; + + /** the newline character(s) */ + std::string newline; + + void setOptions(const Settings& _opt); + + /** Converts to the desired newlines. Called from vprintf */ + void convertNewlines(const std::string& in, std::string& out); + + /** Called from vprintf */ + void wordWrapIndentAppend(const std::string& str); + + /** Appends the character to data, indenting whenever a newline is encountered. + Called from wordWrapIndentAppend */ + void indentAppend(char c); + +public: + + explicit TextOutput(const std::string& filename, const Settings& options = Settings()); + + /** Constructs a text output that can later be commited to a string instead of a file.*/ + explicit TextOutput(const Settings& options = Settings()); + + /** Commit to the filename specified on the constructor. + Not called from the destructor; you must call + it yourself. + @param flush If true (default) the file is ready for reading when the method returns, otherwise + the method returns immediately and writes the file in the background.*/ + void commit(bool flush = true); + + /** Commits to this string */ + void commitString(std::string& string); + + /** Increase indent level by 1 */ + void pushIndent(); + + void popIndent(); + + /** Produces a new string that contains the output */ + std::string commitString(); + + /** Writes a quoted string. Special characters in the string (e.g., \\, \\t, \\n) are escaped so that + TextInput will produce the identical string on reading.*/ + void writeString(const std::string& string); + + void writeBoolean(bool b); + + void writeNumber(double n); + + void writeNumber(int n); + + void writeNewline(); + void writeNewlines(int numLines); + + /** The symbol is written without quotes. Symbols are required to begin with a + letter or underscore and contain only letters, underscores, and numbers + or be a C++ symbol (e.g. "{", "(", "++", etc.) + so that they may be properly parsed by TextInput::readSymbol. Symbols are + printed with a trailing space.*/ + void writeSymbol(const std::string& string); + + /** Convenient idiom for writing multiple symbols in a row, e.g. + writeSymbols("name", "="); The empty symbols are not written. + */ + void writeSymbols( + const std::string& a, + const std::string& b = "", + const std::string& c = "", + const std::string& d = "", + const std::string& e = "", + const std::string& f = ""); + + /** Normal printf conventions. Note that the output will be reformatted + for word-wrapping and newlines */ + void __cdecl printf(const char* fmt, ...) + G3D_CHECK_PRINTF_METHOD_ARGS; + + // Can't pass by reference because that confuses va_start + void __cdecl printf(const std::string fmt, ...); + void __cdecl vprintf(const char* fmt, va_list argPtr) + G3D_CHECK_VPRINTF_METHOD_ARGS; +}; + +// Primitive serializers +void serialize(const bool& b, TextOutput& to); +void serialize(const int& b, TextOutput& to); +void serialize(const uint8& b, TextOutput& to); +void serialize(const double& b, TextOutput& to); +void serialize(const float& b, TextOutput& to); +void serialize(const std::string& b, TextOutput& to); +void serialize(const char* b, TextOutput& to); + +} + +#endif diff --git a/externals/g3dlite/G3D/ThreadSet.h b/externals/g3dlite/G3D/ThreadSet.h new file mode 100644 index 00000000000..121f1415a1d --- /dev/null +++ b/externals/g3dlite/G3D/ThreadSet.h @@ -0,0 +1,87 @@ +#ifndef G3D_THREADSET_H +#define G3D_THREADSET_H + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/ReferenceCount.h" +#include "G3D/GThread.h" +#include "G3D/GMutex.h" + +namespace G3D { + +/** Manages a set of threads. All methods are threadsafe except for + the iterator begin/end. + + @beta*/ +class ThreadSet : public ReferenceCountedObject { +public: + /** Intended to allow future use with a template parameter.*/ + typedef GThread Thread; + + typedef ReferenceCountedPointer ThreadRef; + typedef ReferenceCountedPointer Ref; + typedef Array::Iterator Iterator; + typedef Array::ConstIterator ConstIterator; + +private: + + /** Protects m_thread */ + GMutex m_lock; + + /** Threads in the set */ + Array m_thread; + +public: + + /** Total number of threads (some of which may be completed). */ + int size() const; + + /** Number of threads that have been started */ + int numStarted() const; + + /** Start all threads that are not currently started. + + @param lastThreadBehavior If USE_CURRENT_THREAD, takes the last unstarted thread and executes it manually on + the current thread. This helps to take full advantage of the machine when + running a large number of jobs and avoids the overhead of a thread start for single-thread groups. + Note that this forces start() to block until + that thread is complete. + */ + void start(GThread::SpawnBehavior lastThreadBehavior = GThread::USE_NEW_THREAD) const; + + /** Terminate all threads that are currently started */ + void terminate() const; + + /** Waits until all started threads have completed. */ + void waitForCompletion() const; + + /** Remove all (not stopping them) */ + void clear(); + + /** Removes completed threads and returns the new size.*/ + int removeCompleted(); + + /** Inserts a new thread, if it is not already present, and + returns the new number of threads.*/ + int insert(const ThreadRef& t); + + /** Removes a thread. Returns true if the thread was present and + removed. */ + bool remove(const ThreadRef& t); + + bool contains(const ThreadRef& t) const; + + /** It is an error to mutate the ThreadSet while iterating through it. */ + Iterator begin(); + + Iterator end(); + + ConstIterator begin() const; + + ConstIterator end() const; +}; + + +} // namespace G3D + +#endif diff --git a/externals/g3dlite/G3D/Triangle.h b/externals/g3dlite/G3D/Triangle.h new file mode 100644 index 00000000000..590dbaad946 --- /dev/null +++ b/externals/g3dlite/G3D/Triangle.h @@ -0,0 +1,160 @@ +/** + @file Triangle.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2003-04-05 + @edited 2008-10-06 + + @cite Random point method by Greg Turk, Generating random points in triangles. In A. S. Glassner, ed., Graphics Gems, pp. 24-28. Academic Press, 1990 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_TRIANGLE_H +#define G3D_TRIANGLE_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Vector3.h" +#include "G3D/Plane.h" +#include "G3D/BoundsTrait.h" +#include "G3D/debugAssert.h" +#include + +namespace G3D { + +/** + A generic triangle representation. This should not be used + as the underlying triangle for creating models; it is intended + for providing fast property queries but requires a lot of + storage and is mostly immutable. + */ +class Triangle { +private: + friend class CollisionDetection; + friend class Ray; + + Vector3 _vertex[3]; + + /** edgeDirection[i] is the normalized vector v[i+1] - v[i] */ + Vector3 edgeDirection[3]; + float edgeMagnitude[3]; + Plane _plane; + Vector3::Axis _primaryAxis; + + /** vertex[1] - vertex[0] */ + Vector3 _edge01; + + /** vertex[2] - vertex[0] */ + Vector3 _edge02; + + float _area; + + void init(const Vector3& v0, const Vector3& v1, const Vector3& v2); + +public: + + Triangle(class BinaryInput& b); + void serialize(class BinaryOutput& b); + void deserialize(class BinaryInput& b); + + Triangle(); + + Triangle(const Vector3& v0, const Vector3& v1, const Vector3& v2); + + ~Triangle(); + + /** 0, 1, or 2 */ + inline const Vector3& vertex(int n) const { + debugAssert((n >= 0) && (n < 3)); + return _vertex[n]; + } + + /** vertex[1] - vertex[0] */ + inline const Vector3& edge01() const { + return _edge01; + } + + /** vertex[2] - vertex[0] */ + inline const Vector3& edge02() const { + return _edge02; + } + + float area() const; + + Vector3::Axis primaryAxis() const { + return _primaryAxis; + } + + const Vector3& normal() const; + + /** Barycenter */ + Vector3 center() const; + + const Plane& plane() const; + + /** Returns a random point in the triangle. */ + Vector3 randomPoint() const; + + inline void getRandomSurfacePoint + (Vector3& P, + Vector3& N = Vector3::ignore()) const { + P = randomPoint(); + N = normal(); + } + + /** + For two triangles to be equal they must have + the same vertices in the same order. + That is, vertex[0] == vertex[0], etc. + */ + inline bool operator==(const Triangle& other) const { + for (int i = 0; i < 3; ++i) { + if (_vertex[i] != other._vertex[i]) { + return false; + } + } + + return true; + } + + inline size_t hashCode() const { + return + _vertex[0].hashCode() + + (_vertex[1].hashCode() >> 2) + + (_vertex[2].hashCode() >> 3); + } + + void getBounds(class AABox&) const; + + /** + @brief Intersect the ray at distance less than @a distance. + + @param distance Set to the maximum distance (can be G3D::inf()) + to search for an intersection. On return, this is the smaller + of the distance to the intersection, if one exists, and the original + value. + + @param baryCoord If a triangle is hit before @a distance, a + the barycentric coordinates of the hit location on the triangle. + Otherwise, unmodified. + + @return True if there was an intersection before the original distance. + */ + bool intersect(const class Ray& ray, float& distance, float baryCoord[3]) const; +}; + +} // namespace G3D + +template <> struct HashTrait { + static size_t hashCode(const G3D::Triangle& key) { return key.hashCode(); } +}; + + +template<> struct BoundsTrait { + static void getBounds(const G3D::Triangle& t, G3D::AABox& out) { t.getBounds(out); } +}; + +#endif diff --git a/externals/g3dlite/G3D/UprightFrame.h b/externals/g3dlite/G3D/UprightFrame.h new file mode 100644 index 00000000000..ad5157cb14b --- /dev/null +++ b/externals/g3dlite/G3D/UprightFrame.h @@ -0,0 +1,83 @@ +/** + @file UprightFrame.h + + @author Morgan McGuire, http://graphics.cs.williams.edu + */ + +#ifndef G3D_UPRIGHTFRAME_H +#define G3D_UPRIGHTFRAME_H + +#include "G3D/platform.h" +#include "G3D/Spline.h" +#include "G3D/Vector3.h" +#include "G3D/CoordinateFrame.h" + +namespace G3D { + +/** + Coordinate frame expressed in Euler angles. + Unlike a G3D::Quat, UprightFrame always keeps the reference frame from rolling about its own z axis. + Particularly useful for cameras. + + @sa G3D::CoordinateFrame, G3D::Matrix4, G3D::PhysicsFrame, G3D::UprightSpline, G3D::UprightSplineManipulator + */ +class UprightFrame { +public: + + Vector3 translation; + + /** -pi/2 < pitch < pi/2 in radians about the X-axis */ + float pitch; + + /** In radians about the Y-axis */ + float yaw; + + inline UprightFrame(const Vector3& t = Vector3::zero(), float p = 0, float y = 0) + : translation(t), pitch(p), yaw(y) {} + + UprightFrame(const CoordinateFrame& cframe); + + CoordinateFrame toCoordinateFrame() const; + + /** Supports implicit cast to CoordinateFrame */ + inline operator CoordinateFrame() const { + return toCoordinateFrame(); + } + + /** Required for use with spline */ + UprightFrame operator+(const UprightFrame& other) const; + + /** Required for use with spline */ + UprightFrame operator*(const float k) const; + + /** + Unwraps the yaw values in the elements of the array such that + they still represent the same angles but strictly increase/decrease + without wrapping about zero. For use with Spline + */ + static void unwrapYaw(UprightFrame* a, int N); + + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); +}; + +/** Shortest-path linear velocity spline for camera positions. Always keeps the camera from rolling. +@sa G3D::UprightSplineManipulator, G3D::UprightFrame +*/ +class UprightSpline : public Spline { +protected: + + virtual void ensureShortestPath(UprightFrame* A, int N) const { + UprightFrame::unwrapYaw(A, N); + } + +public: + + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/Vector2.h b/externals/g3dlite/G3D/Vector2.h new file mode 100644 index 00000000000..dba7353785e --- /dev/null +++ b/externals/g3dlite/G3D/Vector2.h @@ -0,0 +1,454 @@ +/** + @file Vector2.h + + 2D vector class + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2001-06-02 + @edited 2008-11-30 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. +*/ + +#ifndef G3D_VECTOR2_H +#define G3D_VECTOR2_H + +#include + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Table.h" +#include "G3D/HashTrait.h" +#include "G3D/Vector2int16.h" +#include "G3D/Random.h" + +namespace G3D { + +class Vector2; +class Vector3; +class Vector4; +class Any; + +/** + Do not subclass-- this implementation makes assumptions about the + memory layout. + */ +class Vector2 { +private: + // Hidden operators + bool operator<(const Vector2&) const; + bool operator>(const Vector2&) const; + bool operator<=(const Vector2&) const; + bool operator>=(const Vector2&) const; + +public: + float x; + float y; + + /** \param any Must either Vector2(#, #) or Vector2 {x = #, y = #}*/ + Vector2(const Any& any); + + /** Converts the Vector2 to an Any. */ + operator Any() const; + + /** Creates the zero vector */ + Vector2(); + Vector2(class TextInput& t); + Vector2(class BinaryInput& b); + Vector2(float x, float y); + Vector2(float coordinate[2]); + Vector2(double coordinate[2]); + Vector2(const Vector2& other); + Vector2(const Vector2int16& other); + + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + + void serialize(class TextOutput& t) const; + void deserialize(class TextInput& t); + + float& operator[](int i); + const float& operator[](int i) const; + + // assignment and comparison + Vector2& operator=(const Vector2& other); + bool operator==(const Vector2& other) const; + bool operator!=(const Vector2& other) const; + size_t hashCode() const; + bool fuzzyEq(const Vector2& other) const; + bool fuzzyNe(const Vector2& other) const; + + /** Returns true if this vector has finite length */ + bool isFinite() const; + + /** Returns true if this vector has length == 0 */ + bool isZero() const; + + /** Returns true if this vector has length == 1 */ + bool isUnit() const; + + // arithmetic operations + Vector2 operator+(const Vector2& v) const; + Vector2 operator-(const Vector2& v) const; + Vector2 operator*(float s) const; + + /** Array (pointwise) multiplication */ + Vector2 operator*(const Vector2& v) const; + + /** Array division */ + Vector2 operator/(const Vector2& v) const; + Vector2 operator/(float s) const; + + /** Unary minus */ + Vector2 operator-() const; + + /** x + y */ + inline float sum() const { + return x + y; + } + + /** + Linear interpolation + */ + inline Vector2 lerp(const Vector2& v, float alpha) const { + return (*this) + (v - *this) * alpha; + } + + inline Vector2 clamp(const Vector2& low, const Vector2& high) const { + return Vector2( + G3D::clamp(x, low.x, high.x), + G3D::clamp(y, low.y, high.y)); + } + + inline Vector2 clamp(float low, float high) const { + return Vector2( + (float)G3D::clamp(x, low, high), + (float)G3D::clamp(y, low, high)); + } + + // arithmetic updates + Vector2& operator+=(const Vector2&); + Vector2& operator-=(const Vector2&); + Vector2& operator*=(float); + Vector2& operator/=(float); + Vector2& operator*=(const Vector2&); + Vector2& operator/=(const Vector2&); + + // vector operations + + /** */ + float length() const; + + /** Returns a unit-length vector */ + Vector2 direction() const; + + /** + Potentially less accurate but faster than direction(). + Only works if System::hasSSE is true. + */ + Vector2 fastDirection() const { + return direction(); + } + + float squaredLength() const; + float dot(const Vector2& s) const; + + /** + Make this vector have unit length and return the old length. + If the vector length was less than tolerance, do not normalize. + */ + float unitize(float fTolerance = 1e-06); + + Vector2 min(const Vector2& v) const; + Vector2 max(const Vector2& v) const; + + /** Uniformly distributed random vector on the unit sphere */ + static Vector2 random(Random& r = Random::common()); + + // Special values. + // Intentionally not inlined: see Matrix3::identity() for details. + static const Vector2& zero(); + static const Vector2& one(); + static const Vector2& unitX(); + static const Vector2& unitY(); + static const Vector2& inf(); + static const Vector2& nan(); + /** smallest (most negative) representable vector */ + static const Vector2& minFinite(); + /** Largest representable vector */ + static const Vector2& maxFinite(); + + std::string toString() const; + + // 2-char swizzles + + Vector2 xx() const; + Vector2 yx() const; + Vector2 xy() const; + Vector2 yy() const; + + // 3-char swizzles + + Vector3 xxx() const; + Vector3 yxx() const; + Vector3 xyx() const; + Vector3 yyx() const; + Vector3 xxy() const; + Vector3 yxy() const; + Vector3 xyy() const; + Vector3 yyy() const; + + // 4-char swizzles + + Vector4 xxxx() const; + Vector4 yxxx() const; + Vector4 xyxx() const; + Vector4 yyxx() const; + Vector4 xxyx() const; + Vector4 yxyx() const; + Vector4 xyyx() const; + Vector4 yyyx() const; + Vector4 xxxy() const; + Vector4 yxxy() const; + Vector4 xyxy() const; + Vector4 yyxy() const; + Vector4 xxyy() const; + Vector4 yxyy() const; + Vector4 xyyy() const; + Vector4 yyyy() const; + +}; + +inline Vector2 operator*(double s, const Vector2& v) { + return v * (float)s; +} + +inline Vector2 operator*(float s, const Vector2& v) { + return v * s; +} + +inline Vector2 operator*(int s, const Vector2& v) { + return v * (float)s; +} + + +inline Vector2::Vector2 () : x(0.0f), y(0.0f) { +} + + +inline Vector2::Vector2(float _x, float _y) : x(_x), y(_y) { +} + + +inline Vector2::Vector2 (float afCoordinate[2]) { + x = afCoordinate[0]; + y = afCoordinate[1]; +} + + + +inline Vector2::Vector2 (double afCoordinate[2]) { + x = (float)afCoordinate[0]; + y = (float)afCoordinate[1]; +} + + +inline Vector2::Vector2 (const Vector2& rkVector) { + x = rkVector.x; + y = rkVector.y; +} + + +inline Vector2::Vector2 (const Vector2int16& v) : x(v.x), y(v.y) { +} + + +inline float& Vector2::operator[] (int i) { + return ((float*)this)[i]; +} + + +inline const float& Vector2::operator[] (int i) const { + return ((float*)this)[i]; +} + + +inline Vector2& Vector2::operator= (const Vector2& rkVector) { + x = rkVector.x; + y = rkVector.y; + return *this; +} + + +inline bool Vector2::operator== (const Vector2& rkVector) const { + return ( x == rkVector.x && y == rkVector.y); +} + + +inline bool Vector2::operator!= (const Vector2& rkVector) const { + return ( x != rkVector.x || y != rkVector.y); +} + + +inline Vector2 Vector2::operator+ (const Vector2& rkVector) const { + return Vector2(x + rkVector.x, y + rkVector.y); +} + + +inline Vector2 Vector2::operator- (const Vector2& rkVector) const { + return Vector2(x - rkVector.x, y - rkVector.y); +} + + +inline Vector2 Vector2::operator* (float fScalar) const { + return Vector2(fScalar*x, fScalar*y); +} + + + +inline Vector2 Vector2::operator- () const { + return Vector2( -x, -y); +} + + + +inline Vector2& Vector2::operator+= (const Vector2& rkVector) { + x += rkVector.x; + y += rkVector.y; + return *this; +} + + + +inline Vector2& Vector2::operator-= (const Vector2& rkVector) { + x -= rkVector.x; + y -= rkVector.y; + return *this; +} + + + +inline Vector2& Vector2::operator*= (float fScalar) { + x *= fScalar; + y *= fScalar; + return *this; +} + + + + +inline Vector2& Vector2::operator*= (const Vector2& rkVector) { + x *= rkVector.x; + y *= rkVector.y; + return *this; +} + + + +inline Vector2& Vector2::operator/= (const Vector2& rkVector) { + x /= rkVector.x; + y /= rkVector.y; + return *this; +} + + +inline Vector2 Vector2::operator* (const Vector2& rkVector) const { + return Vector2(x * rkVector.x, y * rkVector.y); +} + + + +inline Vector2 Vector2::operator/ (const Vector2& rkVector) const { + return Vector2(x / rkVector.x, y / rkVector.y); +} + + +inline float Vector2::squaredLength () const { + return x*x + y*y; +} + + +inline float Vector2::length () const { + return sqrtf(x*x + y*y); +} + + +inline Vector2 Vector2::direction () const { + float lenSquared = x * x + y * y; + + if (lenSquared != 1.0f) { + return *this / sqrtf(lenSquared); + } else { + return *this; + } +} + + + +inline float Vector2::dot (const Vector2& rkVector) const { + return x*rkVector.x + y*rkVector.y; +} + + + +inline Vector2 Vector2::min(const Vector2 &v) const { + return Vector2(G3D::min(v.x, x), G3D::min(v.y, y)); +} + + + +inline Vector2 Vector2::max(const Vector2 &v) const { + return Vector2(G3D::max(v.x, x), G3D::max(v.y, y)); +} + + + +inline bool Vector2::fuzzyEq(const Vector2& other) const { + return G3D::fuzzyEq((*this - other).squaredLength(), 0); +} + + + +inline bool Vector2::fuzzyNe(const Vector2& other) const { + return G3D::fuzzyNe((*this - other).squaredLength(), 0); +} + + + +inline bool Vector2::isFinite() const { + return G3D::isFinite(x) && G3D::isFinite(y); +} + + + +inline bool Vector2::isZero() const { + return (x == 0.0f) && (y == 0.0f); +} + + + +inline bool Vector2::isUnit() const { + return squaredLength() == 1.0f; +} + +} // namespace G3D + +template <> +struct HashTrait { + static size_t hashCode(const G3D::Vector2& key) { + return key.hashCode(); + } +}; + + +// Intentionally outside namespace to avoid operator overloading confusion +inline G3D::Vector2 operator*(double s, const G3D::Vector2& v) { + return v * (float)s; +} +inline G3D::Vector2 operator*(int s, const G3D::Vector2& v) { + return v * (float)s; +} + +#endif diff --git a/externals/g3dlite/G3D/Vector2.inl b/externals/g3dlite/G3D/Vector2.inl new file mode 100644 index 00000000000..4f7c55a39cf --- /dev/null +++ b/externals/g3dlite/G3D/Vector2.inl @@ -0,0 +1,18 @@ +/** + @file Vector2.inl + + @maintainer Morgan McGuire, matrix@graphics3d.com + @cite Portions by Laura Wollstadt, graphics3d.com + + @cite Portions based on Dave Eberly'x Magic Software Library + at http://www.magic-software.com + + @created 2001-06-02 + @edited 2006-01-14 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +} + diff --git a/externals/g3dlite/G3D/Vector2int16.h b/externals/g3dlite/G3D/Vector2int16.h new file mode 100644 index 00000000000..ba72266d75a --- /dev/null +++ b/externals/g3dlite/G3D/Vector2int16.h @@ -0,0 +1,127 @@ +/** + @file Vector2int16.h + + @maintainer Morgan McGuire, matrix@brown.edu + + @created 2003-08-09 + @edited 2004-01-03 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef VECTOR2INT16_H +#define VECTOR2INT16_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/HashTrait.h" + +namespace G3D { + +/** + \class Vector2int16 + A Vector2 that packs its fields into uint16s. + */ +G3D_BEGIN_PACKED_CLASS(2) +class Vector2int16 { +private: + // Hidden operators + bool operator<(const Vector2int16&) const; + bool operator>(const Vector2int16&) const; + bool operator<=(const Vector2int16&) const; + bool operator>=(const Vector2int16&) const; + +public: + G3D::int16 x; + G3D::int16 y; + + Vector2int16() : x(0), y(0) {} + Vector2int16(G3D::int16 _x, G3D::int16 _y) : x(_x), y(_y){} + Vector2int16(const class Vector2& v); + Vector2int16(class BinaryInput& bi); + + inline G3D::int16& operator[] (int i) { + debugAssert(((unsigned int)i) <= 1); + return ((G3D::int16*)this)[i]; + } + + inline const G3D::int16& operator[] (int i) const { + debugAssert(((unsigned int)i) <= 1); + return ((G3D::int16*)this)[i]; + } + + inline Vector2int16 operator+(const Vector2int16& other) const { + return Vector2int16(x + other.x, y + other.y); + } + + inline Vector2int16 operator-(const Vector2int16& other) const { + return Vector2int16(x - other.x, y - other.y); + } + + inline Vector2int16 operator*(const Vector2int16& other) const { + return Vector2int16(x * other.x, y * other.y); + } + + inline Vector2int16 operator*(const int s) const { + return Vector2int16(x * s, y * s); + } + + inline Vector2int16& operator+=(const Vector2int16& other) { + x += other.x; + y += other.y; + return *this; + } + + /** Shifts both x and y */ + inline Vector2int16 operator>>(const int s) const { + return Vector2int16(x >> s, y >> s); + } + + /** Shifts both x and y */ + inline Vector2int16 operator<<(const int s) const { + return Vector2int16(x << s, y << s); + } + + inline Vector2int16& operator-=(const Vector2int16& other) { + x -= other.x; + y -= other.y; + return *this; + } + + inline Vector2int16& operator*=(const Vector2int16& other) { + x *= other.x; + y *= other.y; + return *this; + } + + Vector2int16 clamp(const Vector2int16& lo, const Vector2int16& hi); + + inline bool operator== (const Vector2int16& rkVector) const { + return ((int32*)this)[0] == ((int32*)&rkVector)[0]; + } + + inline bool operator!= (const Vector2int16& rkVector) const { + return ((int32*)this)[0] != ((int32*)&rkVector)[0]; + } + + Vector2int16 max(const Vector2int16& v) const { + return Vector2int16(iMax(x, v.x), iMax(y, v.y)); + } + + Vector2int16 min(const Vector2int16& v) const { + return Vector2int16(iMin(x, v.x), iMin(y, v.y)); + } + + void serialize(class BinaryOutput& bo) const; + void deserialize(class BinaryInput& bi); +} +G3D_END_PACKED_CLASS(2) + +} + +template<> struct HashTrait { + static size_t hashCode(const G3D::Vector2int16& key) { return static_cast(key.x + ((int)key.y << 16)); } +}; + +#endif diff --git a/externals/g3dlite/G3D/Vector3.h b/externals/g3dlite/G3D/Vector3.h new file mode 100644 index 00000000000..4825efb9985 --- /dev/null +++ b/externals/g3dlite/G3D/Vector3.h @@ -0,0 +1,798 @@ +/** + @file Vector3.h + + 3D vector class + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2001-06-02 + @edited 2009-11-01 + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_Vector3_h +#define G3D_Vector3_h + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Random.h" +#include "G3D/Vector2.h" +#include "G3D/Table.h" +#include "G3D/HashTrait.h" +#include "G3D/PositionTrait.h" +#include "G3D/Vector2.h" +#include +#include + +namespace G3D { + +class Vector2; +class Vector4; +class Vector4int8; +class Vector3int32; +class Any; + +/** + Swizzles + Vector classes have swizzle operators, e.g. v.xy(), that + allow selection of arbitrary sub-fields. These cannot be used as write + masks. Examples + +
+Vector3 v(1, 2, 3);
+Vector3 j;
+Vector2 b;
+
+b = v.xz();
+j = b.xx();
+
+ + + Warning + + Do not subclass-- this implementation makes assumptions about the + memory layout. + */ +class Vector3 { +public: + + // coordinates + float x, y, z; + +private: + + // Hidden operators + bool operator<(const Vector3&) const; + bool operator>(const Vector3&) const; + bool operator<=(const Vector3&) const; + bool operator>=(const Vector3&) const; + +public: + /** Initializes to zero */ + Vector3(); + + /** \param any Must either Vector3(#, #, #) or Vector3 {x = #, y = #, z = #}*/ + Vector3(const Any& any); + + /** Converts the Vector3 to an Any. */ + operator Any() const; + + /** Divides by 127 */ + Vector3(const Vector4int8&); + Vector3(const class Vector3int32& v); + explicit Vector3(class BinaryInput& b); + Vector3(float _x, float _y, float _z); + explicit Vector3(const class Vector2& v, float _z); + explicit Vector3(float coordinate[3]); + explicit Vector3(double coordinate[3]); + Vector3(const class Vector3int16& v); + explicit Vector3(class TextInput& t); + explicit Vector3(const class Color3& c); + + /** Format is three float32's */ + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + + /** Format is "(%f, %f, %f)" */ + void serialize(class TextOutput& t) const; + void deserialize(class TextInput& t); + + // access vector V as V[0] = V.x, V[1] = V.y, V[2] = V.z + // + // WARNING. These member functions rely on + // (1) Vector3 not having virtual functions + // (2) the data packed in a 3*sizeof(float) memory block + const float& __fastcall operator[] (int i) const; + float& operator[] (int i); + + enum Axis {X_AXIS=0, Y_AXIS=1, Z_AXIS=2, DETECT_AXIS=-1}; + + /** + Returns the largest dimension. Particularly convenient for determining + which plane to project a triangle onto for point-in-polygon tests. + */ + Axis primaryAxis() const; + + // assignment and comparison + Vector3& __fastcall operator= (const Vector3& rkVector); + bool operator== (const Vector3& rkVector) const; + bool operator!= (const Vector3& rkVector) const; + size_t hashCode() const; + bool fuzzyEq(const Vector3& other) const; + bool fuzzyNe(const Vector3& other) const; + + /** Returns true if this vector has finite length. */ + bool isFinite() const; + + /** Returns true if this vector has length ~= 0 */ + bool isZero() const; + + /** Returns true if this vector has length ~= 1 */ + bool isUnit() const; + + // arithmetic operations + Vector3 __fastcall operator+ (const Vector3& v) const; + Vector3 __fastcall operator- (const Vector3& v) const; + Vector3 __fastcall operator* (float s) const; + inline Vector3 __fastcall operator/ (float s) const { + return *this * (1.0f / s); + } + Vector3 __fastcall operator* (const Vector3& v) const; + Vector3 __fastcall operator/ (const Vector3& v) const; + Vector3 __fastcall operator- () const; + + // arithmetic updates + Vector3& __fastcall operator+= (const Vector3& v); + Vector3& __fastcall operator-= (const Vector3& v); + Vector3& __fastcall operator*= (float s); + inline Vector3& __fastcall operator/= (float s) { + return (*this *= (1.0f / s)); + } + Vector3& __fastcall operator*= (const Vector3& v); + Vector3& __fastcall operator/= (const Vector3& v); + + /** Same as magnitude */ + float length() const; + + float magnitude() const; + + /** + The result is a nan vector if the length is almost zero. + */ + Vector3 direction() const; + + /** + Potentially less accurate but faster than direction(). + Only works if System::hasSSE is true. + */ + Vector3 fastDirection() const; + + /** + Reflect this vector about the (not necessarily unit) normal. + Assumes that both the before and after vectors point away from + the base of the normal. + + Note that if used for a collision or ray reflection you + must negate the resulting vector to get a direction pointing + away from the collision. + +
+       V'    N      V
+                 
+         r   ^   -,
+          \  |  /
+            \|/
+     
+ + See also Vector3::reflectionDirection + */ + Vector3 reflectAbout(const Vector3& normal) const; + + /** + See also G3D::Ray::reflect. + The length is 1. +
+       V'    N       V
+                 
+         r   ^    /
+          \  |  /
+            \|'-
+     
+ */ + Vector3 reflectionDirection(const Vector3& normal) const; + + + /** + Returns Vector3::zero() if the length is nearly zero, otherwise + returns a unit vector. + */ + inline Vector3 directionOrZero() const { + float mag = magnitude(); + if (G3D::fuzzyEq(mag, 0.0f)) { + return Vector3::zero(); + } else if (G3D::fuzzyEq(mag, 1.0f)) { + return *this; + } else { + return *this * (1.0f / mag); + } + } + + /** + Returns the direction of a refracted ray, + where iExit is the index of refraction for the + previous material and iEnter is the index of refraction + for the new material. Like Vector3::reflectionDirection, + the result has length 1 and is + pointed away from the intersection. + + Returns Vector3::zero() in the case of total internal refraction. + + @param iOutside The index of refraction (eta) outside + (on the positive normal side) of the surface. + + @param iInside The index of refraction (eta) inside + (on the negative normal side) of the surface. + + See also G3D::Ray::refract. +
+              N      V
+                  
+              ^    /
+              |  /
+              |'-
+          __--
+     V'<--
+     
+ */ + Vector3 refractionDirection( + const Vector3& normal, + float iInside, + float iOutside) const; + + /** Synonym for direction */ + inline Vector3 unit() const { + return direction(); + } + + /** Returns a normalized vector. May be computed with lower + precision than unit */ + inline Vector3 fastUnit() const { + return fastDirection(); + } + + /** Same as squaredMagnitude */ + float squaredLength() const; + + float squaredMagnitude () const; + + float __fastcall dot(const Vector3& rkVector) const; + + float unitize(float tolerance = 1e-06); + + /** Cross product. Note that two cross products in a row + can be computed more cheaply: v1 x (v2 x v3) = (v1 dot v3) v2 - (v1 dot v2) v3. + */ + Vector3 __fastcall cross(const Vector3& rkVector) const; + Vector3 unitCross(const Vector3& rkVector) const; + + /** + Returns a matrix such that v.cross() * w = v.cross(w). +
+     [ 0  -v.z  v.y ]
+     [ v.z  0  -v.x ]
+     [ -v.y v.x  0  ]
+     
+ */ + class Matrix3 cross() const; + + Vector3 __fastcall min(const Vector3 &v) const; + Vector3 __fastcall max(const Vector3 &v) const; + + /** Smallest element */ + inline float min() const { + return G3D::min(G3D::min(x, y), z); + } + + /** Largest element */ + inline float max() const { + return G3D::max(G3D::max(x, y), z); + } + + std::string toString() const; + + inline Vector3 clamp(const Vector3& low, const Vector3& high) const { + return Vector3( + G3D::clamp(x, low.x, high.x), + G3D::clamp(y, low.y, high.y), + G3D::clamp(z, low.z, high.z)); + } + + inline Vector3 clamp(float low, float high) const { + return Vector3( + G3D::clamp(x, low, high), + G3D::clamp(y, low, high), + G3D::clamp(z, low, high)); + } + + /** + Linear interpolation + */ + inline Vector3 lerp(const Vector3& v, float alpha) const { + return (*this) + (v - *this) * alpha; + } + + /** Gram-Schmidt orthonormalization. */ + static void orthonormalize (Vector3 akVector[3]); + + /** \brief Random unit vector, uniformly distributed on the sphere. + + Distribution rendered by G3D::DirectionHistogram: + \image html vector3-random.png + */ + static Vector3 random(Random& r = Random::common()); + + /** \brief Random unit vector, distributed according to \f$\max(\cos \theta,0)\f$. + + That is, so that the probability of \f$\vec{V}\f$ is proportional + to \f$\max(\vec{v} \cdot \vec{n}, 0)\f$. Useful in photon mapping for + Lambertian scattering. + + Distribution rendered by G3D::DirectionHistogram: + \image html vector3-coshemirandom.png + + \param n Unit vector at the center of the distribution. + + @cite Henrik Wann Jensen, Realistic Image Synthesis using Photon Mapping eqn 2.24 + */ + static Vector3 cosHemiRandom(const Vector3& n, Random& r = Random::common()); + + /** \brief Random unit vector, distributed according to \f$\max(\cos^k \theta,0)\f$. + + That is, so that the probability of \f$\vec{V}\f$ is + proportional to \f$\max((\vec{v} \cdot \vec{n})^k, 0)\f$. + Useful in photon mapping for glossy scattering. + + Distribution rendered by G3D::DirectionHistogram: + \image html vector3-cospowhemirandom.png + + \param n Unit vector at the center of the distribution. + + @cite Ashikhmin and Shirley, An anisotropic Phong BRDF model, Journal of Graphics Tools, 2002 + */ + static Vector3 cosPowHemiRandom(const Vector3& n, const float k, Random& r = Random::common()); + + /** + \brief Random vector distributed over the hemisphere about normal. + + Distribution rendered by G3D::DirectionHistogram: + \image html vector3-hemirandom.png + */ + static Vector3 hemiRandom(const Vector3& normal, Random& r = Random::common()); + + /** Input W must be initialize to a nonzero vector, output is {U,V,W} + an orthonormal basis. A hint is provided about whether or not W + is already unit length. + @deprecated Use getTangents + */ + static void generateOrthonormalBasis (Vector3& rkU, Vector3& rkV, + Vector3& rkW, bool bUnitLengthW = true); + + inline float sum() const { + return x + y + z; + } + + inline float average() const { + return sum() / 3.0f; + } + + // Special values. + static const Vector3& zero(); + static const Vector3& one(); + static const Vector3& unitX(); + static const Vector3& unitY(); + static const Vector3& unitZ(); + static const Vector3& inf(); + static const Vector3& nan(); + + /** Smallest (most negative) representable vector */ + static const Vector3& minFinite(); + + /** Largest representable vector */ + static const Vector3& maxFinite(); + + + /** Creates two orthonormal tangent vectors X and Y such that + if Z = this, X x Y = Z.*/ + inline void getTangents(Vector3& X, Vector3& Y) const { + debugAssertM(G3D::fuzzyEq(length(), 1.0f), + "makeAxes requires Z to have unit length"); + + // Choose another vector not perpendicular + X = (abs(x) < 0.9f) ? Vector3::unitX() : Vector3::unitY(); + + // Remove the part that is parallel to Z + X -= *this * this->dot(X); + X /= X.length(); + + Y = this->cross(X); + } + + + // 2-char swizzles + + Vector2 xx() const; + Vector2 yx() const; + Vector2 zx() const; + Vector2 xy() const; + Vector2 yy() const; + Vector2 zy() const; + Vector2 xz() const; + Vector2 yz() const; + Vector2 zz() const; + + // 3-char swizzles + + Vector3 xxx() const; + Vector3 yxx() const; + Vector3 zxx() const; + Vector3 xyx() const; + Vector3 yyx() const; + Vector3 zyx() const; + Vector3 xzx() const; + Vector3 yzx() const; + Vector3 zzx() const; + Vector3 xxy() const; + Vector3 yxy() const; + Vector3 zxy() const; + Vector3 xyy() const; + Vector3 yyy() const; + Vector3 zyy() const; + Vector3 xzy() const; + Vector3 yzy() const; + Vector3 zzy() const; + Vector3 xxz() const; + Vector3 yxz() const; + Vector3 zxz() const; + Vector3 xyz() const; + Vector3 yyz() const; + Vector3 zyz() const; + Vector3 xzz() const; + Vector3 yzz() const; + Vector3 zzz() const; + + // 4-char swizzles + + Vector4 xxxx() const; + Vector4 yxxx() const; + Vector4 zxxx() const; + Vector4 xyxx() const; + Vector4 yyxx() const; + Vector4 zyxx() const; + Vector4 xzxx() const; + Vector4 yzxx() const; + Vector4 zzxx() const; + Vector4 xxyx() const; + Vector4 yxyx() const; + Vector4 zxyx() const; + Vector4 xyyx() const; + Vector4 yyyx() const; + Vector4 zyyx() const; + Vector4 xzyx() const; + Vector4 yzyx() const; + Vector4 zzyx() const; + Vector4 xxzx() const; + Vector4 yxzx() const; + Vector4 zxzx() const; + Vector4 xyzx() const; + Vector4 yyzx() const; + Vector4 zyzx() const; + Vector4 xzzx() const; + Vector4 yzzx() const; + Vector4 zzzx() const; + Vector4 xxxy() const; + Vector4 yxxy() const; + Vector4 zxxy() const; + Vector4 xyxy() const; + Vector4 yyxy() const; + Vector4 zyxy() const; + Vector4 xzxy() const; + Vector4 yzxy() const; + Vector4 zzxy() const; + Vector4 xxyy() const; + Vector4 yxyy() const; + Vector4 zxyy() const; + Vector4 xyyy() const; + Vector4 yyyy() const; + Vector4 zyyy() const; + Vector4 xzyy() const; + Vector4 yzyy() const; + Vector4 zzyy() const; + Vector4 xxzy() const; + Vector4 yxzy() const; + Vector4 zxzy() const; + Vector4 xyzy() const; + Vector4 yyzy() const; + Vector4 zyzy() const; + Vector4 xzzy() const; + Vector4 yzzy() const; + Vector4 zzzy() const; + Vector4 xxxz() const; + Vector4 yxxz() const; + Vector4 zxxz() const; + Vector4 xyxz() const; + Vector4 yyxz() const; + Vector4 zyxz() const; + Vector4 xzxz() const; + Vector4 yzxz() const; + Vector4 zzxz() const; + Vector4 xxyz() const; + Vector4 yxyz() const; + Vector4 zxyz() const; + Vector4 xyyz() const; + Vector4 yyyz() const; + Vector4 zyyz() const; + Vector4 xzyz() const; + Vector4 yzyz() const; + Vector4 zzyz() const; + Vector4 xxzz() const; + Vector4 yxzz() const; + Vector4 zxzz() const; + Vector4 xyzz() const; + Vector4 yyzz() const; + Vector4 zyzz() const; + Vector4 xzzz() const; + Vector4 yzzz() const; + Vector4 zzzz() const; + + /** Can be passed to ignore a vector3 parameter */ + static Vector3& ignore(); +}; + +inline G3D::Vector3 operator*(float s, const G3D::Vector3& v) { + return v * s; +} + +inline G3D::Vector3 operator*(double s, const G3D::Vector3& v) { + return v * (float)s; +} + +inline G3D::Vector3 operator*(int s, const G3D::Vector3& v) { + return v * (float)s; +} + +std::ostream& operator<<(std::ostream& os, const Vector3&); + + +void serialize(const Vector3::Axis& a, class BinaryOutput& bo); +void deserialize(Vector3::Axis& a, class BinaryInput& bo); + + +//---------------------------------------------------------------------------- +inline Vector3::Vector3() : x(0.0f), y(0.0f), z(0.0f) { +} + +//---------------------------------------------------------------------------- + +inline Vector3::Vector3 (float fX, float fY, float fZ) : x(fX), y(fY), z(fZ) { +} + +//---------------------------------------------------------------------------- +inline Vector3::Vector3 (float V[3]) : x(V[0]), y(V[1]), z(V[2]){ +} + +//---------------------------------------------------------------------------- +inline Vector3::Vector3 (double V[3]) : x((float)V[0]), y((float)V[1]), z((float)V[2]){ +} + +//---------------------------------------------------------------------------- +inline const float& Vector3::operator[] (int i) const { + return ((float*)this)[i]; +} + +inline float& Vector3::operator[] (int i) { + return ((float*)this)[i]; +} + + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator= (const Vector3& rkVector) { + x = rkVector.x; + y = rkVector.y; + z = rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- + +inline bool Vector3::fuzzyEq(const Vector3& other) const { + return G3D::fuzzyEq((*this - other).squaredMagnitude(), 0); +} + +//---------------------------------------------------------------------------- + +inline bool Vector3::fuzzyNe(const Vector3& other) const { + return G3D::fuzzyNe((*this - other).squaredMagnitude(), 0); +} + +//---------------------------------------------------------------------------- + +inline bool Vector3::isFinite() const { + return G3D::isFinite(x) && G3D::isFinite(y) && G3D::isFinite(z); +} + +//---------------------------------------------------------------------------- +inline bool Vector3::operator== (const Vector3& rkVector) const { + return ( x == rkVector.x && y == rkVector.y && z == rkVector.z ); +} + +//---------------------------------------------------------------------------- +inline bool Vector3::operator!= (const Vector3& rkVector) const { + return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator+ (const Vector3& rkVector) const { + return Vector3(x + rkVector.x, y + rkVector.y, z + rkVector.z); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator- (const Vector3& rkVector) const { + return Vector3(x - rkVector.x, y - rkVector.y, z - rkVector.z); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator* (const Vector3& rkVector) const { + return Vector3(x * rkVector.x, y * rkVector.y, z * rkVector.z); +} + +inline Vector3 Vector3::operator*(float f) const { + return Vector3(x * f, y * f, z * f); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator/ (const Vector3& rkVector) const { + return Vector3(x / rkVector.x, y / rkVector.y, z / rkVector.z); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator- () const { + return Vector3(-x, -y, -z); +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator+= (const Vector3& rkVector) { + x += rkVector.x; + y += rkVector.y; + z += rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator-= (const Vector3& rkVector) { + x -= rkVector.x; + y -= rkVector.y; + z -= rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator*= (float fScalar) { + x *= fScalar; + y *= fScalar; + z *= fScalar; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator*= (const Vector3& rkVector) { + x *= rkVector.x; + y *= rkVector.y; + z *= rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator/= (const Vector3& rkVector) { + x /= rkVector.x; + y /= rkVector.y; + z /= rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- +inline float Vector3::squaredMagnitude () const { + return x*x + y*y + z*z; +} + +//---------------------------------------------------------------------------- +inline float Vector3::squaredLength () const { + return squaredMagnitude(); +} + +//---------------------------------------------------------------------------- +inline float Vector3::magnitude() const { + return ::sqrtf(x*x + y*y + z*z); +} + +//---------------------------------------------------------------------------- +inline float Vector3::length() const { + return magnitude(); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::direction () const { + const float lenSquared = squaredMagnitude(); + const float invSqrt = 1.0f / sqrtf(lenSquared); + return Vector3(x * invSqrt, y * invSqrt, z * invSqrt); +} + +//---------------------------------------------------------------------------- + +inline Vector3 Vector3::fastDirection () const { + float lenSquared = x * x + y * y + z * z; + float invSqrt = rsq(lenSquared); + return Vector3(x * invSqrt, y * invSqrt, z * invSqrt); +} + +//---------------------------------------------------------------------------- +inline float Vector3::dot (const Vector3& rkVector) const { + return x*rkVector.x + y*rkVector.y + z*rkVector.z; +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::cross (const Vector3& rkVector) const { + return Vector3(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z, + x*rkVector.y - y*rkVector.x); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::unitCross (const Vector3& rkVector) const { + Vector3 kCross(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z, + x*rkVector.y - y*rkVector.x); + kCross.unitize(); + return kCross; +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::min(const Vector3 &v) const { + return Vector3(G3D::min(v.x, x), G3D::min(v.y, y), G3D::min(v.z, z)); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::max(const Vector3 &v) const { + return Vector3(G3D::max(v.x, x), G3D::max(v.y, y), G3D::max(v.z, z)); +} + +//---------------------------------------------------------------------------- +inline bool Vector3::isZero() const { + return G3D::fuzzyEq(squaredMagnitude(), 0.0f); +} + +//---------------------------------------------------------------------------- + +inline bool Vector3::isUnit() const { + return G3D::fuzzyEq(squaredMagnitude(), 1.0f); +} + +} // namespace G3D + + +template <> +struct HashTrait { + static size_t hashCode(const G3D::Vector3& key) { + return key.hashCode(); + } +}; + + +template<> struct PositionTrait { + static void getPosition(const G3D::Vector2& v, G3D::Vector3& p) { p = G3D::Vector3(v, 0); } +}; + +template<> struct PositionTrait { + static void getPosition(const G3D::Vector3& v, G3D::Vector3& p) { p = v; } +}; + + +#endif diff --git a/externals/g3dlite/G3D/Vector3.inl b/externals/g3dlite/G3D/Vector3.inl new file mode 100644 index 00000000000..9211c2a70fd --- /dev/null +++ b/externals/g3dlite/G3D/Vector3.inl @@ -0,0 +1,249 @@ +/** + @file Vector3.inl + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com + + @created 2001-06-02 + @edited 2004-05-21 + Copyright 2000-2004, Morgan McGuire. + All rights reserved. + */ + +//---------------------------------------------------------------------------- +#ifdef SSE + // If you receive an error on this line, it is because you do not have the file + // xmmintrin.h needed for MMX & SSE extensions. Download and install + // + // http://download.microsoft.com/download/vstudio60ent/SP5/Wideband-Full/WIN98Me/EN-US/vs6sp5.exe + // and + // http://download.microsoft.com/download/vb60ent/Update/6/W9X2KXP/EN-US/vcpp5.exe + // + // to get this file. +# include +#endif + +inline unsigned int hashCode(const G3D::Vector3& v) { + return v.hashCode(); +} + +namespace G3D { + +//---------------------------------------------------------------------------- +inline Vector3::Vector3() : x(0.0f), y(0.0f), z(0.0f) { +} + +//---------------------------------------------------------------------------- + +inline Vector3::Vector3 (float fX, float fY, float fZ) : x(fX), y(fY), z(fZ) { +} + +//---------------------------------------------------------------------------- +inline Vector3::Vector3 (float V[3]) : x(V[0]), y(V[1]), z(V[2]){ +} +//---------------------------------------------------------------------------- +inline Vector3::Vector3 (double V[3]) : x((float)V[0]), y((float)V[1]), z((float)V[2]){ +} + +//---------------------------------------------------------------------------- +inline Vector3::Vector3 (const Vector3& V) : x(V.x), y(V.y), z(V.z) { +} + +//---------------------------------------------------------------------------- + +//inline Vector3::Vector3 (const __m128& m) { + // Cast from SSE packed floats +// *this = *(Vector3*)&m; +//} + +//---------------------------------------------------------------------------- +inline const float& Vector3::operator[] (int i) const { + return ((float*)this)[i]; +} + +inline float& Vector3::operator[] (int i) { + return ((float*)this)[i]; +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator= (const Vector3& rkVector) { + x = rkVector.x; + y = rkVector.y; + z = rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- + +inline bool Vector3::fuzzyEq(const Vector3& other) const { + return G3D::fuzzyEq((*this - other).squaredMagnitude(), 0); +} + +//---------------------------------------------------------------------------- + +inline bool Vector3::fuzzyNe(const Vector3& other) const { + return G3D::fuzzyNe((*this - other).squaredMagnitude(), 0); +} + +//---------------------------------------------------------------------------- + +inline bool Vector3::isFinite() const { + return G3D::isFinite(x) && G3D::isFinite(y) && G3D::isFinite(z); +} + +//---------------------------------------------------------------------------- +inline bool Vector3::operator== (const Vector3& rkVector) const { + return ( x == rkVector.x && y == rkVector.y && z == rkVector.z ); +} + +//---------------------------------------------------------------------------- +inline bool Vector3::operator!= (const Vector3& rkVector) const { + return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator+ (const Vector3& rkVector) const { + return Vector3(x + rkVector.x, y + rkVector.y, z + rkVector.z); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator- (const Vector3& rkVector) const { + return Vector3(x - rkVector.x, y - rkVector.y, z - rkVector.z); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator* (const Vector3& rkVector) const { + return Vector3(x * rkVector.x, y * rkVector.y, z * rkVector.z); +} + +inline Vector3 Vector3::operator*(float f) const { + return Vector3(x * f, y * f, z * f); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator/ (const Vector3& rkVector) const { + return Vector3(x / rkVector.x, y / rkVector.y, z / rkVector.z); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::operator- () const { + return Vector3(-x, -y, -z); +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator+= (const Vector3& rkVector) { + x += rkVector.x; + y += rkVector.y; + z += rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator-= (const Vector3& rkVector) { + x -= rkVector.x; + y -= rkVector.y; + z -= rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator*= (float fScalar) { + x *= fScalar; + y *= fScalar; + z *= fScalar; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator*= (const Vector3& rkVector) { + x *= rkVector.x; + y *= rkVector.y; + z *= rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector3& Vector3::operator/= (const Vector3& rkVector) { + x /= rkVector.x; + y /= rkVector.y; + z /= rkVector.z; + return *this; +} + +//---------------------------------------------------------------------------- +inline float Vector3::squaredMagnitude () const { + return x*x + y*y + z*z; +} + +//---------------------------------------------------------------------------- +inline float Vector3::squaredLength () const { + return squaredMagnitude(); +} + +//---------------------------------------------------------------------------- +inline float Vector3::magnitude() const { + return sqrtf(x*x + y*y + z*z); +} + +//---------------------------------------------------------------------------- +inline float Vector3::length() const { + return magnitude(); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::direction () const { + float lenSquared = squaredMagnitude(); + float invSqrt = 1.0f / sqrtf(lenSquared); + return Vector3(x * invSqrt, y * invSqrt, z * invSqrt); +} + +//---------------------------------------------------------------------------- + +inline Vector3 Vector3::fastDirection () const { + float lenSquared = x * x + y * y + z * z; + float invSqrt = rsq(lenSquared); + return Vector3(x * invSqrt, y * invSqrt, z * invSqrt); +} + +//---------------------------------------------------------------------------- +inline float Vector3::dot (const Vector3& rkVector) const { + return x*rkVector.x + y*rkVector.y + z*rkVector.z; +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::cross (const Vector3& rkVector) const { + return Vector3(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z, + x*rkVector.y - y*rkVector.x); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::unitCross (const Vector3& rkVector) const { + Vector3 kCross(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z, + x*rkVector.y - y*rkVector.x); + kCross.unitize(); + return kCross; +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::min(const Vector3 &v) const { + return Vector3(G3D::min(v.x, x), G3D::min(v.y, y), G3D::min(v.z, z)); +} + +//---------------------------------------------------------------------------- +inline Vector3 Vector3::max(const Vector3 &v) const { + return Vector3(G3D::max(v.x, x), G3D::max(v.y, y), G3D::max(v.z, z)); +} + +//---------------------------------------------------------------------------- +inline bool Vector3::isZero() const { + return G3D::fuzzyEq(squaredMagnitude(), 0.0f); +} + +//---------------------------------------------------------------------------- + +inline bool Vector3::isUnit() const { + return G3D::fuzzyEq(squaredMagnitude(), 1.0f); +} + +} // namespace diff --git a/externals/g3dlite/G3D/Vector3int16.h b/externals/g3dlite/G3D/Vector3int16.h new file mode 100644 index 00000000000..3197ea49d1a --- /dev/null +++ b/externals/g3dlite/G3D/Vector3int16.h @@ -0,0 +1,127 @@ +/** + @file Vector3int16.h + + @maintainer Morgan McGuire, matrix@brown.edu + + @created 2003-04-07 + @edited 2003-06-24 + Copyright 2000-2004, Morgan McGuire. + All rights reserved. + */ + +#ifndef VECTOR3INT16_H +#define VECTOR3INT16_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/HashTrait.h" + +#ifdef _MSC_VER +// Turn off "conditional expression is constant" warning; MSVC generates this +// for debug assertions in inlined methods. +#pragma warning (disable : 4127) +#endif + + +namespace G3D { + +/** + \class Vector3int16 + A Vector3 that packs its fields into uint16s. + */ +G3D_BEGIN_PACKED_CLASS(2) +class Vector3int16 { +private: + // Hidden operators + bool operator<(const Vector3int16&) const; + bool operator>(const Vector3int16&) const; + bool operator<=(const Vector3int16&) const; + bool operator>=(const Vector3int16&) const; + +public: + G3D::int16 x; + G3D::int16 y; + G3D::int16 z; + + Vector3int16() : x(0), y(0), z(0) {} + Vector3int16(G3D::int16 _x, G3D::int16 _y, G3D::int16 _z) : x(_x), y(_y), z(_z) {} + Vector3int16(const class Vector3& v); + Vector3int16(class BinaryInput& bi); + + void serialize(class BinaryOutput& bo) const; + void deserialize(class BinaryInput& bi); + + inline G3D::int16& operator[] (int i) { + debugAssert(i <= 2); + return ((G3D::int16*)this)[i]; + } + + inline const G3D::int16& operator[] (int i) const { + debugAssert(i <= 2); + return ((G3D::int16*)this)[i]; + } + + inline Vector3int16 operator+(const Vector3int16& other) const { + return Vector3int16(x + other.x, y + other.y, z + other.z); + } + + inline Vector3int16 operator-(const Vector3int16& other) const { + return Vector3int16(x - other.x, y - other.y, z - other.z); + } + + inline Vector3int16 operator*(const Vector3int16& other) const { + return Vector3int16(x * other.x, y * other.y, z * other.z); + } + + inline Vector3int16 operator*(const int s) const { + return Vector3int16(int16(x * s), int16(y * s), int16(z * s)); + } + + inline Vector3int16& operator+=(const Vector3int16& other) { + x += other.x; + y += other.y; + z += other.y; + return *this; + } + + inline Vector3int16& operator-=(const Vector3int16& other) { + x -= other.x; + y -= other.y; + z -= other.z; + return *this; + } + + inline Vector3int16& operator*=(const Vector3int16& other) { + x *= other.x; + y *= other.y; + z *= other.z; + return *this; + } + + inline bool operator== (const Vector3int16& rkVector) const { + return ( x == rkVector.x && y == rkVector.y && z == rkVector.z ); + } + + inline bool operator!= (const Vector3int16& rkVector) const { + return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); + } + + Vector3int16 max(const Vector3int16& v) const { + return Vector3int16(std::max(x, v.x), std::max(y, v.y), std::max(z, v.z)); + } + + Vector3int16 min(const Vector3int16& v) const { + return Vector3int16(std::min(x, v.x), std::min(y, v.y), std::min(z, v.z)); + } + + std::string toString() const; +} +G3D_END_PACKED_CLASS(2) + +} + +template <> struct HashTrait { + static size_t hashCode(const G3D::Vector3int16& key) { return static_cast(key.x + ((int)key.y << 5) + ((int)key.z << 10)); } +}; + +#endif diff --git a/externals/g3dlite/G3D/Vector3int32.h b/externals/g3dlite/G3D/Vector3int32.h new file mode 100644 index 00000000000..2f256ea0300 --- /dev/null +++ b/externals/g3dlite/G3D/Vector3int32.h @@ -0,0 +1,128 @@ +/** + @file Vector3int32.h + + @maintainer Morgan McGuire, matrix@brown.edu + + @created 2008-07-01 + @edited 2008-07-01 + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef VECTOR3INT32_H +#define VECTOR3INT32_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/HashTrait.h" + +namespace G3D { + +/** + \ Vector3int32 + A Vector3 that packs its fields into uint32s. + */ +G3D_BEGIN_PACKED_CLASS(4) +class Vector3int32 { +private: + // Hidden operators + bool operator<(const Vector3int32&) const; + bool operator>(const Vector3int32&) const; + bool operator<=(const Vector3int32&) const; + bool operator>=(const Vector3int32&) const; + +public: + G3D::int32 x; + G3D::int32 y; + G3D::int32 z; + + Vector3int32() : x(0), y(0), z(0) {} + Vector3int32(int _x, int _y, int _z) : x(_x), y(_y), z(_z) {} + Vector3int32(const class Vector3int16& v); + Vector3int32(const class Vector3& v); + Vector3int32(class BinaryInput& bi); + + void serialize(class BinaryOutput& bo) const; + void deserialize(class BinaryInput& bi); + + inline G3D::int32& operator[] (int i) { + debugAssert(i <= 2); + return ((G3D::int32*)this)[i]; + } + + inline const G3D::int32& operator[] (int i) const { + debugAssert(i <= 2); + return ((G3D::int32*)this)[i]; + } + + inline Vector3int32 operator+(const Vector3int32& other) const { + return Vector3int32(x + other.x, y + other.y, z + other.z); + } + + inline Vector3int32 operator-(const Vector3int32& other) const { + return Vector3int32(x - other.x, y - other.y, z - other.z); + } + + inline Vector3int32 operator*(const Vector3int32& other) const { + return Vector3int32(x * other.x, y * other.y, z * other.z); + } + + inline Vector3int32 operator*(const int s) const { + return Vector3int32(x * s, y * s, z * s); + } + + inline Vector3int32& operator+=(const Vector3int32& other) { + x += other.x; + y += other.y; + z += other.y; + return *this; + } + + inline Vector3int32& operator-=(const Vector3int32& other) { + x -= other.x; + y -= other.y; + z -= other.z; + return *this; + } + + inline Vector3int32& operator*=(const Vector3int32& other) { + x *= other.x; + y *= other.y; + z *= other.z; + return *this; + } + + inline bool operator== (const Vector3int32& rkVector) const { + return ( x == rkVector.x && y == rkVector.y && z == rkVector.z ); + } + + inline bool operator!= (const Vector3int32& rkVector) const { + return ( x != rkVector.x || y != rkVector.y || z != rkVector.z ); + } + + Vector3int32 max(const Vector3int32& v) const { + return Vector3int32(iMax(x, v.x), iMax(y, v.y), iMax(z, v.z)); + } + + Vector3int32 min(const Vector3int32& v) const { + return Vector3int32(iMin(x, v.x), iMin(y, v.y), iMin(z, v.z)); + } + + std::string toString() const; +} +G3D_END_PACKED_CLASS(4) + +} + +template <> struct HashTrait { + static size_t hashCode(const G3D::Vector3int32& key) { + // Mask for the top bit of a uint32 + const G3D::uint32 top = (1UL << 31); + // Mask for the bottom 10 bits of a uint32 + const G3D::uint32 bot = 0x000003FF; + return static_cast(((key.x & top) | ((key.y & top) >> 1) | ((key.z & top) >> 2)) | + (((key.x & bot) << 19) ^ ((key.y & bot) << 10) ^ (key.z & bot))); + } +}; + +#endif diff --git a/externals/g3dlite/G3D/Vector4.h b/externals/g3dlite/G3D/Vector4.h new file mode 100644 index 00000000000..5e511451f86 --- /dev/null +++ b/externals/g3dlite/G3D/Vector4.h @@ -0,0 +1,716 @@ +/** + @file Vector4.h + + Homogeneous vector class. + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2002-07-09 + @edited 2008-11-01 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_Vector4_h +#define G3D_Vector4_h + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Vector3.h" +#include "G3D/Vector2.h" +#include "G3D/Table.h" +#include "G3D/HashTrait.h" +#include "G3D/PositionTrait.h" +#include + +namespace G3D { + +class Vector2; +class Vector3; +class Vector4; +class Vector4int8; +class Any; + +/** + Do not subclass-- this implementation makes assumptions about the + memory layout. + */ +class Vector4 { +private: + // Hidden operators + bool operator<(const Vector4&) const; + bool operator>(const Vector4&) const; + bool operator<=(const Vector4&) const; + bool operator>=(const Vector4&) const; + +public: + + /** \param any Must either Vector4(#, #, #, #) or Vector3 {x = #, y = #, z = #, w =#}*/ + Vector4(const Any& any); + + /** Converts the Vector4 to an Any. */ + operator Any() const; + + // construction + Vector4(); + Vector4(float fX, float fY, float fZ, float fW); + Vector4(float afCoordinate[4]); + Vector4(const Vector4& rkVector); + Vector4(const class Color4& c); + Vector4(const Vector3& rkVector, float fW); + Vector4(const Vector2& v1, const Vector2& v2); + Vector4(const Vector2& v1, float fz, float fw); + + /** Divides by 127 when converting */ + Vector4(const Vector4int8&); + + Vector4(class BinaryInput& b); + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + + // coordinates + float x, y, z, w; + + // access vector V as V[0] = V.x, V[1] = V.y, V[2] = V.z, etc. + // + // WARNING. These member functions rely on + // (1) Vector4 not having virtual functions + // (2) the data packed in a 4*sizeof(float) memory block + float& operator[] (int i); + const float& operator[] (int i) const; + + // assignment and comparison + Vector4& operator= (const Vector4& rkVector); + bool operator== (const Vector4& rkVector) const; + bool operator!= (const Vector4& rkVector) const; + + static const Vector4& zero(); + + inline void set(float _x, float _y, float _z, float _w) { + x = _x; + y = _y; + z = _z; + w = _w; + } + + inline void set(const Vector3& v, float _w) { + x = v.x; + y = v.y; + z = v.z; + w = _w; + } + + inline void set(const Vector2& v, float _z, float _w) { + x = v.x; + y = v.y; + z = _z; + w = _w; + } + + size_t hashCode() const; + bool fuzzyEq(const Vector4& other) const; + bool fuzzyNe(const Vector4& other) const; + + static const Vector4& inf(); + static const Vector4& nan(); + + /** sqrt(this->dot(*this)) */ + float length() const; + float squaredLength() const; + + inline float sum() const { + return x + y + z + w; + } + + /** Returns true if this vector has finite length */ + bool isFinite() const; + + /** Returns true if this vector has length == 0 */ + bool isZero() const; + + /** Returns true if this vector has length == 1 */ + bool isUnit() const; + + // arithmetic operations + Vector4 operator+ (const Vector4& rkVector) const; + Vector4 operator- (const Vector4& rkVector) const; + + inline Vector4 operator*(const Vector4& rkVector) const { + return Vector4(x * rkVector.x, y * rkVector.y, z * rkVector.z, w * rkVector.w); + } + + inline Vector4 operator/(const Vector4& rkVector) const { + return Vector4(x / rkVector.x, y / rkVector.y, z / rkVector.z, w / rkVector.w); + } + + Vector4 operator*(const class Matrix4& M) const; + + Vector4 operator* (float fScalar) const; + Vector4 operator/ (float fScalar) const; + Vector4 operator- () const; + friend Vector4 operator* (float, const Vector4& rkVector); + + // arithmetic updates + Vector4& operator+= (const Vector4& rkVector); + Vector4& operator-= (const Vector4& rkVector); + Vector4& operator*= (float fScalar); + Vector4& operator/= (float fScalar); + + inline Vector4 clamp(const Vector4& low, const Vector4& high) const { + return Vector4( + G3D::clamp(x, low.x, high.x), + G3D::clamp(y, low.y, high.y), + G3D::clamp(z, low.z, high.z), + G3D::clamp(w, low.w, high.w)); + } + + inline Vector4 clamp(float low, float high) const { + return Vector4( + G3D::clamp(x, low, high), + G3D::clamp(y, low, high), + G3D::clamp(z, low, high), + G3D::clamp(w, low, high)); + } + + float dot (const Vector4& rkVector) const; + + Vector4 min(const Vector4& v) const; + Vector4 max(const Vector4& v) const; + + std::string toString() const; + + /** + Linear interpolation + */ + Vector4 lerp(const Vector4& v, float alpha) const; + + // 2-char swizzles + + Vector2 xx() const; + Vector2 yx() const; + Vector2 zx() const; + Vector2 wx() const; + Vector2 xy() const; + Vector2 yy() const; + Vector2 zy() const; + Vector2 wy() const; + Vector2 xz() const; + Vector2 yz() const; + Vector2 zz() const; + Vector2 wz() const; + Vector2 xw() const; + Vector2 yw() const; + Vector2 zw() const; + Vector2 ww() const; + + // 3-char swizzles + + Vector3 xxx() const; + Vector3 yxx() const; + Vector3 zxx() const; + Vector3 wxx() const; + Vector3 xyx() const; + Vector3 yyx() const; + Vector3 zyx() const; + Vector3 wyx() const; + Vector3 xzx() const; + Vector3 yzx() const; + Vector3 zzx() const; + Vector3 wzx() const; + Vector3 xwx() const; + Vector3 ywx() const; + Vector3 zwx() const; + Vector3 wwx() const; + Vector3 xxy() const; + Vector3 yxy() const; + Vector3 zxy() const; + Vector3 wxy() const; + Vector3 xyy() const; + Vector3 yyy() const; + Vector3 zyy() const; + Vector3 wyy() const; + Vector3 xzy() const; + Vector3 yzy() const; + Vector3 zzy() const; + Vector3 wzy() const; + Vector3 xwy() const; + Vector3 ywy() const; + Vector3 zwy() const; + Vector3 wwy() const; + Vector3 xxz() const; + Vector3 yxz() const; + Vector3 zxz() const; + Vector3 wxz() const; + Vector3 xyz() const; + Vector3 yyz() const; + Vector3 zyz() const; + Vector3 wyz() const; + Vector3 xzz() const; + Vector3 yzz() const; + Vector3 zzz() const; + Vector3 wzz() const; + Vector3 xwz() const; + Vector3 ywz() const; + Vector3 zwz() const; + Vector3 wwz() const; + Vector3 xxw() const; + Vector3 yxw() const; + Vector3 zxw() const; + Vector3 wxw() const; + Vector3 xyw() const; + Vector3 yyw() const; + Vector3 zyw() const; + Vector3 wyw() const; + Vector3 xzw() const; + Vector3 yzw() const; + Vector3 zzw() const; + Vector3 wzw() const; + Vector3 xww() const; + Vector3 yww() const; + Vector3 zww() const; + Vector3 www() const; + + // 4-char swizzles + + Vector4 xxxx() const; + Vector4 yxxx() const; + Vector4 zxxx() const; + Vector4 wxxx() const; + Vector4 xyxx() const; + Vector4 yyxx() const; + Vector4 zyxx() const; + Vector4 wyxx() const; + Vector4 xzxx() const; + Vector4 yzxx() const; + Vector4 zzxx() const; + Vector4 wzxx() const; + Vector4 xwxx() const; + Vector4 ywxx() const; + Vector4 zwxx() const; + Vector4 wwxx() const; + Vector4 xxyx() const; + Vector4 yxyx() const; + Vector4 zxyx() const; + Vector4 wxyx() const; + Vector4 xyyx() const; + Vector4 yyyx() const; + Vector4 zyyx() const; + Vector4 wyyx() const; + Vector4 xzyx() const; + Vector4 yzyx() const; + Vector4 zzyx() const; + Vector4 wzyx() const; + Vector4 xwyx() const; + Vector4 ywyx() const; + Vector4 zwyx() const; + Vector4 wwyx() const; + Vector4 xxzx() const; + Vector4 yxzx() const; + Vector4 zxzx() const; + Vector4 wxzx() const; + Vector4 xyzx() const; + Vector4 yyzx() const; + Vector4 zyzx() const; + Vector4 wyzx() const; + Vector4 xzzx() const; + Vector4 yzzx() const; + Vector4 zzzx() const; + Vector4 wzzx() const; + Vector4 xwzx() const; + Vector4 ywzx() const; + Vector4 zwzx() const; + Vector4 wwzx() const; + Vector4 xxwx() const; + Vector4 yxwx() const; + Vector4 zxwx() const; + Vector4 wxwx() const; + Vector4 xywx() const; + Vector4 yywx() const; + Vector4 zywx() const; + Vector4 wywx() const; + Vector4 xzwx() const; + Vector4 yzwx() const; + Vector4 zzwx() const; + Vector4 wzwx() const; + Vector4 xwwx() const; + Vector4 ywwx() const; + Vector4 zwwx() const; + Vector4 wwwx() const; + Vector4 xxxy() const; + Vector4 yxxy() const; + Vector4 zxxy() const; + Vector4 wxxy() const; + Vector4 xyxy() const; + Vector4 yyxy() const; + Vector4 zyxy() const; + Vector4 wyxy() const; + Vector4 xzxy() const; + Vector4 yzxy() const; + Vector4 zzxy() const; + Vector4 wzxy() const; + Vector4 xwxy() const; + Vector4 ywxy() const; + Vector4 zwxy() const; + Vector4 wwxy() const; + Vector4 xxyy() const; + Vector4 yxyy() const; + Vector4 zxyy() const; + Vector4 wxyy() const; + Vector4 xyyy() const; + Vector4 yyyy() const; + Vector4 zyyy() const; + Vector4 wyyy() const; + Vector4 xzyy() const; + Vector4 yzyy() const; + Vector4 zzyy() const; + Vector4 wzyy() const; + Vector4 xwyy() const; + Vector4 ywyy() const; + Vector4 zwyy() const; + Vector4 wwyy() const; + Vector4 xxzy() const; + Vector4 yxzy() const; + Vector4 zxzy() const; + Vector4 wxzy() const; + Vector4 xyzy() const; + Vector4 yyzy() const; + Vector4 zyzy() const; + Vector4 wyzy() const; + Vector4 xzzy() const; + Vector4 yzzy() const; + Vector4 zzzy() const; + Vector4 wzzy() const; + Vector4 xwzy() const; + Vector4 ywzy() const; + Vector4 zwzy() const; + Vector4 wwzy() const; + Vector4 xxwy() const; + Vector4 yxwy() const; + Vector4 zxwy() const; + Vector4 wxwy() const; + Vector4 xywy() const; + Vector4 yywy() const; + Vector4 zywy() const; + Vector4 wywy() const; + Vector4 xzwy() const; + Vector4 yzwy() const; + Vector4 zzwy() const; + Vector4 wzwy() const; + Vector4 xwwy() const; + Vector4 ywwy() const; + Vector4 zwwy() const; + Vector4 wwwy() const; + Vector4 xxxz() const; + Vector4 yxxz() const; + Vector4 zxxz() const; + Vector4 wxxz() const; + Vector4 xyxz() const; + Vector4 yyxz() const; + Vector4 zyxz() const; + Vector4 wyxz() const; + Vector4 xzxz() const; + Vector4 yzxz() const; + Vector4 zzxz() const; + Vector4 wzxz() const; + Vector4 xwxz() const; + Vector4 ywxz() const; + Vector4 zwxz() const; + Vector4 wwxz() const; + Vector4 xxyz() const; + Vector4 yxyz() const; + Vector4 zxyz() const; + Vector4 wxyz() const; + Vector4 xyyz() const; + Vector4 yyyz() const; + Vector4 zyyz() const; + Vector4 wyyz() const; + Vector4 xzyz() const; + Vector4 yzyz() const; + Vector4 zzyz() const; + Vector4 wzyz() const; + Vector4 xwyz() const; + Vector4 ywyz() const; + Vector4 zwyz() const; + Vector4 wwyz() const; + Vector4 xxzz() const; + Vector4 yxzz() const; + Vector4 zxzz() const; + Vector4 wxzz() const; + Vector4 xyzz() const; + Vector4 yyzz() const; + Vector4 zyzz() const; + Vector4 wyzz() const; + Vector4 xzzz() const; + Vector4 yzzz() const; + Vector4 zzzz() const; + Vector4 wzzz() const; + Vector4 xwzz() const; + Vector4 ywzz() const; + Vector4 zwzz() const; + Vector4 wwzz() const; + Vector4 xxwz() const; + Vector4 yxwz() const; + Vector4 zxwz() const; + Vector4 wxwz() const; + Vector4 xywz() const; + Vector4 yywz() const; + Vector4 zywz() const; + Vector4 wywz() const; + Vector4 xzwz() const; + Vector4 yzwz() const; + Vector4 zzwz() const; + Vector4 wzwz() const; + Vector4 xwwz() const; + Vector4 ywwz() const; + Vector4 zwwz() const; + Vector4 wwwz() const; + Vector4 xxxw() const; + Vector4 yxxw() const; + Vector4 zxxw() const; + Vector4 wxxw() const; + Vector4 xyxw() const; + Vector4 yyxw() const; + Vector4 zyxw() const; + Vector4 wyxw() const; + Vector4 xzxw() const; + Vector4 yzxw() const; + Vector4 zzxw() const; + Vector4 wzxw() const; + Vector4 xwxw() const; + Vector4 ywxw() const; + Vector4 zwxw() const; + Vector4 wwxw() const; + Vector4 xxyw() const; + Vector4 yxyw() const; + Vector4 zxyw() const; + Vector4 wxyw() const; + Vector4 xyyw() const; + Vector4 yyyw() const; + Vector4 zyyw() const; + Vector4 wyyw() const; + Vector4 xzyw() const; + Vector4 yzyw() const; + Vector4 zzyw() const; + Vector4 wzyw() const; + Vector4 xwyw() const; + Vector4 ywyw() const; + Vector4 zwyw() const; + Vector4 wwyw() const; + Vector4 xxzw() const; + Vector4 yxzw() const; + Vector4 zxzw() const; + Vector4 wxzw() const; + Vector4 xyzw() const; + Vector4 yyzw() const; + Vector4 zyzw() const; + Vector4 wyzw() const; + Vector4 xzzw() const; + Vector4 yzzw() const; + Vector4 zzzw() const; + Vector4 wzzw() const; + Vector4 xwzw() const; + Vector4 ywzw() const; + Vector4 zwzw() const; + Vector4 wwzw() const; + Vector4 xxww() const; + Vector4 yxww() const; + Vector4 zxww() const; + Vector4 wxww() const; + Vector4 xyww() const; + Vector4 yyww() const; + Vector4 zyww() const; + Vector4 wyww() const; + Vector4 xzww() const; + Vector4 yzww() const; + Vector4 zzww() const; + Vector4 wzww() const; + Vector4 xwww() const; + Vector4 ywww() const; + Vector4 zwww() const; + Vector4 wwww() const; + +}; + + +//---------------------------------------------------------------------------- +inline Vector4::Vector4() { + x = y = z = w = 0; +} + +//---------------------------------------------------------------------------- + +inline Vector4::Vector4 (float fX, float fY, float fZ, float fW) { + x = fX; + y = fY; + z = fZ; + w = fW; +} + +//---------------------------------------------------------------------------- +inline Vector4::Vector4 (float afCoordinate[4]) { + x = afCoordinate[0]; + y = afCoordinate[1]; + z = afCoordinate[2]; + w = afCoordinate[3]; +} + +//---------------------------------------------------------------------------- +inline Vector4::Vector4(const Vector4& rkVector) { + x = rkVector.x; + y = rkVector.y; + z = rkVector.z; + w = rkVector.w; +} +//---------------------------------------------------------------------------- +inline Vector4::Vector4(const Vector3& rkVector, float fW) { + x = rkVector.x; + y = rkVector.y; + z = rkVector.z; + w = fW; +} + +//---------------------------------------------------------------------------- +inline float& Vector4::operator[] (int i) { + return ((float*)this)[i]; +} + +//---------------------------------------------------------------------------- +inline const float& Vector4::operator[] (int i) const { + return ((float*)this)[i]; +} + +//---------------------------------------------------------------------------- +inline Vector4& Vector4::operator= (const Vector4& rkVector) { + x = rkVector.x; + y = rkVector.y; + z = rkVector.z; + w = rkVector.w; + return *this; +} + +//---------------------------------------------------------------------------- +inline bool Vector4::operator== (const Vector4& rkVector) const { + return ( (x == rkVector.x) && (y == rkVector.y) && (z == rkVector.z) && (w == rkVector.w)); +} + +//---------------------------------------------------------------------------- +inline bool Vector4::operator!= (const Vector4& rkVector) const { + return ( x != rkVector.x || y != rkVector.y || z != rkVector.z || w != rkVector.w); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::operator+ (const Vector4& rkVector) const { + return Vector4(x + rkVector.x, y + rkVector.y, z + rkVector.z, w + rkVector.w); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::operator- (const Vector4& rkVector) const { + return Vector4(x - rkVector.x, y - rkVector.y, z - rkVector.z, w - rkVector.w); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::operator* (float fScalar) const { + return Vector4(fScalar*x, fScalar*y, fScalar*z, fScalar*w); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::operator- () const { + return Vector4( -x, -y, -z, -w); +} + +//---------------------------------------------------------------------------- +inline Vector4& Vector4::operator+= (const Vector4& rkVector) { + x += rkVector.x; + y += rkVector.y; + z += rkVector.z; + w += rkVector.w; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector4& Vector4::operator-= (const Vector4& rkVector) { + x -= rkVector.x; + y -= rkVector.y; + z -= rkVector.z; + w -= rkVector.w; + return *this; +} + +//---------------------------------------------------------------------------- + +inline Vector4 Vector4::lerp(const Vector4& v, float alpha) const { + return (*this) + (v - *this) * alpha; +} + + +//---------------------------------------------------------------------------- +inline Vector4& Vector4::operator*= (float fScalar) { + x *= fScalar; + y *= fScalar; + z *= fScalar; + w *= fScalar; + return *this; +} + + +//---------------------------------------------------------------------------- +inline float Vector4::dot(const Vector4& rkVector) const { + return x*rkVector.x + y*rkVector.y + z*rkVector.z + w*rkVector.w; +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::min(const Vector4 &v) const { + return Vector4(G3D::min(v.x, x), G3D::min(v.y, y), G3D::min(v.z, z), G3D::min(v.w, w)); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::max(const Vector4 &v) const { + return Vector4(G3D::max(v.x, x), G3D::max(v.y, y), G3D::max(v.z, z), G3D::max(v.w, w)); +} + +//---------------------------------------------------------------------------- +inline bool Vector4::isZero() const { + return (x == 0.0f) && (y == 0.0f) && (z == 0.0f) && (w == 0.0f); +} + +//---------------------------------------------------------------------------- + +inline bool Vector4::isFinite() const { + return G3D::isFinite(x) && G3D::isFinite(y) && G3D::isFinite(z) && G3D::isFinite(w); +} + +//---------------------------------------------------------------------------- + +inline bool Vector4::isUnit() const { + return squaredLength() == 1.0; +} + +//---------------------------------------------------------------------------- + +inline float Vector4::length() const { + return sqrtf(squaredLength()); +} + +//---------------------------------------------------------------------------- + +inline float Vector4::squaredLength() const { + return x * x + y * y + z * z + w * w; +} + +} + +template <> struct HashTrait { + static size_t hashCode(const G3D::Vector4& key) { return key.hashCode(); } +}; + + +template<> struct PositionTrait { + static void getPosition(const G3D::Vector4& v, G3D::Vector3& p) { p = v.xyz(); } +}; + +inline G3D::Vector4 operator* (float s, const G3D::Vector4& v) { + return v * s; +} + +#endif diff --git a/externals/g3dlite/G3D/Vector4.inl b/externals/g3dlite/G3D/Vector4.inl new file mode 100644 index 00000000000..576cca83b56 --- /dev/null +++ b/externals/g3dlite/G3D/Vector4.inl @@ -0,0 +1,191 @@ +/** + @file Vector4.inl + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2002-07-09 + @edited 2003-02-10 + */ + +//---------------------------------------------------------------------------- + +inline unsigned int hashCode(const G3D::Vector4& v) { + return v.hashCode(); +} + +namespace G3D { + +//---------------------------------------------------------------------------- +inline Vector4::Vector4() { + x = y = z = w = 0; +} + +//---------------------------------------------------------------------------- + +inline Vector4::Vector4 (float fX, float fY, float fZ, float fW) { + x = fX; + y = fY; + z = fZ; + w = fW; +} + +//---------------------------------------------------------------------------- +inline Vector4::Vector4 (float afCoordinate[4]) { + x = afCoordinate[0]; + y = afCoordinate[1]; + z = afCoordinate[2]; + w = afCoordinate[3]; +} + +//---------------------------------------------------------------------------- +inline Vector4::Vector4(const Vector4& rkVector) { + x = rkVector.x; + y = rkVector.y; + z = rkVector.z; + w = rkVector.w; +} +//---------------------------------------------------------------------------- +inline Vector4::Vector4(const Vector3& rkVector, float fW) { + x = rkVector.x; + y = rkVector.y; + z = rkVector.z; + w = fW; +} + +//---------------------------------------------------------------------------- +inline float& Vector4::operator[] (int i) { + return ((float*)this)[i]; +} + +//---------------------------------------------------------------------------- +inline const float& Vector4::operator[] (int i) const { + return ((float*)this)[i]; +} + +//---------------------------------------------------------------------------- +inline Vector4::operator float* () { + return (float*)this; +} + +inline Vector4::operator const float* () const { + return (float*)this; +} + +//---------------------------------------------------------------------------- +inline Vector4& Vector4::operator= (const Vector4& rkVector) { + x = rkVector.x; + y = rkVector.y; + z = rkVector.z; + w = rkVector.w; + return *this; +} + +//---------------------------------------------------------------------------- +inline bool Vector4::operator== (const Vector4& rkVector) const { + return ( (x == rkVector.x) && (y == rkVector.y) && (z == rkVector.z) && (w == rkVector.w)); +} + +//---------------------------------------------------------------------------- +inline bool Vector4::operator!= (const Vector4& rkVector) const { + return ( x != rkVector.x || y != rkVector.y || z != rkVector.z || w != rkVector.w); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::operator+ (const Vector4& rkVector) const { + return Vector4(x + rkVector.x, y + rkVector.y, z + rkVector.z, w + rkVector.w); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::operator- (const Vector4& rkVector) const { + return Vector4(x - rkVector.x, y - rkVector.y, z - rkVector.z, w - rkVector.w); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::operator* (float fScalar) const { + return Vector4(fScalar*x, fScalar*y, fScalar*z, fScalar*w); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::operator- () const { + return Vector4( -x, -y, -z, -w); +} + +//---------------------------------------------------------------------------- +inline Vector4& Vector4::operator+= (const Vector4& rkVector) { + x += rkVector.x; + y += rkVector.y; + z += rkVector.z; + w += rkVector.w; + return *this; +} + +//---------------------------------------------------------------------------- +inline Vector4& Vector4::operator-= (const Vector4& rkVector) { + x -= rkVector.x; + y -= rkVector.y; + z -= rkVector.z; + w -= rkVector.w; + return *this; +} + +//---------------------------------------------------------------------------- + +inline Vector4 Vector4::lerp(const Vector4& v, float alpha) const { + return (*this) + (v - *this) * alpha; +} + +//---------------------------------------------------------------------------- +inline Vector4& Vector4::operator*= (float fScalar) { + x *= fScalar; + y *= fScalar; + z *= fScalar; + w *= fScalar; + return *this; +} + +//---------------------------------------------------------------------------- +inline float Vector4::dot(const Vector4& rkVector) const { + return x*rkVector.x + y*rkVector.y + z*rkVector.z + w*rkVector.w; +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::min(const Vector4 &v) const { + return Vector4(G3D::min(v.x, x), G3D::min(v.y, y), G3D::min(v.z, z), G3D::min(v.w, w)); +} + +//---------------------------------------------------------------------------- +inline Vector4 Vector4::max(const Vector4 &v) const { + return Vector4(G3D::max(v.x, x), G3D::max(v.y, y), G3D::max(v.z, z), G3D::max(v.w, w)); +} + +//---------------------------------------------------------------------------- +inline bool Vector4::isZero() const { + return (x == 0.0f) && (y == 0.0f) && (z == 0.0f) && (w == 0.0f); +} + +//---------------------------------------------------------------------------- + +inline bool Vector4::isFinite() const { + return G3D::isFinite(x) && G3D::isFinite(y) && G3D::isFinite(z) && G3D::isFinite(w); +} + +//---------------------------------------------------------------------------- + +inline bool Vector4::isUnit() const { + return squaredLength() == 1.0; +} + +//---------------------------------------------------------------------------- + +inline float Vector4::length() const { + return sqrtf(squaredLength()); +} + +//---------------------------------------------------------------------------- + +inline float Vector4::squaredLength() const { + return x * x + y * y + z * z + w * w; +} + +} + diff --git a/externals/g3dlite/G3D/Vector4int8.h b/externals/g3dlite/G3D/Vector4int8.h new file mode 100644 index 00000000000..544b693e8b3 --- /dev/null +++ b/externals/g3dlite/G3D/Vector4int8.h @@ -0,0 +1,113 @@ +/** + @file Vector4int8.h + + Homogeneous vector class. + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2007-02-09 + @edited 2007-02-09 + + Copyright 2000-2007, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_VECTOR4INT8_H +#define G3D_VECTOR4INT8_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" + +namespace G3D { + +class Vector3; +class Vector4; + +/** + Homogeneous vector stored efficiently in four signed int8s. + + */ +class Vector4int8 { +private: + // Hidden operators + bool operator<(const Vector4int8&) const; + bool operator>(const Vector4int8&) const; + bool operator<=(const Vector4int8&) const; + bool operator>=(const Vector4int8&) const; + + + /** For fast operations, treat this packed data structure as + an int32 */ + inline uint32& asInt32() { + return *reinterpret_cast(this); + } + + inline const uint32& asInt32() const { + return *reinterpret_cast(this); + } + +public: + // construction + inline Vector4int8() : x(0), y(0), z(0), w(0) {} + + /** Multiplies the source by 127 and clamps to (-128, 127) when converting */ + Vector4int8(const Vector4& source); + + /** Multiplies the source by 127 and clamps to (-128, 127) when converting */ + Vector4int8(const Vector3& source, int8 w); + + inline Vector4int8(int8 x, int8 y, int8 z, int8 w) : x(x), y(y), z(z), w(w) {} + + Vector4int8(class BinaryInput& b); + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + + // coordinates + int8 x, y, z, w; + + inline operator int8* () { + return reinterpret_cast(this); + } + + inline operator const int8* () const { + return reinterpret_cast(this); + } + + // access vector V as V[0] = V.x, V[1] = V.y, V[2] = V.z, etc. + // + // WARNING. These member functions rely on + // (1) Vector4int8 not having virtual functions + // (2) the data packed in a 4*sizeof(int8) memory block + inline int8& operator[] (int i) { + debugAssert(i >= 0 && i <= 4); + return ((int8*)this)[i]; + } + + const int8& operator[] (int i) const { + debugAssert(i >= 0 && i <= 4); + return ((const int8*)this)[i]; + } + + // assignment and comparison + Vector4int8& operator= (const Vector4int8& other) { + asInt32() = other.asInt32(); + return *this; + } + + inline bool operator== (const Vector4int8& other) const { + return asInt32() == other.asInt32(); + } + + inline bool operator!= (const Vector4int8& other) const { + return ! (*this == other); + } + + inline unsigned int hashCode() const { + return asInt32(); + } +}; + +} // namespace G3D + + +#endif diff --git a/externals/g3dlite/G3D/WeakCache.h b/externals/g3dlite/G3D/WeakCache.h new file mode 100644 index 00000000000..f9fdc4bbd5b --- /dev/null +++ b/externals/g3dlite/G3D/WeakCache.h @@ -0,0 +1,122 @@ +/** + @file WeakCache.h + + @maintainer Morgan McGuire, graphics3d.com + + @created 2007-05-16 + @edited 2007-05-16 + + Copyright 2000-2007, Morgan McGuire. + All rights reserved. + */ +#ifndef G3D_WEAKCACHE_H +#define G3D_WEAKCACHE_H + +#include "G3D/ReferenceCount.h" +#include "G3D/Table.h" + +namespace G3D { + +/** + A cache that does not prevent its members from being garbage collected. + Useful to avoid loading or computing an expression twice. Useful + for memoization and dynamic programming. + + Maintains a table of weak pointers. Weak pointers do not prevent + an object from being garbage collected. If the object is garbage + collected, the cache removes its reference. + + There are no "contains" or "iterate" methods because elements can be + flushed from the cache at any time if they are garbage collected. + + Example: +
+      WeakCache textureCache;
+
+      TextureRef loadTexture(std::string s) {
+          TextureRef t = textureCache[s];
+
+          if (t.isNull()) {
+              t = Texture::fromFile(s);
+              textureCache.set(s, t);
+          }
+
+          return t;
+      }
+      
+      
+    
+ */ +template +class WeakCache { + typedef WeakReferenceCountedPointer ValueWeakRef; + +private: + + Table table; + +public: + /** + Returns NULL if the object is not in the cache + */ + ValueRef operator[](const Key& k) { + if (table.containsKey(k)) { + ValueWeakRef w = table[k]; + ValueRef s = w.createStrongPtr(); + if (s.isNull()) { + // This object has been collected; clean out its key + table.remove(k); + } + return s; + } else { + return NULL; + } + } + + void set(const Key& k, ValueRef v) { + table.set(k, v); + } + + /** Removes k from the cache or does nothing if it is not currently in the cache.*/ + void remove(const Key& k) { + if (table.containsKey(k)) { + table.remove(k); + } + } +}; + +#if 0 // To turn off all WeakCaching +template +class WeakCache { +private: + + Table table; + +public: + /** + Returns NULL if the object is not in the cache + */ + ValueRef operator[](const Key& k) { + if (table.containsKey(k)) { + return table[k]; + } else { + return NULL; + } + } + + void set(const Key& k, ValueRef v) { + table.set(k, v); + } + + /** Removes k from the cache or does nothing if it is not currently in the cache.*/ + void remove(const Key& k) { + if (table.containsKey(k)) { + table.remove(k); + } + } +}; +#endif + +} +#endif + diff --git a/externals/g3dlite/G3D/Welder.h b/externals/g3dlite/G3D/Welder.h new file mode 100644 index 00000000000..2c2554da7b6 --- /dev/null +++ b/externals/g3dlite/G3D/Welder.h @@ -0,0 +1,82 @@ +#ifndef G3D_Welder_h +#define G3D_Welder_h + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/Vector3.h" +#include "G3D/Vector2.h" + +namespace G3D { + +class Any; + +class Welder { +private: + + Welder() {} + +public: + + class Settings { + public: + /** Surfaces with normals that are within this angle of each + other are considered to be curved. Default value is toRadians(70.0f).*/ + float normalSmoothingAngle; + float vertexWeldRadius; + float textureWeldRadius; + float normalWeldRadius; + + inline Settings(float normalSmoothAngle = toRadians(70.0f)) : + normalSmoothingAngle(normalSmoothAngle), + vertexWeldRadius(0.0001f), + textureWeldRadius(0.0001f), + normalWeldRadius(0.01f) {} + + + Settings(const Any& any); + operator Any() const; + }; + +/** + Mutates geometry, texCoord, and indexArray so that the output has collocated vertices collapsed (welded). + + @param vertices Input and output + @param textureCoords Input and output + @param normals Output only + @param indices Input and output. This is an array of trilist indices. + @param oldToNewIndex Output argument + @param normalSmoothingAngle Varies from 0 (flat shading) to toRadians(180) for extremely smooth shading. Default is toRadians(70) + */ + static void weld( + Array& vertices, + Array& textureCoords, + Array& normals, + Array*>& indices, + const Settings& settings); + + /** + Mutates geometry, texCoord, and indexArray so that the output has collocated vertices collapsed (welded). + + @param vertices Input and output + @param textureCoords Input and output + @param normals Output only + @param indices Input and output. This is an array of trilist indices. + @param oldToNewIndex Output argument + @param normalSmoothingAngle Varies from 0 (flat shading) to toRadians(180) for extremely smooth shading. Default is toRadians(70) + */ + inline static void weld( + Array& vertices, + Array& textureCoords, + Array& normals, + Array& indices, + const Settings& settings) { + + Array*> meta; + meta.append(&indices); + weld(vertices, textureCoords, normals, meta, settings); + } +}; + +} + +#endif diff --git a/externals/g3dlite/G3D/WrapMode.h b/externals/g3dlite/G3D/WrapMode.h new file mode 100644 index 00000000000..8ef38a77c23 --- /dev/null +++ b/externals/g3dlite/G3D/WrapMode.h @@ -0,0 +1,93 @@ +/** + @file WrapMode.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2007-04-17 + @edited 2007-04-17 + + Copyright 2000-2010, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_WrapMode_h +#define G3D_WrapMode_h + +#include "G3D/platform.h" +#include "G3D/enumclass.h" + +#ifdef IGNORE +# undef IGNORE +#endif +#ifdef ZERO +# undef ZERO +#endif +#ifdef ERROR +# undef ERROR +#endif + +namespace G3D { + +/** + Describes the behavior of G3D::Texture, G3D::Map2D, G3D::Image3, + etc. when accessing an out-of-bounds pixel. Not all classes support + all modes. + + Refer to these as scoped enums, e.g., WrapMode m = WrapMode::CLAMP;. + + WrapMode::IGNORE silently discards attempts to write to out + of bounds locations and returns an undefined value for reading + from out of bounds locations. + + WrapMode::ERROR generates an error when the + pixel indices are out of bounds + + WrapMode::CLAMP makes out of bounds pixels equal to the last in-range pixel along that dimension. + + WrapMode::TILE computes out of bounds pixels modulo the dimension + + WrapMode::ZERO treats out of bounds values as the zero value, which varies in definition + according to the class used. For example, with a G3D::Texture, ZERO = Color4(0,0,0,0). + + Uses the "Intelligent Enum" design pattern + http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4001/ + */ +class WrapMode { +public: + /** Don't use this enum; use WrapMode instances instead. */ + enum Value { + CLAMP, + TILE, + ZERO, + IGNORE, + ERROR + }; + +private: + + Value value; + +public: + + G3D_DECLARE_ENUM_CLASS_METHODS(WrapMode); + + inline const char* toString() const { + static const char* s[] = {"CLAMP", "TILE", "ZERO", "IGNORE", "ERROR"}; + return s[value]; + } + + inline explicit WrapMode(const std::string& x) : value(ERROR) { + static const char* s[] = {"CLAMP", "TILE", "ZERO", "IGNORE", "ERROR"}; + for (int i = 0; i < 5; ++i) { + if (x == s[i]) { + value = (Value)i; + } + } + } +}; + +} // namespace G3D + +G3D_DECLARE_ENUM_CLASS_HASHCODE(G3D::WrapMode); + +#endif diff --git a/externals/g3dlite/G3D/constants.h b/externals/g3dlite/G3D/constants.h new file mode 100644 index 00000000000..dd5cb3649e5 --- /dev/null +++ b/externals/g3dlite/G3D/constants.h @@ -0,0 +1,129 @@ +/** + @file G3D/constants.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @created 2009-05-20 + @edited 2009-05-20 +*/ +#ifndef G3D_constants_h +#define G3D_constants_h + +#include "G3D/platform.h" +#include "G3D/enumclass.h" + +namespace G3D { + +/** These are defined to have the same value as the equivalent OpenGL + constant. */ +class PrimitiveType { +public: + enum Value { + POINTS = 0x0000, + LINES = 0x0001, + LINE_STRIP = 0x0003, + TRIANGLES = 0x0004, + TRIANGLE_STRIP = 0x0005, + TRIANGLE_FAN = 0x0006, + QUADS = 0x0007, + QUAD_STRIP = 0x0008 + }; + +private: + + Value value; + +public: + + G3D_DECLARE_ENUM_CLASS_METHODS(PrimitiveType); +}; + + +/** Values for SuperSurface::GPUGeom::refractionHint. */ +class RefractionQuality { +public: + enum Value { + /** No refraction; a translucent object will appear as if it had the same index of refraction + as the surrounding medium and objects will be undistorted in the background. */ + NONE = 0, + + /** Use a static environment map (cube or paraboloid) for computing transmissivity.*/ + STATIC_ENV = 25, + + /** Use a dynamically rendered 2D environment map; distort the background. This looks good for many scenes + but avoids the cost of rendering a cube map for DYNAMIC_ENV. */ + DYNAMIC_FLAT = 50, + + /** Use a dynamically rendered 2D environment map that is re-captured per transparent object. This works well + for transparent objects that are separated by a significant camera space z distance but overlap in screen space.*/ + DYNAMIC_FLAT_MULTILAYER = 55, + + /** Render a dynamic environment map */ + DYNAMIC_ENV = 75, + + /** Use the best method available, ideally true ray tracing. */ + BEST = 100 + }; + +private: + + /** Used for to/from string conversion. Last is the emtpy string as a sentinel */ + static const std::string str[7]; + static const Value enm[6]; + Value value; + +public: + G3D_DECLARE_ENUM_CLASS_METHODS(RefractionQuality); + + RefractionQuality(const class Any&); + RefractionQuality& operator=(const Any&); + operator Any() const; + const std::string& toString() const; +}; + + +/** Values for SuperSurface::GPUGeom::mirrorHint. */ +class MirrorQuality { +public: + + enum Value { + /** Reflections are black */ + NONE = 0, + + /** Use a static environment map. This is what most games use */ + STATIC_ENV = 25, + + /** Planar reflection, typically for water or glass windows. This assumes that the mirror is flat; + it is distinct from RefractionQuality::DYNAMIC_FLAT, which assumes the background is flat.*/ + DYNAMIC_PLANAR = 50, + + /** Render a dynamic environment map. */ + DYNAMIC_ENV = 75, + + /** Use the best method available, ideally true ray tracing. */ + BEST = 100 + }; + +private: + + /** Used for to/from string conversion. Last is the emtpy string as a sentinel */ + static const std::string str[6]; + static const Value enm[5]; + + Value value; + +public: + G3D_DECLARE_ENUM_CLASS_METHODS(MirrorQuality); + MirrorQuality(const class Any&); + MirrorQuality& operator=(const Any&); + operator Any() const; + const std::string& toString() const; +}; + +} // namespace G3D + +G3D_DECLARE_ENUM_CLASS_HASHCODE(G3D::PrimitiveType) +G3D_DECLARE_ENUM_CLASS_HASHCODE(G3D::RefractionQuality) +G3D_DECLARE_ENUM_CLASS_HASHCODE(G3D::MirrorQuality) + +#endif + diff --git a/externals/g3dlite/G3D/debug.h b/externals/g3dlite/G3D/debug.h new file mode 100644 index 00000000000..a7697fe9c01 --- /dev/null +++ b/externals/g3dlite/G3D/debug.h @@ -0,0 +1,66 @@ +/** + @file debug.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2001-08-26 + @edited 2006-02-16 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. +*/ + +#ifndef G3D_DEBUG_H +#define G3D_DEBUG_H + +#include "G3D/platform.h" +#ifdef _MSC_VER + #include +#endif + +#include "G3D/debugPrintf.h" +#include "G3D/debugAssert.h" + +namespace G3D { + +#ifdef _MSC_VER + // Turn off 64-bit warnings +# pragma warning(push) +# pragma warning( disable : 4312) +# pragma warning( disable : 4267) +# pragma warning( disable : 4311) +#endif + + +/** + Useful for debugging purposes. + */ +inline bool isValidHeapPointer(const void* x) { + #ifdef _MSC_VER + return + (x != (void*)0xcccccccc) && (x != (void*)0xdeadbeef) && (x != (void*)0xfeeefeee); + #else + return x != NULL; + #endif +} + +/** + Returns true if the pointer is likely to be + a valid pointer (instead of an arbitrary number). + Useful for debugging purposes. + */ +inline bool isValidPointer(const void* x) { + #ifdef _MSC_VER + return x != ((void*)0xcccccccc) && (x != (void*)0xdeadbeef) && (x != (void*)0xfeeefeee); + #else + return x != NULL; + #endif +} + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +} + +#endif diff --git a/externals/g3dlite/G3D/debugAssert.h b/externals/g3dlite/G3D/debugAssert.h new file mode 100644 index 00000000000..432e97e679d --- /dev/null +++ b/externals/g3dlite/G3D/debugAssert.h @@ -0,0 +1,233 @@ +/** + @file debugAssert.h + + debugAssert(expression); + debugAssertM(expression, message); + + @cite + John Robbins, Microsoft Systems Journal Bugslayer Column, Feb 1999. + + http://msdn.microsoft.com/library/periodic/period99/feb99_BUGSLAYE_BUGSLAYE.htm + + @cite + Douglas Cox, An assert() Replacement, Code of The Day, flipcode, Sept 19, 2000 + + http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-AssertReplace&forum=cotd&id=-1 + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2001-08-26 + @edited 2006-01-12 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_DEBUGASSERT_H +#define G3D_DEBUGASSERT_H + +#include +#include "G3D/platform.h" + +#include + +#ifdef _MSC_VER +// conditional expression is constant +# pragma warning (disable : 4127) +#endif + +#ifdef G3D_LINUX + // Needed so we can define a global display + // pointer for debugAssert. +#if SOMEONE_MADE_THIS_USEFUL + #include + #include + #include +#endif +#endif + + +/** + @def debugBreak() + + Break at the current location (i.e. don't push a procedure stack frame + before breaking). + */ + +/** + @def debugAssert(exp) + Breaks if the expression is false. If G3D_DEBUG_NOGUI is defined, prompts at + the console, otherwise pops up a dialog. The user may then break (debug), + ignore, or halt the program. + + The assertion is also posted to the clipboard under Win32. + */ + +/** + @def debugAssertM(exp, msg) + Breaks if the expression is false and displays a message. If G3D_DEBUG_NOGUI + is defined, prompts at the console, otherwise pops up a dialog. The user may + then break (debug), ignore, or halt the program. + + The assertion is also posted to the clipboard under Win32. + */ + +/** + @def alwaysAssertM(exp, msg) + Same as debugAssertM except that it asserts in release builds as well. + */ + +namespace G3D { +typedef bool (*AssertionHook)( + const char* _expression, + const std::string& message, + const char* filename, + int lineNumber, + bool useGuiPrompt); + +/** + Allows customization of the global function invoked when a debugAssert fails. + The initial value is G3D::_internal::_handleDebugAssert_. G3D will invoke + rawBreak if the hook returns true. If NULL, assertions are not handled. +*/ +void setAssertionHook(AssertionHook hook); + +AssertionHook assertionHook(); + +/** + Called by alwaysAssertM in case of failure in release mode. If returns + true then the program exits with -1 (you can replace this with your own + version that throws an exception or has other failure modes). + */ +void setFailureHook(AssertionHook hook); +AssertionHook failureHook(); + +namespace _internal { + extern AssertionHook _debugHook; + extern AssertionHook _failureHook; +} // internal +} // G3D + +/** + @def __debugPromptShowDialog__ + @internal + */ + +#ifdef G3D_DEBUG + +# if defined(_MSC_VER) +# define rawBreak() ::DebugBreak(); +# elif defined(__i386__) + // gcc on intel +# define rawBreak() __asm__ __volatile__ ( "int $3" ); +# else + // some other gcc +# define rawBreak() ::abort() +# endif + + +# define debugBreak() G3D::_internal::_releaseInputGrab_(); rawBreak(); G3D::_internal::_restoreInputGrab_(); +# define debugAssert(exp) debugAssertM(exp, "Debug assertion failure") + + #ifdef G3D_DEBUG_NOGUI + #define __debugPromptShowDialog__ false + #else + #define __debugPromptShowDialog__ true + #endif + + #define debugAssertM(exp, message) do { \ + if (!(exp)) { \ + G3D::_internal::_releaseInputGrab_(); \ + if ((G3D::_internal::_debugHook != NULL) && \ + G3D::_internal::_debugHook((const char*)(#exp), message, __FILE__, __LINE__, __debugPromptShowDialog__)) { \ + rawBreak(); \ + } \ + G3D::_internal::_restoreInputGrab_(); \ + } \ + } while (0) + + #define alwaysAssertM debugAssertM + +#else // Release + #ifdef G3D_DEBUG_NOGUI + #define __debugPromptShowDialog__ false + #else + #define __debugPromptShowDialog__ true + #endif + + // In the release build, just define away assertions. + #define rawBreak() do {} while (0) + #define debugAssert(exp) do {} while (0) + #define debugAssertM(exp, message) do {} while (0) + #define debugBreak() do {} while (0) + + // But keep the 'always' assertions + #define alwaysAssertM(exp, message) { \ + if (!(exp)) { \ + G3D::_internal::_releaseInputGrab_(); \ + if ((G3D::_internal::_failureHook != NULL) && \ + G3D::_internal::_failureHook(#exp, message, __FILE__, __LINE__, __debugPromptShowDialog__)) { \ + ::exit(-1); \ + } \ + G3D::_internal::_restoreInputGrab_(); \ + } \ + } + +#endif // if debug + + + +namespace G3D { namespace _internal { + +#ifdef G3D_LINUX +#if SOMEONE_MADE_THIS_USEFUL + /** + A pointer to the X11 display. Initially NULL. If set to a + non-null value (e.g. by SDLWindow), debugAssert attempts to use + this display to release the mouse/input grab when an assertion + fails. + */ + extern Display* x11Display; + + /** + A pointer to the X11 window. Initially NULL. If set to a + non-null value (e.g. by SDLWindow), debugAssert attempts to use + this window to release the mouse/input grab when an assertion + fails. + */ + extern Window x11Window; +#endif +#endif + +/** + Pops up an assertion dialog or prints an assertion + + ignoreAlways - return result of pressing the ignore button. + useGuiPrompt - if true, shows a dialog + */ +bool _handleDebugAssert_( + const char* expression, + const std::string& message, + const char* filename, + int lineNumber, + bool useGuiPrompt); + +bool _handleErrorCheck_( + const char* expression, + const std::string& message, + const char* filename, + int lineNumber, + bool useGuiPrompt); + +/** Attempts to give the user back their mouse and keyboard if they + were locked to the current window. + @internal*/ +void _releaseInputGrab_(); + +/** Attempts to restore the state before _releaseInputGrab_. + @internal*/ +void _restoreInputGrab_(); + +}; }; // namespace + +#endif diff --git a/externals/g3dlite/G3D/debugPrintf.h b/externals/g3dlite/G3D/debugPrintf.h new file mode 100644 index 00000000000..b42151cae9e --- /dev/null +++ b/externals/g3dlite/G3D/debugPrintf.h @@ -0,0 +1,62 @@ +/** + @file debugPrintf.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2001-08-26 + @edited 2007-07-20 + + Copyright 2000-2007, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_DEBUGPRINTF_H +#define G3D_DEBUGPRINTF_H + +#include "G3D/platform.h" +#include +#include +#include "G3D/format.h" +#include + +namespace G3D { + +typedef void (*ConsolePrintHook)(const std::string&); + +namespace _internal { + extern ConsolePrintHook _consolePrintHook; +} + +/** Called by consolePrintf after the log and terminal have been written to. + Used by GConsole to intercept printing routines.*/ +void setConsolePrintHook(ConsolePrintHook h); + +ConsolePrintHook consolePrintHook(); + +/** + Sends output to the log and to the last GConsole instantiated. + + Guarantees that the output has been flushed by the time the routine + returns. + @sa G3D::logPrintf, G3D::screenPrintf + @return The string that was printed + */ +std::string __cdecl consolePrintf(const char* fmt ...) G3D_CHECK_PRINTF_ARGS; +std::string consolePrint(const std::string&); + +/** + Under visual studio, appears in the VS debug pane. + On unix-based operating systems the output is sent to stderr. + + Also sends output to the console (G3D::consolePrintf) if there is a consolePrintHook, + and log (G3D::logPrintf), and flushes before returning. + + @return The string that was printed +*/ +std::string __cdecl debugPrintf(const char* fmt ...) G3D_CHECK_PRINTF_ARGS; +std::string debugPrint(const std::string&); + +} // namespace G3D + +#endif + diff --git a/externals/g3dlite/G3D/enumclass.h b/externals/g3dlite/G3D/enumclass.h new file mode 100644 index 00000000000..c7dfe45f14f --- /dev/null +++ b/externals/g3dlite/G3D/enumclass.h @@ -0,0 +1,147 @@ +/** + @file G3D/enumclass.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @created 2007-01-27 + @edited 2007-07-20 +*/ +#ifndef G3D_enumclass_h +#define G3D_enumclass_h + +#include "G3D/HashTrait.h" +#include "G3D/BinaryInput.h" +#include "G3D/BinaryOutput.h" + +/** +\def G3D_DECLARE_ENUM_CLASS_METHODS + + \brief Creates a series of methods that turn a class into a scoped enumeration. + + Uses the "Intelligent Enum" design pattern + http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4001/ + + Enum classes are initialized to their zero value by default. + + See GLG3D/GKey.h for an example. + \sa G3D_DECLARE_ENUM_CLASS_HASHCODE + */ +#define G3D_DECLARE_ENUM_CLASS_METHODS(Classname)\ + inline Classname(char v) : value((Value)v) {}\ +\ + inline Classname() : value((Value)0) {}\ +\ + inline Classname(const Value v) : value(v) {}\ +\ + explicit inline Classname(int v) : value((Value)v) {}\ +\ + /** Support cast back to the Value type, which is needed to allow implicit assignment inside unions. */\ + /*inline operator Value() const { + return value; + }*/\ +\ + inline operator int() const {\ + return (int)value;\ + }\ +\ + inline bool operator== (const Classname other) const {\ + return value == other.value;\ + }\ +\ + inline bool operator== (const Classname::Value other) const {\ + return value == other;\ + }\ +\ + inline bool operator!= (const Classname other) const {\ + return value != other.value;\ + }\ +\ + inline bool operator!= (const Classname::Value other) const {\ + return value != other;\ + }\ +\ + inline bool operator< (const Classname other) const {\ + return value < other.value;\ + }\ +\ + inline bool operator> (const Classname other) const {\ + return value > other.value;\ + }\ +\ + inline bool operator>= (const Classname other) const {\ + return value >= other.value;\ + }\ +\ + inline bool operator<= (const Classname other) const {\ + return value <= other.value;\ + }\ +\ + inline bool operator< (const Value other) const {\ + return value < other;\ + }\ +\ + inline bool operator> (const Value other) const {\ + return value > other;\ + }\ +\ + inline bool operator<= (const Value other) const {\ + return value <= other;\ + }\ +\ + inline bool operator>= (const Value other) const {\ + return value >= other;\ + }\ +\ + inline Classname& operator-- () {\ + value = (Value)((int)value - 1);\ + return *this;\ + }\ +\ + inline Classname& operator++ () {\ + value = (Value)((int)value + 1);\ + return *this;\ + }\ +\ + inline Classname& operator+= (const int x) {\ + value = (Value)((int)value + x);\ + return *this;\ + }\ +\ + inline Classname& operator-= (const int x) {\ + value = (Value)((int)value - x);\ + return *this;\ + }\ +\ + inline Classname operator+ (const int x) const {\ + return Classname((int)value + x);\ + }\ +\ + inline Classname operator- (const int x) const {\ + return Classname((int)value - x);\ + }\ +\ + inline unsigned int hashCode() const {\ + return (unsigned int)value;\ + }\ +\ + inline void serialize(BinaryOutput& b) const {\ + b.writeInt32(value);\ + }\ +\ + inline void deserialize(BinaryInput& b) {\ + value = (Value)b.readInt32();\ + } + +/** \def G3D_DECLARE_ENUM_CLASS_HASHCODE +*/ +#define G3D_DECLARE_ENUM_CLASS_HASHCODE(Classname)\ +template <> struct HashTrait \ +{ \ + static size_t hashCode(Classname::Value key) { return static_cast(key); } \ +}; \ + \ +template <> struct HashTrait \ +{ \ + static size_t hashCode(Classname key) { return static_cast(key.hashCode()); } \ +}; + +#endif diff --git a/externals/g3dlite/G3D/fileutils.h b/externals/g3dlite/G3D/fileutils.h new file mode 100644 index 00000000000..9e49777d93a --- /dev/null +++ b/externals/g3dlite/G3D/fileutils.h @@ -0,0 +1,254 @@ +/** + @file fileutils.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @author 2002-06-06 + @edited 2010-02-06 + + Copyright 2000-2010, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_fileUtils_h +#define G3D_fileUtils_h + +#include "G3D/platform.h" +#include +#include +#include "G3D/Array.h" +#include "G3D/Set.h" +#include "G3D/g3dmath.h" + +#ifdef G3D_WIN32 +// For chdir, mkdir, etc. +# include +#endif + +namespace G3D { + + namespace _internal { + extern Set currentFilesUsed; + } + +/** Returns all the files used by G3D and GLG3D during the current execution. */ +Array filesUsed(); + +std::string readWholeFile( + const std::string& filename); + + +/** Reads from a zip file and decompresses the desired contents + into memory. Does not support recursive zip calls (i.e. a .zip + stored within another .zip) + + @param file the path, of the format C:\\...\\something.zip\\...\\desiredfile.ext + @param data a pointer to the memory where the file will be stored + @param length the size of the file decompressed to memory */ +void zipRead(const std::string& file, + void*& data, + size_t& length); + + +/** Closes the contents of a zip file that had been decompressed to + memory. Must be called in tandem with zipRead() to avoid memory + leaks. + + @param data the pointer to the decompressed file in memory */ +void zipClose(void* data); + + +/** + @param flush If true (default), the file is ready for reading as soon + as the function returns. If false, the function returns immediately and + writes the file in the background. + */ +void writeWholeFile( + const std::string& filename, + const std::string& str, + bool flush = true); + +/** + Creates the directory (which may optionally end in a /) + and any parents needed to reach it. + */ +void createDirectory( + const std::string& dir); + +/** + Fully qualifies a filename. The filename may contain wildcards, + in which case the wildcards will be preserved in the returned value. + */ +std::string resolveFilename(const std::string& filename); + +/** + Appends all files matching filespec to the files array. The names + will not contain paths unless includePath == true. These may be + relative to the current directory unless the filespec is fully qualified + (can be done with resolveFilename). + Wildcards can only appear to the right of the last slash in filespec. + Works with .zip files used as paths, if filespec is passed in the form + C:\\...\\something.zip\\* Does not work recursively with zipfiles (a + .zip within a .zip will not work) + */ +void getFiles( + const std::string& filespec, + Array& files, + bool includePath = false); + +/** + Appends all directories matching filespec to the files array. The names + will not contain paths unless includePath == true. These may be + relative to the current directory unless the filespec is fully qualified + (can be done with resolveFilename). + Does not append special directories "." or "..". + Works with .zip files used as paths, if filespec is passed in the form + C:\\...\\something.zip\\* Does not work recursively with zipfiles (a + .zip within a .zip will not work) + */ +void getDirs( + const std::string& filespec, + Array& files, + bool includePath = false); + + +/** Returns true if the specified path exists and is a directory */ +bool isDirectory(const std::string& filespec); + + +/** Returns true if the specified filename exists and is a zipfile */ +bool isZipfile(const std::string& filename); + + +/** Returns the length of the file. If + filename specifies a path that contains a zipfile, but the + contents within are specified correctly, returns the + uncompressed size of the requested file. Returns -1 if + the file does not exist. + + @param filename the path to test, may contain .zip +*/ +int64 fileLength(const std::string& filename); + +/** + Copies the file + */ +void copyFile( + const std::string& source, + const std::string& dest); + +/** Returns a temporary file that is open for read/write access. This + tries harder than the ANSI tmpfile, so it may succeed when that fails. */ +FILE* createTempFile(); + +/** + Returns true if the given file (or directory) exists. + + \param filename the path to test. must not end in a trailing slash. + \param lookInZipfiles if the path does not exist, calls zipfileExists() + \param trustCache If true and \a lookInZipfiles is true, cache directory and zipfile contents + so that subsequent calls to the same directory are fast. + + \sa G3D::clearFileSystemCache, G3D::zipfileExists + */ +bool fileExists +(const std::string& filename, + bool lookInZipfiles = true, + bool trustCache = true); + + +/** Clears the cache used by fileExists */ +void clearFileSystemCache(); + +/** + Returns true if the given file (or directory) exists + within a zipfile. Called if fileExists initially + returns false and the lookInZipfiles flag has been set. + Must not end in a trailing slash. Does not work for recursive + zipfiles (.zips within another .zip) + + @param filename the path to test + @param outZipfile the path to the .zip file + @param outInternalFile the path (within the .zip) where the desired file is located, if valid + + */ +bool zipfileExists +(const std::string& filename, + std::string& outZipfile, + std::string& outInternalFile); + +bool zipfileExists(const std::string& filename); + +/** + Parses a filename into four useful pieces. + + Examples: + + c:\\a\\b\\d.e + root = "c:\\" + path = "a" "b" + base = "d" + ext = "e" + + /a/b/d.e + root = "/" + path = "a" "b" + base = "d" + ext = "e" + + /a/b + root = "/" + path = "a" + base = "b" + ext = "e" + + */ +void parseFilename( + const std::string& filename, + std::string& drive, + Array& path, + std::string& base, + std::string& ext); + + +/** + Returns the part of the filename that includes the base and ext from + parseFilename (i.e. everything to the right of the path). + */ +std::string filenameBaseExt(const std::string& filename); + +/** + Returns the extension on a filename. + */ +std::string filenameExt(const std::string& filename); + + +/** Returns the portion of a filename to the left of the last period + and to the right of the last slash or colon. + */ +std::string filenameBase(const std::string& filename); + +/** Creates a unique filename base in the current directory using the + specified prefix and suffix.*/ +std::string generateFilenameBase(const std::string& prefix = "", const std::string& suffix = ""); + +/** + Returns the drive (if Win32) and path from a filename, including + a slash if there was one. + filenamePath(f) + filenameBaseExt(f) == f + */ +std::string filenamePath(const std::string& filename); + +/** Returns true if '*' or '?' appears in the string */ +bool filenameContainsWildcards(const std::string& filename); + +/** Returns true if dst does not exist or src is newer than dst. Works on both files and directories. */ +bool fileIsNewer(const std::string& src, const std::string& dst); + +/** Appends file onto dirname, ensuring a / if needed. */ +std::string pathConcat(const std::string& dirname, const std::string& file); + +} // namespace + +#endif + diff --git a/externals/g3dlite/G3D/filter.h b/externals/g3dlite/G3D/filter.h new file mode 100644 index 00000000000..609477b79c9 --- /dev/null +++ b/externals/g3dlite/G3D/filter.h @@ -0,0 +1,29 @@ +/** + @file G3D/filter.h + + @author Morgan McGuire, http://graphics.cs.williams.edu + @created 2007-03-01 + @edited 2007-03-01 + + Copyright 2000-2007, Morgan McGuire. + All rights reserved. + */ +#ifndef G3D_FILTER_H +#define G3D_FILTER_H + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/g3dmath.h" + +namespace G3D { +/** + Generates a set of 1D gaussian filter coefficients of size N. The coefficients + are centered on element (N-1)/2 and have standard deviation given by std. The coefficients + are normalized such that the sum across coeff is 1.0. + + Matches the results returned by Matlab fspecial('gaussian', [1, N], std) + */ +void gaussian1D(Array& coeff, int N = 5, float std = 0.5f); +} + +#endif diff --git a/externals/g3dlite/G3D/format.h b/externals/g3dlite/G3D/format.h new file mode 100644 index 00000000000..3c7f0678876 --- /dev/null +++ b/externals/g3dlite/G3D/format.h @@ -0,0 +1,44 @@ +/** + @file format.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @author 2000-09-09 + @edited 2005-11-03 + + Copyright 2000-2005, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_FORMAT_H +#define G3D_FORMAT_H + +#include "G3D/platform.h" +#include +#include +#include + +namespace G3D { + +/** + Produces a string from arguments of the style of printf. This avoids + problems with buffer overflows when using sprintf and makes it easy + to use the result functionally. This function is fast when the resulting + string is under 160 characters (not including terminator) and slower + when the string is longer. + */ +std::string __cdecl format( + const char* fmt + ...) G3D_CHECK_PRINTF_ARGS; + +/** + Like format, but can be called with the argument list from a ... function. + */ +std::string vformat( + const char* fmt, + va_list argPtr) G3D_CHECK_VPRINTF_ARGS; + + +} // namespace + +#endif diff --git a/externals/g3dlite/G3D/g3dfnmatch.h b/externals/g3dlite/G3D/g3dfnmatch.h new file mode 100644 index 00000000000..464b3927eee --- /dev/null +++ b/externals/g3dlite/G3D/g3dfnmatch.h @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 1992, 1993 + *The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + *This product includes software developed by the University of + *California, Berkeley and its contributors. + * 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. + * + *@(#)fnmatch.h8.1 (Berkeley) 6/2/93 + * + * From FreeBSD fnmatch.h 1.7 + * $Id: g3dfnmatch.h,v 1.1 2010/02/06 06:51:28 morgan3d Exp $ + */ +#ifndef G3D_g3dfnmatch_h +#define G3D_g3dfnmatch_h + +#include "G3D/platform.h" + +namespace G3D { + +#if defined(G3D_WIN32) + +# if ! defined(FNM_NOMATCH) +# define FNM_NOMATCH 1 /* Match failed. */ +# define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ +# define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ +# define FNM_PERIOD 0x04 /* Period must be matched by period. */ +# define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ +# define FNM_CASEFOLD 0x10 /* Case insensitive search. */ +# define FNM_PREFIX_DIRS 0x20 /* Directory prefixes of pattern match too. */ +# endif + +#else + + // On non-windows systems, include fnmatch directly +# include +#endif + + +/** + Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. + Compares a filename or pathname to a pattern. + +The fnmatch() function checks whether the string argument matches the pattern argument, which is a shell wildcard pattern. +The flags argument modifies the behaviour; it is the bitwise OR of zero or more of the following flags: + +- FNM_NOESCAPE If this flag is set, treat backslash as an ordinary character, instead of an escape character. +- FNM_PATHNAME If this flag is set, match a slash in string only with a slash in pattern and not by an asterisk (*) or a question mark (?) metacharacter, nor by a bracket expression ([]) containing a slash. +- FNM_PERIOD If this flag is set, a leading period in string has to be matched exactly by a period in pattern. A period is considered to be leading if it is the first character in string, or if both FNM_PATHNAME is set and the period immediately follows a slash. +- FNM_FILE_NAME This is a GNU synonym for FNM_PATHNAME. +- FNM_LEADING_DIR If this flag (a GNU extension) is set, the pattern is considered to be matched if it matches an initial segment of string which is followed by a slash. This flag is mainly for the internal use of glibc and is only implemented in certain cases. +- FNM_CASEFOLD If this flag (a GNU extension) is set, the pattern is matched case-insensitively. + +\return Zero if \a string matches \a pattern, FNM_NOMATCH if there is no match or another non-zero value if there is an error + + */ +int g3dfnmatch(const char *pattern, const char *string, int flags); +} +#endif diff --git a/externals/g3dlite/G3D/g3dmath.h b/externals/g3dlite/G3D/g3dmath.h new file mode 100644 index 00000000000..d16214ebb37 --- /dev/null +++ b/externals/g3dlite/G3D/g3dmath.h @@ -0,0 +1,845 @@ +/** + @file g3dmath.h + + Math util class. + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @cite highestBit by Jukka Liimatta + + @created 2001-06-02 + @edited 2009-04-07 + + Copyright 2000-2006, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_g3dmath_h +#define G3D_g3dmath_h + +#ifdef _MSC_VER +// Disable conditional expression is constant, which occurs incorrectly on inlined functions +# pragma warning (push) +# pragma warning (disable : 4127) +// disable: "C++ exception handler used" +# pragma warning (disable : 4530) +#endif + +#include "G3D/platform.h" +#include +#include +#include +#include + +#ifdef _MSC_VER + // Visual Studio is missing inttypes.h +# ifndef PRId64 +# define PRId64 "I64d" +# endif +#else +#include +#endif + +/*These defines enable functionality introduced with the 1999 ISO C +**standard. They must be defined before the inclusion of math.h to +**engage them. If optimisation is enabled, these functions will be +**inlined. With optimisation switched off, you have to link in the +**maths library using -lm. +*/ + +#define _ISOC9X_SOURCE1 +#define _ISOC99_SOURCE1 +#define __USE_ISOC9X1 +#define __USE_ISOC991 + +#include + +#include "G3D/debug.h" + +#undef min +#undef max + +namespace G3D { + +#ifdef _MSC_VER +inline double __fastcall drand48() { + return ::rand() / double(RAND_MAX); +} + +#if !defined(_WIN64) + +/** + Win32 implementation of the C99 fast rounding routines. + + @cite routines are + Copyright (C) 2001 Erik de Castro Lopo + + Permission to use, copy, modify, distribute, and sell this file for any + purpose is hereby granted without fee, provided that the above copyright + and this permission notice appear in all copies. No representations are + made about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. +*/ + +__inline long int lrint (double flt) { + int intgr; + + _asm { + fld flt + fistp intgr + }; + + return intgr; +} + +__inline long int lrintf(float flt) { + int intgr; + + _asm { + fld flt + fistp intgr + }; + + return intgr; +} + +#else + + __inline long int lrint (double flt) { + return (long int)floor(flt+0.5f); + } + + __inline long int lrintf(float flt) { + return (long int)floorf(flt+0.5f); + } + +#endif + +#endif + + +#define fuzzyEpsilon (0.00001f) +/** + This value should not be tested against directly, instead + G3D::isNan() and G3D::isFinite() will return reliable results. */ +double inf(); + +/** This value should not be tested against directly, instead + G3D::isNan() and G3D::isFinite() will return reliable results. */ +double nan(); + +float finf(); + +float fnan(); + +inline double pi() { + return 3.1415926535898; +} + +inline double halfPi() { + return 1.57079633; +} + +inline double twoPi() { + return 6.28318531; +} + +typedef signed char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; +typedef int int32; +typedef unsigned int uint32; + +#ifdef _MSC_EXTENSIONS + typedef __int64 int64; + typedef unsigned __int64 uint64; +#elif ! defined(_MSC_VER) + typedef int64_t int64; + typedef uint64_t uint64; +#else + typedef long long int64; + typedef unsigned long long uint64; +#endif + +typedef float float32; +typedef double float64; + +int iAbs(int iValue); +int iCeil(double fValue); + +/** + Clamps the value to the range [low, hi] (inclusive) + */ +int iClamp(int val, int low, int hi); +int16 iClamp(int16 val, int16 low, int16 hi); +double clamp(double val, double low, double hi); +float clamp(float val, float low, float hi); + +/** + Returns a + (b - a) * f; + */ +inline double lerp(double a, double b, double f) { + return a + (b - a) * f; +} + +inline float lerp(float a, float b, float f) { + return a + (b - a) * f; +} + +/** + Wraps the value to the range [0, hi) (exclusive + on the high end). This is like the clock arithmetic + produced by % (modulo) except the result is guaranteed + to be positive. + */ +int iWrap(int val, int hi); + +int iFloor(double fValue); + +int iSign(int iValue); +int iSign(double fValue); + +inline int iSign(float f) { + return iSign((double)f); +} + + +/** + Fast round to integer using the lrint routine. + Typically 6x faster than casting to integer. + */ +inline int iRound(double fValue) { + return lrint(fValue); +} + +/** + Fast round to integer using the lrint routine. + Typically 6x faster than casting to integer. + */ +inline int iRound(float f) { + return lrintf(f); +} + +/** + Returns a random number uniformly at random between low and hi + (inclusive). + @deprecated Use Random::integer + */ +int iRandom(int low, int hi); + +double abs (double fValue); +double aCos (double fValue); +double aSin (double fValue); +double aTan (double fValue); +double aTan2 (double fY, double fX); +double sign (double fValue); +double square (double fValue); + +/** + Returns true if the argument is a finite real number. + */ +bool isFinite(double x); + +/** + Returns true if the argument is NaN (not a number). + You can't use x == nan to test this because all + comparisons against nan return false. + */ +bool isNaN(double x); +bool isNaN(float x); +inline bool isNaN(int x) { + (void)x; + return false; +} + +/** + Computes x % 3. + */ +int iMod3(int x); + +/** + Uniform random number between low and hi, inclusive. [low, hi] + @deprecated + @sa Random::uniform + */ +float uniformRandom(float low = 0.0f, float hi = 1.0f); + +/** + Normally distributed random number. + + @deprecated + @sa Random::gaussian + */ +float gaussRandom(float mean = 0.0f, float stdev = 1.0f); + + +/** Returns x5 */ +template +inline T pow5(T x) { + const T y = x * x; + return y * y * x; +} + + +template +inline T min(const T& x, const T& y) { + return std::min(x, y); +} + +template +inline T min(const T& x, const T& y, const T& z) { + return std::min(std::min(x, y), z); +} + +template +inline T min(const T& x, const T& y, const T& z, const T& w) { + return std::min(std::min(x, y), std::min(z, w)); +} + +template +inline T max(const T& x, const T& y) { + return std::max(x, y); +} + +template +inline T max(const T& x, const T& y, const T& z) { + return std::max(std::max(x, y), z); +} + +template +inline T max(const T& x, const T& y, const T& z, const T& w) { + return std::max(std::max(x, y), std::max(z, w)); +} + +int iMin(int x, int y); +int iMax(int x, int y); + +double square(double x); +double sumSquares(double x, double y); +double sumSquares(double x, double y, double z); +double distance(double x, double y); +double distance(double x, double y, double z); + +/** + Returnes the 0-based index of the highest 1 bit from + the left. -1 means the number was 0. + + @cite Based on code by jukka@liimatta.org + */ +int highestBit(uint32 x); + +/** + Note that fuzzyEq(a, b) && fuzzyEq(b, c) does not imply + fuzzyEq(a, c), although that will be the case on some + occasions. + */ +bool fuzzyEq(double a, double b); + +/** True if a is definitely not equal to b. + Guaranteed false if a == b. + Possibly false when a != b.*/ +bool fuzzyNe(double a, double b); + +/** Is a strictly greater than b? (Guaranteed false if a <= b). + (Possibly false if a > b) */ +bool fuzzyGt(double a, double b); + +/** Is a near or greater than b? */ +bool fuzzyGe(double a, double b); + +/** Is a strictly less than b? (Guaranteed false if a >= b)*/ +bool fuzzyLt(double a, double b); + +/** Is a near or less than b? */ +bool fuzzyLe(double a, double b); + +/** + Computes 1 / sqrt(x). + */ +inline float rsq(float x) { + return 1.0f / sqrtf(x); +} + +/** + Return the next power of 2 higher than the input + If the input is already a power of 2, the output will be the same + as the input. + */ +int ceilPow2(unsigned int in); + +/** Returns 2^x */ +inline int pow2(unsigned int x) { + return 1 << x; +} + +inline double log2(double x) { + return ::log(x) * 1.442695; +} + +inline float log2(float x) { + return ::logf(x) * 1.442695f; +} + +inline double log2(int x) { + return log2((double)x); +} + + +/** + * True if num is a power of two. + */ +bool isPow2(int num); + +bool isOdd(int num); +bool isEven(int num); + +double toRadians(double deg); +double toDegrees(double rad); + +/** + Returns true if x is not exactly equal to 0.0f. + */ +inline bool any(float x) { + return x != 0; +} + +/** + Returns true if x is not exactly equal to 0.0f. + */ +inline bool all(float x) { + return x != 0; +} + +/** + v / v (for DirectX/Cg support) + */ +inline float normalize(float v) { + return v / v; +} + +/** + a * b (for DirectX/Cg support) + */ +inline float dot(float a, float b) { + return a * b; +} + + +/** + a * b (for DirectX/Cg support) + */ +inline float mul(float a, float b) { + return a * b; +} + +/** + 2^x + */ +inline double exp2(double x) { + return pow(2.0, x); +} + +inline float exp2(float x) { + return powf(2.0f, x); +} + +/** @deprecated Use rsq */ +inline double rsqrt(double x) { + return 1.0 / sqrt(x); +} + +/** @deprecated Use rsq */ +inline float rsqrt(float x) { + // TODO: default this to using the SSE2 instruction + return 1.0 / sqrtf(x); +} + +/** + sin(x)/x + */ +inline double sinc(double x) { + double r = sin(x) / x; + + if (isNaN(r)) { + return 1.0; + } else { + return r; + } +} + +/** + Computes a floating point modulo; the result is t wrapped to the range [lo, hi). + */ +inline float wrap(float t, float lo, float hi) { + if ((t >= lo) && (t < hi)) { + return t; + } + + debugAssert(hi > lo); + + float interval = hi - lo; + + return t - interval * iFloor((t - lo) / interval); +} + + +inline double wrap(double t, double lo, double hi) { + if ((t >= lo) && (t < hi)) { + return t; + } + + debugAssert(hi > lo); + + double interval = hi - lo; + + return t - interval * iFloor((t - lo) / interval); +} + +inline double wrap(double t, double hi) { + return wrap(t, 0.0, hi); +} + + +inline bool isFinite(double x) { + return ! isNaN(x) && (x < G3D::inf()) && (x > -G3D::inf()); +} + +inline bool isFinite(float x) { + return ! isNaN(x) && (x < G3D::finf()) && (x > -G3D::finf()); +} + +//---------------------------------------------------------------------------- +inline int iAbs (int iValue) { + return ( iValue >= 0 ? iValue : -iValue ); +} + +//---------------------------------------------------------------------------- +inline int iCeil (double fValue) { + return int(::ceil(fValue)); +} + +//---------------------------------------------------------------------------- + +inline int iClamp(int val, int low, int hi) { + debugAssert(low <= hi); + if (val <= low) { + return low; + } else if (val >= hi) { + return hi; + } else { + return val; + } +} + +//---------------------------------------------------------------------------- + +inline int16 iClamp(int16 val, int16 low, int16 hi) { + debugAssert(low <= hi); + if (val <= low) { + return low; + } else if (val >= hi) { + return hi; + } else { + return val; + } +} + +//---------------------------------------------------------------------------- + +inline double clamp(double val, double low, double hi) { + debugAssert(low <= hi); + if (val <= low) { + return low; + } else if (val >= hi) { + return hi; + } else { + return val; + } +} + +inline float clamp(float val, float low, float hi) { + debugAssert(low <= hi); + if (val <= low) { + return low; + } else if (val >= hi) { + return hi; + } else { + return val; + } +} +//---------------------------------------------------------------------------- + +inline int iWrap(int val, int hi) { + if (val < 0) { + return ((val % hi) + hi) % hi; + } else { + return val % hi; + } +} + +//---------------------------------------------------------------------------- +inline int iFloor (double fValue) { + return int(::floor(fValue)); +} + +//---------------------------------------------------------------------------- +inline int iSign (int iValue) { + return ( iValue > 0 ? + 1 : ( iValue < 0 ? -1 : 0 ) ); +} + +inline int iSign (double fValue) { + return ( fValue > 0.0 ? + 1 : ( fValue < 0.0 ? -1 : 0 ) ); +} + +//---------------------------------------------------------------------------- +inline double abs (double fValue) { + return double(::fabs(fValue)); +} + +//---------------------------------------------------------------------------- +inline double aCos (double fValue) { + if ( -1.0 < fValue ) { + if ( fValue < 1.0 ) + return double(::acos(fValue)); + else + return 0.0; + } else { + return pi(); + } +} + +//---------------------------------------------------------------------------- +inline double aSin (double fValue) { + if ( -1.0 < fValue ) { + if ( fValue < 1.0 ) { + return double(::asin(fValue)); + } else { + return -halfPi(); + } + } else { + return halfPi(); + } +} + +//---------------------------------------------------------------------------- +inline double aTan (double fValue) { + return double(::atan(fValue)); +} + +//---------------------------------------------------------------------------- +inline double aTan2 (double fY, double fX) { + return double(::atan2(fY, fX)); +} + +//---------------------------------------------------------------------------- +inline double sign (double fValue) { + if (fValue > 0.0) { + return 1.0; + } + + if (fValue < 0.0) { + return -1.0; + } + + return 0.0; +} + +inline float sign (float fValue) { + if (fValue > 0.0f) { + return 1.0f; + } + + if (fValue < 0.0f) { + return -1.0f; + } + + return 0.0f; +} + + +inline float uniformRandom(float low, float hi) { + return (hi - low) * float(::rand()) / float(RAND_MAX) + low; +} + +inline double square(double x) { + return x * x; +} + +inline float square(float x) { + return x * x; +} + +inline int square(int x) { + return x * x; +} + +//---------------------------------------------------------------------------- +inline double sumSquares(double x, double y) { + return x*x + y*y; +} + +//---------------------------------------------------------------------------- +inline float sumSquares(float x, float y) { + return x*x + y*y; +} + +//---------------------------------------------------------------------------- +inline double sumSquares(double x, double y, double z) { + return x*x + y*y + z*z; +} + +//---------------------------------------------------------------------------- +inline float sumSquares(float x, float y, float z) { + return x*x + y*y + z*z; +} + +//---------------------------------------------------------------------------- +inline double distance(double x, double y) { + return sqrt(sumSquares(x, y)); +} + +//---------------------------------------------------------------------------- +inline float distance(float x, float y) { + return sqrt(sumSquares(x, y)); +} + +//---------------------------------------------------------------------------- +inline double distance(double x, double y, double z) { + return sqrt(sumSquares(x, y, z)); +} + +//---------------------------------------------------------------------------- +inline float distance(float x, float y, float z) { + return sqrt(sumSquares(x, y, z)); +} + +//---------------------------------------------------------------------------- + +/** @deprecated use G3D::min */ +inline int iMin(int x, int y) { + return (x >= y) ? y : x; +} + +//---------------------------------------------------------------------------- +/** @deprecated use G3D::min */ +inline int iMax(int x, int y) { + return (x >= y) ? x : y; +} + +//---------------------------------------------------------------------------- +inline int ceilPow2(unsigned int in) { + in -= 1; + + in |= in >> 16; + in |= in >> 8; + in |= in >> 4; + in |= in >> 2; + in |= in >> 1; + + return in + 1; +} + +inline bool isPow2(int num) { + return ((num & -num) == num); +} + +inline bool isOdd(int num) { + return (num & 1) == 1; +} + +inline bool isEven(int num) { + return (num & 1) == 0; +} + +inline double toRadians(double deg) { + return deg * pi() / 180.0; +} + +inline double toDegrees(double rad) { + return rad * 180.0 / pi(); +} + +inline float toRadians(float deg) { + return deg * (float)pi() / 180.0f; +} + +inline float toDegrees(float rad) { + return rad * 180.0f / (float)pi(); +} + +inline float toRadians(int deg) { + return deg * (float)pi() / 180.0f; +} + +inline float toDegrees(int rad) { + return rad * 180.0f / (float)pi(); +} +/** + Computes an appropriate epsilon for comparing a and b. + */ +inline double eps(double a, double b) { + // For a and b to be nearly equal, they must have nearly + // the same magnitude. This means that we can ignore b + // since it either has the same magnitude or the comparison + // will fail anyway. + (void)b; + const double aa = abs(a) + 1.0; + if (aa == inf()) { + return fuzzyEpsilon; + } else { + return fuzzyEpsilon * aa; + } +} + +inline bool fuzzyEq(double a, double b) { + return (a == b) || (abs(a - b) <= eps(a, b)); +} + +inline bool fuzzyNe(double a, double b) { + return ! fuzzyEq(a, b); +} + +inline bool fuzzyGt(double a, double b) { + return a > b + eps(a, b); +} + +inline bool fuzzyGe(double a, double b) { + return a > b - eps(a, b); +} + +inline bool fuzzyLt(double a, double b) { + return a < b - eps(a, b); +} + +inline bool fuzzyLe(double a, double b) { + return a < b + eps(a, b); +} + +inline int iMod3(int x) { + return x % 3; +} + +/** + Given a 32-bit integer, returns the integer with the bytes in the opposite order. + */ +inline uint32 flipEndian32(const uint32 x) { + return (x << 24) | ((x & 0xFF00) << 8) | + ((x & 0xFF0000) >> 8) | ((x & 0xFF000000) >> 24); +} + +/** + Given a 16-bit integer, returns the integer with the bytes in the opposite order. + */ +inline uint16 flipEndian16(const uint16 x) { + return (x << 8) | ((x & 0xFF00) >> 8); +} + + +} // namespace + +#ifdef _MSC_VER +# pragma warning (pop) +#endif + +#endif + diff --git a/externals/g3dlite/G3D/g3dmath.inl b/externals/g3dlite/G3D/g3dmath.inl new file mode 100644 index 00000000000..9bf661a7ebc --- /dev/null +++ b/externals/g3dlite/G3D/g3dmath.inl @@ -0,0 +1,288 @@ +/** + @file g3dmath.inl + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2001-06-02 + @edited 2006-01-14 + */ + +#include + +#ifdef _MSC_VER +// Disable conditional expression is constant, which occurs incorrectly on inlined functions +# pragma warning (push) +# pragma warning( disable : 4127 ) +#endif + +namespace G3D { + +inline bool isNaN(double x) { + bool b1 = (x < 0.0); + bool b2 = (x >= 0.0); + bool b3 = !(b1 || b2); + return b3; +} + +inline bool isFinite(double x) { + return ! isNaN(x) && (x < G3D::inf()) && (x > -G3D::inf()); +} + +//---------------------------------------------------------------------------- +inline int iAbs (int iValue) { + return ( iValue >= 0 ? iValue : -iValue ); +} + +//---------------------------------------------------------------------------- +inline int iCeil (double fValue) { + return int(::ceil(fValue)); +} + +//---------------------------------------------------------------------------- + +inline int iClamp(int val, int low, int hi) { + debugAssert(low <= hi); + if (val <= low) { + return low; + } else if (val >= hi) { + return hi; + } else { + return val; + } +} + +//---------------------------------------------------------------------------- + +inline double clamp(double val, double low, double hi) { + debugAssert(low <= hi); + if (val <= low) { + return low; + } else if (val >= hi) { + return hi; + } else { + return val; + } +} + +inline float clamp(float val, float low, float hi) { + debugAssert(low <= hi); + if (val <= low) { + return low; + } else if (val >= hi) { + return hi; + } else { + return val; + } +} +//---------------------------------------------------------------------------- + +inline int iWrap(int val, int hi) { + if (val < 0) { + return ((val % hi) + hi) % hi; + } else { + return val % hi; + } +} + +//---------------------------------------------------------------------------- +inline int iFloor (double fValue) { + return int(::floor(fValue)); +} + +//---------------------------------------------------------------------------- +inline int iSign (int iValue) { + return ( iValue > 0 ? + 1 : ( iValue < 0 ? -1 : 0 ) ); +} + +inline int iSign (double fValue) { + return ( fValue > 0.0 ? + 1 : ( fValue < 0.0 ? -1 : 0 ) ); +} + +//---------------------------------------------------------------------------- +inline double abs (double fValue) { + return double(::fabs(fValue)); +} + +//---------------------------------------------------------------------------- +inline double aCos (double fValue) { + if ( -1.0 < fValue ) { + if ( fValue < 1.0 ) + return double(::acos(fValue)); + else + return 0.0; + } else { + return G3D_PI; + } +} + +//---------------------------------------------------------------------------- +inline double aSin (double fValue) { + if ( -1.0 < fValue ) { + if ( fValue < 1.0 ) { + return double(::asin(fValue)); + } else { + return -G3D_HALF_PI; + } + } else { + return G3D_HALF_PI; + } +} + +//---------------------------------------------------------------------------- +inline double aTan (double fValue) { + return double(::atan(fValue)); +} + +//---------------------------------------------------------------------------- +inline double aTan2 (double fY, double fX) { + return double(::atan2(fY, fX)); +} + +//---------------------------------------------------------------------------- +inline double sign (double fValue) { + if (fValue > 0.0) { + return 1.0; + } + + if (fValue < 0.0) { + return -1.0; + } + + return 0.0; +} + +inline double G3D_DEPRECATED unitRandom () { + return double(::rand()) / double(RAND_MAX); +} + +inline float uniformRandom(float low, float hi) { + return (hi - low) * float(::rand()) / float(RAND_MAX) + low; +} + +//---------------------------------------------------------------------------- +inline double G3D_DEPRECATED symmetricRandom () { + return 2.0 * double(::rand()) / double(RAND_MAX) - 1.0; +} + +//---------------------------------------------------------------------------- +inline double square(double x) { + return x * x; +} + +//---------------------------------------------------------------------------- +inline double sumSquares(double x, double y) { + return x*x + y*y; +} + +//---------------------------------------------------------------------------- +inline double sumSquares(double x, double y, double z) { + return x*x + y*y + z*z; +} + +//---------------------------------------------------------------------------- +inline double distance(double x, double y) { + return sqrt(sumSquares(x, y)); +} + +//---------------------------------------------------------------------------- +inline double distance(double x, double y, double z) { + return sqrt(sumSquares(x, y, z)); +} + +//---------------------------------------------------------------------------- + +/** @deprecated use G3D::min */ +inline int iMin(int x, int y) { + return (x >= y) ? y : x; +} + +//---------------------------------------------------------------------------- +/** @deprecated use G3D::min */ +inline int iMax(int x, int y) { + return (x >= y) ? x : y; +} + +//---------------------------------------------------------------------------- +inline int ceilPow2(unsigned int in) { + in -= 1; + + in |= in >> 16; + in |= in >> 8; + in |= in >> 4; + in |= in >> 2; + in |= in >> 1; + + return in + 1; +} + +inline bool isPow2(int num) { + return ((num & -num) == num); +} + +inline bool isOdd(int num) { + return (num & 1) == 1; +} + +inline bool isEven(int num) { + return (num & 1) == 0; +} + +inline double toRadians(double deg) { + return deg * G3D_PI / 180.0; +} + +inline double toDegrees(double rad) { + return rad * 180.0 / G3D_PI; +} + +/** + Computes an appropriate epsilon for comparing a and b. + */ +inline double eps(double a, double b) { + // For a and b to be nearly equal, they must have nearly + // the same magnitude. This means that we can ignore b + // since it either has the same magnitude or the comparison + // will fail anyway. + (void)b; + const double aa = abs(a) + 1; + if (aa == inf()) { + return fuzzyEpsilon; + } else { + return fuzzyEpsilon * aa; + } +} + +inline bool fuzzyEq(double a, double b) { + return (a == b) || (abs(a - b) <= eps(a, b)); +} + +inline bool fuzzyNe(double a, double b) { + return ! fuzzyEq(a, b); +} + +inline bool fuzzyGt(double a, double b) { + return a > b + eps(a, b); +} + +inline bool fuzzyGe(double a, double b) { + return a > b - eps(a, b); +} + +inline bool fuzzyLt(double a, double b) { + return a < b - eps(a, b); +} + +inline bool fuzzyLe(double a, double b) { + return a < b + eps(a, b); +} + +inline int iMod3(int x) { + return x % 3; +} + +} // namespace G3D + +#ifdef _MSC_VER +// Disable conditional expression is constant, which occurs incorrectly on inlined functions +# pragma warning (pop) +#endif diff --git a/externals/g3dlite/G3D/platform.h b/externals/g3dlite/G3D/platform.h new file mode 100644 index 00000000000..11ba0127a16 --- /dev/null +++ b/externals/g3dlite/G3D/platform.h @@ -0,0 +1,331 @@ +/** + @file platform.h + + \#defines for platform specific issues. + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2003-06-09 + @edited 2010-01-11 + */ + +#ifndef G3D_platform_h +#define G3D_platform_h + +/** + The version number of G3D in the form: MmmBB -> + version M.mm [beta BB] + */ +#define G3D_VER 80004 + +// fatal error for unsupported architectures +#if defined(__powerpc__) +# error PowerPC is not supported by G3D! +#endif + +#if defined(G3D_RELEASEDEBUG) +# define G3D_DEBUGRELEASE +#endif + +#if defined(G3D_DEBUGRELEASE) && defined(_DEBUG) +# undef _DEBUG +#endif + +/** @def G3D_DEBUG() + Defined if G3D is built in debug mode. */ +#if !defined(G3D_DEBUG) && (defined(_DEBUG) || defined(G3D_DEBUGRELEASE)) +# define G3D_DEBUG +#endif + +#ifndef _MSC_VER +/// Fast call is a register-based optimized calling convention supported only by Visual C++ +#define __fastcall + +#endif + +#ifdef _MSC_VER + #define G3D_WIN32 +#elif defined(__FreeBSD__) || defined(__OpenBSD__) + #define G3D_FREEBSD + #define G3D_LINUX +#elif defined(__linux__) + #define G3D_LINUX +#elif defined(__APPLE__) + #define G3D_OSX + + // Prevent OS X fp.h header from being included; it defines + // pi as a constant, which creates a conflict with G3D +#define __FP__ +#else + #error Unknown platform +#endif + +// Detect 64-bit under various compilers +#if (defined(_M_X64) || defined(_WIN64) || defined(__LP64__) || defined(_LP64)) +# define G3D_64BIT + #if defined(WIN32) + #include + #endif +#else +# define G3D_32BIT +#endif + +// Strongly encourage inlining on gcc +#ifdef __GNUC__ +#define inline __inline__ +#endif + + +// Verify that the supported compilers are being used and that this is a known +// processor. + +#ifdef G3D_LINUX +# ifndef __GNUC__ +# error G3D only supports the gcc compiler on Linux. +# endif +#endif + +#ifdef G3D_OSX +# ifndef __GNUC__ +# error G3D only supports the gcc compiler on OS X. +# endif + +# if defined(__i386__) +# define G3D_OSX_INTEL +# elif defined(__PPC__) +# define G3D_OSX_PPC +# else +# define G3D_OSX_UNKNOWN +# endif + +#endif + + +#ifdef _MSC_VER +// Microsoft Visual C++ 8.0 ("Express") = 1400 +// Microsoft Visual C++ 7.1 ("2003") _MSC_VER = 1310 +// Microsoft Visual C++ 7.0 ("2002") _MSC_VER = 1300 +// Microsoft Visual C++ 6.0 _MSC_VER = 1200 +// Microsoft Visual C++ 5.0 _MSC_VER = 1100 + +// Turn off warnings about deprecated C routines +# pragma warning (disable : 4996) + +// Turn off "conditional expression is constant" warning; MSVC generates this +// for debug assertions in inlined methods. +# pragma warning (disable : 4127) + +/** @def G3D_DEPRECATED() + Creates deprecated warning. */ +# define G3D_DEPRECATED __declspec(deprecated) + +// Prevent Winsock conflicts by hiding the winsock API +# ifndef _WINSOCKAPI_ +# define _G3D_INTERNAL_HIDE_WINSOCK_ +# define _WINSOCKAPI_ +# endif + +// Disable 'name too long for browse information' warning +# pragma warning (disable : 4786) +// TODO: remove +# pragma warning (disable : 4244) + +# define restrict + +/** @def G3D_CHECK_PRINTF_METHOD_ARGS() + Enables printf parameter validation on gcc. */ +# define G3D_CHECK_PRINTF_ARGS + +/** @def G3D_CHECK_PRINTF_METHOD_ARGS() + Enables printf parameter validation on gcc. */ +# define G3D_CHECK_VPRINTF_ARGS + +/** @def G3D_CHECK_PRINTF_METHOD_ARGS() + Enables printf parameter validation on gcc. */ +# define G3D_CHECK_PRINTF_METHOD_ARGS + +/** @def G3D_CHECK_PRINTF_METHOD_ARGS() + Enables printf parameter validation on gcc. */ +# define G3D_CHECK_VPRINTF_METHOD_ARGS + + // On MSVC, we need to link against the multithreaded DLL version of + // the C++ runtime because that is what SDL and ZLIB are compiled + // against. This is not the default for MSVC, so we set the following + // defines to force correct linking. + // + // For documentation on compiler options, see: + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/HTML/_core_Compiler_Reference.asp + // + + // DLL runtime + #ifndef _DLL + #define _DLL + #endif + + // Multithreaded runtime + #ifndef _MT + #define _MT 1 + #endif + + // Ensure that we aren't forced into the static lib + #ifdef _STATIC_CPPLIB + #undef _STATIC_CPPLIB + #endif + + #ifdef _DEBUG + #pragma comment (linker, "/NODEFAULTLIB:LIBCMTD.LIB") + #pragma comment (linker, "/NODEFAULTLIB:LIBCPMTD.LIB") + #pragma comment (linker, "/NODEFAULTLIB:LIBCPD.LIB") + #pragma comment (linker, "/DEFAULTLIB:MSVCPRTD.LIB") + #pragma comment(linker, "/NODEFAULTLIB:LIBCD.LIB") + #pragma comment(linker, "/DEFAULTLIB:MSVCRTD.LIB") + #else + #pragma comment(linker, "/NODEFAULTLIB:LIBC.LIB") + #pragma comment(linker, "/DEFAULTLIB:MSVCRT.LIB") + #pragma comment (linker, "/NODEFAULTLIB:LIBCMT.LIB") + #pragma comment (linker, "/NODEFAULTLIB:LIBCPMT.LIB") + #pragma comment(linker, "/NODEFAULTLIB:LIBCP.LIB") + #pragma comment (linker, "/DEFAULTLIB:MSVCPRT.LIB") + #endif + + // Now set up external linking + +# ifdef _DEBUG + // zlib was linked against the release MSVCRT; force + // the debug version. +# pragma comment(linker, "/NODEFAULTLIB:MSVCRT.LIB") +# endif + + +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif + + +# define NOMINMAX 1 +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0500 +# endif +# include +# undef WIN32_LEAN_AND_MEAN +# undef NOMINMAX + +# ifdef _G3D_INTERNAL_HIDE_WINSOCK_ +# undef _G3D_INTERNAL_HIDE_WINSOCK_ +# undef _WINSOCKAPI_ +# endif + + +/** @def G3D_START_AT_MAIN() + Defines necessary wrapper around WinMain on Windows to allow transfer of execution to main(). */ +# define G3D_START_AT_MAIN()\ +int WINAPI G3D_WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw);\ +int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) {\ + return G3D_WinMain(hInst, hPrev, szCmdLine, sw);\ +} + +#else + +/** @def G3D_START_AT_MAIN() + Defines necessary wrapper around WinMain on Windows to allow transfer of execution to main(). */ +# define G3D_START_AT_MAIN() + +#endif // win32 + +#ifdef __GNUC__ + +# include + +# if __STDC_VERSION__ < 199901 +# define restrict __restrict__ +# endif + +/** @def G3D_DEPRECATED() + Creates deprecated warning. */ +# define G3D_DEPRECATED __attribute__((__deprecated__)) + +// setup function calling conventions +# if defined(__i386__) && ! defined(__x86_64__) + +# ifndef __cdecl +# define __cdecl __attribute__((cdecl)) +# endif + +# ifndef __stdcall +# define __stdcall __attribute__((stdcall)) +# endif + +# elif defined(__x86_64__) + +# ifndef __cdecl +# define __cdecl +# endif + +# ifndef __stdcall +# define __stdcall +# endif +# endif // calling conventions + +/** @def G3D_CHECK_PRINTF_METHOD_ARGS() + Enables printf parameter validation on gcc. */ +# define G3D_CHECK_PRINTF_METHOD_ARGS __attribute__((__format__(__printf__, 2, 3))) + +/** @def G3D_CHECK_PRINTF_METHOD_ARGS() + Enables printf parameter validation on gcc. */ +# define G3D_CHECK_VPRINTF_METHOD_ARGS __attribute__((__format__(__printf__, 2, 0))) + +/** @def G3D_CHECK_PRINTF_METHOD_ARGS() + Enables printf parameter validation on gcc. */ +# define G3D_CHECK_PRINTF_ARGS __attribute__((__format__(__printf__, 1, 2))) + +/** @def G3D_CHECK_PRINTF_METHOD_ARGS() + Enables printf parameter validation on gcc. */ +# define G3D_CHECK_VPRINTF_ARGS __attribute__((__format__(__printf__, 1, 0))) +#endif + + +/** + @def STR(expression) + + Creates a string from the expression. Frequently used with G3D::Shader + to express shading programs inline. + + STR(this becomes a string)\verbatim
\endverbatim evaluates the same as \verbatim\endverbatim"this becomes a string"
+ */
+#define STR(x) #x
+
+/** @def PRAGMA(expression)
+    \#pragma may not appear inside a macro, so this uses the pragma operator
+    to create an equivalent statement.*/
+#ifdef _MSC_VER
+// Microsoft's version http://msdn.microsoft.com/en-us/library/d9x1s805.aspx
+#    define PRAGMA(x) __pragma(x)
+#else
+// C99 standard http://www.delorie.com/gnu/docs/gcc/cpp_45.html
+#    define PRAGMA(x) _Pragma(#x)
+#endif
+
+/** @def G3D_BEGIN_PACKED_CLASS(byteAlign)
+    Switch to tight alignment
+    See G3D::Color3uint8 for an example.*/
+#ifdef _MSC_VER
+#    define G3D_BEGIN_PACKED_CLASS(byteAlign)  PRAGMA( pack(push, byteAlign) )
+#else
+#    define G3D_BEGIN_PACKED_CLASS(byteAlign)
+#endif
+
+/** @def G3D_END_PACKED_CLASS(byteAlign)
+    End switch to tight alignment
+    See G3D::Color3uint8 for an example.*/
+#ifdef _MSC_VER
+#    define G3D_END_PACKED_CLASS(byteAlign)  ; PRAGMA( pack(pop) )
+#elif defined(__GNUC__)
+#    define G3D_END_PACKED_CLASS(byteAlign)  __attribute((aligned(byteAlign))) ;
+#else
+#    define G3D_END_PACKED_CLASS(byteAlign)  ;
+#endif
+
+
+// Header guard
+#endif
diff --git a/externals/g3dlite/G3D/prompt.h b/externals/g3dlite/G3D/prompt.h
new file mode 100644
index 00000000000..c6df628099e
--- /dev/null
+++ b/externals/g3dlite/G3D/prompt.h
@@ -0,0 +1,67 @@
+/** 
+ @file prompt.h
+ 
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ @cite   Windows GUI code by Max McGuire
+
+ @created 2001-08-26
+ @edited  2006-08-13
+ */
+
+#ifndef G3D_PROMPT_H
+#define G3D_PROMPT_H
+
+#include "platform.h"
+#include 
+
+namespace G3D {
+
+/**
+  Prints a prompt to stdout and waits for user input.  The return value is
+  the number of the user's choice (the first is 0, if there are no
+  choices, returns 0). 
+ 
+  @param useGui Under Win32, use a GUI, not stdout prompt.
+  @param windowTitle The title for the prompt window
+  @param promptx The text string to prompt the user with
+  @param choice  An array of strings that are the choices the user may make
+  @param numChoices The length of choice.
+
+  @cite Windows dialog interface by Max McGuire, mmcguire@ironlore.com
+  @cite Font setting code by Kurt Miller, kurt@flipcode.com
+ */
+int prompt(
+    const char*     windowTitle,
+    const char*     promptx,
+    const char**    choice,
+    int             numChoices,
+    bool            useGui);
+
+/**
+  Prints a prompt and waits for user input.  The return value is
+  the number of the user's choice (the first is 0, if there are no
+  choices, returns 0).
+  

Uses GUI under Win32, stdout prompt otherwise. + */ +inline int prompt( + const char* windowTitle, + const char* promptx, + const char** choice, + int numChoices) { + + return prompt(windowTitle, promptx, choice, numChoices, true); +} + + +/** + Displays a GUI prompt with "Ok" as the only choice. + */ +void msgBox( + const std::string& message, + const std::string& title = "Message"); + + +}; // namespace + +#endif + diff --git a/externals/g3dlite/G3D/serialize.h b/externals/g3dlite/G3D/serialize.h new file mode 100644 index 00000000000..2382c0ee0fd --- /dev/null +++ b/externals/g3dlite/G3D/serialize.h @@ -0,0 +1,30 @@ +#ifndef G3D_SERIALIZE_H +#define G3D_SERIALIZE_H + +#include "G3D/BinaryInput.h" +#include "G3D/BinaryOutput.h" +#include "G3D/Array.h" + +namespace G3D { + + +template +void serialize(const Array& array, BinaryOutput& b) { + b.writeInt32(array.size()); + for (int i = 0; i < array.size(); ++i) { + serialize(array[i], b); + } +} + +template +void deserialize(Array& array, BinaryInput& b) { + int N = b.readInt32(); + array.resize(N); + for (int i = 0; i < array.size(); ++i) { + deserialize(array[i], b); + } +} + +} + +#endif diff --git a/externals/g3dlite/G3D/splinefunc.h b/externals/g3dlite/G3D/splinefunc.h new file mode 100644 index 00000000000..3f3a018c292 --- /dev/null +++ b/externals/g3dlite/G3D/splinefunc.h @@ -0,0 +1,118 @@ +/** + @file spline.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2004-07-25 + @edited 2007-05-05 + */ + +#ifndef G3D_SPLINEFUNC_H +#define G3D_SPLINEFUNC_H + +#include "G3D/platform.h" +#include "G3D/debug.h" +#include "G3D/Array.h" +#include "G3D/g3dmath.h" + +namespace G3D { + +/** + Interpolates a property according to a piecewise linear spline. This provides + C0 continuity but the derivatives are not smooth. +

+ Example: + + const double times[] = {MIDNIGHT, SUNRISE - HOUR, SUNRISE, SUNRISE + sunRiseAndSetTime / 4, SUNRISE + sunRiseAndSetTime, SUNSET - sunRiseAndSetTime, SUNSET - sunRiseAndSetTime / 2, SUNSET, SUNSET + HOUR/2, DAY}; + const Color3 color[] = {Color3(0, .0, .1), Color3(0, .0, .1), Color3::black(), Color3::black(), Color3::white() * .25, Color3::white() * .25, Color3(.5, .2, .2), Color3(.05, .05, .1), Color3(0, .0, .1), Color3(0, .0, .1)}; + ambient = linearSpline(time, times, color, 10); + + + See also G3D::Spline + + @param x The spline is a function of x; this is the sample to choose. + @param controlX controlX[i], controlY[i] is a control points. It is assumed + that controlX are strictly increasing. XType must support + the "<" operator and a subtraction operator that returns + a number. + @param controlY YType must support multiplication and addition. + @param numControl The number of control points. + */ +template +YType linearSpline(double x, const XType* controlX, const YType* controlY, int numControl) { + debugAssert(numControl >= 1); + + // Off the beginning + if ((numControl == 1) || (x < controlX[0])) { + return controlY[0]; + } + + for (int i = 1; i < numControl; ++i) { + if (x < controlX[i]) { + const double alpha = (double)(controlX[i] - x) / (controlX[i] - controlX[i - 1]); + return controlY[i] * (1 - alpha) + controlY[i - 1] * alpha; + } + } + + // Off the end + return controlY[numControl - 1]; +} + + + /** See also G3D::Spline*/ +template YType cyclicCatmullRomSpline( + double t, + const YType* controlY, + int numPoints) { + + debugAssert(numPoints >= 3); + + t = wrap(t, numPoints); + + // Find the indices of adjacent control points + int i = iFloor(t); + + // Compute the distance from the control point + t = t - i; + + // Shift back one point for correct indexing + i += numPoints - 1; + + // Pick up four control points + const YType& P0 = controlY[(i + 0) % numPoints]; + const YType& P1 = controlY[(i + 1) % numPoints]; + const YType& P2 = controlY[(i + 2) % numPoints]; + const YType& P3 = controlY[(i + 3) % numPoints]; + + return 0.5 * ((2 * P1) + + (-P0 + P2) * t + + (2*P0 - 5*P1 + 4*P2 - P3) * t*t + + (-P0 + 3*P1- 3*P2 + P3) * t*t*t); +} + +/** + A cubic spline with regularly spaced + control points. The spline interpolates + the control points. The spline + will wrap from the last point back to the first. + + The t parameter is on the range [0, controlY.size()], + where integers correspond to control points exactly. + + See also G3D::Spline + + @cite http://www.mvps.org/directx/articles/catmull/ +*/ +template YType cyclicCatmullRomSpline( + double t, + const Array& controlY) { + + int numPoints = controlY.size(); + return cyclicCatmullRomSpline(t, controlY.getCArray(), numPoints); +} + +} + +#endif + + diff --git a/externals/g3dlite/G3D/stringutils.h b/externals/g3dlite/G3D/stringutils.h new file mode 100644 index 00000000000..e15a757a7a6 --- /dev/null +++ b/externals/g3dlite/G3D/stringutils.h @@ -0,0 +1,140 @@ +/** + @file stringutils.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @author 2000-09-09 + @edited 2008-08-05 + */ + +#ifndef G3D_STRINGUTILS_H +#define G3D_STRINGUTILS_H + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include + +namespace G3D { + +extern const char* NEWLINE; + +/** Separates a comma-separated line, properly escaping commas within + double quotes (") and super quotes ("""). This matches Microsoft Excel's + CSV output. + + \param stripQuotes If true, strips leading and trailing " and """ + + \sa G3D::stringSplit, G3D::TextInput, G3D::readWholeFile +*/ +void parseCommaSeparated(const std::string s, Array& array, bool stripQuotes = true); + +/** + Returns true if the test string begins with the pattern string. + */ +bool beginsWith( + const std::string& test, + const std::string& pattern); + +/** + Returns true if the test string ends with the pattern string. + */ +bool endsWith( + const std::string& test, + const std::string& pattern); + +/** + Produces a new string that is the input string + wrapped at a certain number of columns (where + the line is broken at the latest space before the + column limit.) Platform specific NEWLINEs + are inserted to wrap. + */ +std::string wordWrap( + const std::string& input, + int numCols); + +/** + A comparison function for passing to Array::sort. + */ +int stringCompare( + const std::string& s1, + const std::string& s2); + +int stringPtrCompare( + const std::string* s1, + const std::string* s2); + +/** + Returns a new string that is an uppercase version of x. + */ +std::string toUpper( + const std::string& x); + +std::string toLower( + const std::string& x); + +/** + Splits x at each occurance of splitChar. + */ +G3D::Array stringSplit( + const std::string& x, + char splitChar); + +/** + joinChar is not inserted at the beginning or end, just in between + elements. + */ +std::string stringJoin( + const G3D::Array& a, + char joinChar); + +std::string stringJoin( + const G3D::Array& a, + const std::string& joinStr); + +/** + Strips whitespace from both ends of the string. + */ +std::string trimWhitespace( + const std::string& s); + +/** These standard C functions are renamed for clarity/naming + conventions and to return bool, not int. + */ +inline bool isWhiteSpace(const unsigned char c) { + return isspace(c) != 0; +} + +/** These standard C functions are renamed for clarity/naming + conventions and to return bool, not int. + */ +inline bool isNewline(const unsigned char c) { + return (c == '\n') || (c == '\r'); +} + +/** These standard C functions are renamed for clarity/naming + conventions and to return bool, not int. + */ +inline bool isDigit(const unsigned char c) { + return isdigit(c) != 0; +} + +/** These standard C functions are renamed for clarity/naming + conventions and to return bool, not int. + */ +inline bool isLetter(const unsigned char c) { + return isalpha(c) != 0; +} + +inline bool isSlash(const unsigned char c) { + return (c == '\\') || (c == '/'); +} + +inline bool isQuote(const unsigned char c) { + return (c == '\'') || (c == '\"'); +} + +}; // namespace + +#endif + diff --git a/externals/g3dlite/G3D/uint128.h b/externals/g3dlite/G3D/uint128.h new file mode 100644 index 00000000000..da1af3ec272 --- /dev/null +++ b/externals/g3dlite/G3D/uint128.h @@ -0,0 +1,51 @@ +/** + @file uint128.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @author Kyle Whitson + + @created 2008-07-17 + @edited 2008-07-17 + */ + +#ifndef G3D_UINT128_H +#define G3D_UINT128_H + +#include "G3D/g3dmath.h" + +namespace G3D { + +/** Limited functionality 128-bit unsigned integer. This is primarily to support FNV hashing and other + cryptography applications. See the GMP library for high-precision C++ math support. */ +class uint128 { +public: + + G3D::uint64 hi; + G3D::uint64 lo; + + uint128(const uint64& lo); + + uint128(const uint64& hi, const uint64& lo); + + uint128& operator+=(const uint128& x); + + uint128& operator*=(const uint128& x); + + uint128& operator^=(const uint128& x); + + uint128& operator&=(const uint128& x); + + uint128& operator|=(const uint128& x); + + bool operator==(const uint128& x); + + uint128& operator>>=(const int x); + + uint128& operator<<=(const int x); + + uint128 operator&(const uint128& x); + +}; +} + +#endif diff --git a/externals/g3dlite/G3D/units.h b/externals/g3dlite/G3D/units.h new file mode 100644 index 00000000000..2e30304dc62 --- /dev/null +++ b/externals/g3dlite/G3D/units.h @@ -0,0 +1,126 @@ +/** + @file units.h + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2009-08-21 + @edited 2009-08-21 + */ +#ifndef G3D_units_h +#define G3D_units_h + +#include "G3D/platform.h" + +namespace G3D { +/** Use using namespace G3D::units; to include all units + into your program. The units system is specifically designed not to + be general but to support commonly used units efficiently and + clearly. See http://en.wikipedia.org/wiki/SI_prefix for interesting facts + about SI/metric units and full definitions.*/ +namespace units { + +/** 1e-9 m */ +inline float nanometers() { + return 1e-9f; +} + +/** 1e-6 m */ +inline float micrometers() { + return 1e-6f; +} + +/** 0.001 m */ +inline float millimeters() { + return 0.001f; +} + +/** 0.01 m */ +inline float centimeters() { + return 0.01f; +} + +/** SI base unit of distance measure. */ +inline float meters() { + return 1.0f; +} + +/** 1000 m */ +inline float kilometers() { + return 100.0f; +} + +/** 0.0254 m */ +inline float inches() { + return 0.0254f; +} + +/** 0.3048 m */ +inline float feet() { + return 0.3048f; +} + +/** 0.9144 m */ +inline float yards() { + return 0.9144f; +} + +/** 1609.344 m */ +inline float miles() { + return 1609.344f; +} + +///////////////////////////////////////////////////////////// + +/** SI base unit of angular measure. */ +inline float radians() { + return 1.0f; +} + +/** pi/180 */ +inline float degrees() { + return 0.0174532925f; +} + +////////////////////////////////////////////////////////////// + +/** 1e-9 s */ +inline float nanoseconds() { + return 1e-9f; +} + +/** 1e-3 s */ +inline float milliseconds() { + return 1e-3f; +} + +/** Base unit of time */ +inline float seconds() { + return 1.0; +} + +/** 60 s */ +inline float minutes() { + return 60.0f; +} + +/** 3600 s */ +inline float hours() { + return 3600.0f; +} + +/** 86400 s */ +inline float days() { + return 86400.0f; +} + +/** 31556926 s */ +inline float years() { + return 31556926.0f; +} + +/////////////////////////////////////////// + +} +} + +#endif diff --git a/externals/g3dlite/G3D/vectorMath.h b/externals/g3dlite/G3D/vectorMath.h new file mode 100644 index 00000000000..ac6d2b32e9d --- /dev/null +++ b/externals/g3dlite/G3D/vectorMath.h @@ -0,0 +1,235 @@ +/** + @file vectorMath.h + + Function aliases for popular vector methods. + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created: 2001-06-02 + @edited: 2004-02-02 + Copyright 2000-2004, Morgan McGuire. + All rights reserved. + */ + +#ifndef G3D_VECTORMATH_H +#define G3D_VECTORMATH_H + +#include "G3D/platform.h" +#include "G3D/g3dmath.h" +#include "G3D/Vector2.h" +#include "G3D/Vector3.h" +#include "G3D/Vector4.h" +#include "G3D/Matrix3.h" +#include "G3D/Matrix4.h" +#include "G3D/Color1.h" +#include "G3D/Color3.h" +#include "G3D/Color4.h" + + +namespace G3D { + + +inline Matrix4 mul(const Matrix4& a, const Matrix4& b) { + return a * b; +} + +inline Vector4 mul(const Matrix4& m, const Vector4& v) { + return m * v; +} + +inline Vector3 mul(const Matrix3& m, const Vector3& v) { + return m * v; +} + +inline Matrix3 mul(const Matrix3& a, const Matrix3& b) { + return a * b; +} + +inline float dot(const Vector2& a, const Vector2& b) { + return a.dot(b); +} + +inline float dot(const Vector3& a, const Vector3& b) { + return a.dot(b); +} + +inline float dot(const Vector4& a, const Vector4& b) { + return a.dot(b); +} + +inline Vector2 normalize(const Vector2& v) { + return v / v.length(); +} + +inline Vector3 normalize(const Vector3& v) { + return v / v.magnitude(); +} + +inline Vector4 normalize(const Vector4& v) { + return v / v.length(); +} + +inline Vector2 abs(const Vector2& v) { + return Vector2(::fabsf(v.x), ::fabsf(v.y)); +} + +inline Vector3 abs(const Vector3& v) { + return Vector3(::fabsf(v.x), ::fabsf(v.y), ::fabsf(v.z)); +} + +inline Vector4 abs(const Vector4& v) { + return Vector4(::fabsf(v.x), ::fabsf(v.y), ::fabsf(v.z), ::fabsf(v.w)); +} + +inline bool all(const Vector2& v) { + return (v.x != 0) && (v.y != 0); +} + +inline bool all(const Vector3& v) { + return (v.x != 0) && (v.y != 0) && (v.z != 0); +} + +inline bool all(const Vector4& v) { + return (v.x != 0) && (v.y != 0) && (v.z != 0) && (v.w != 0); +} + +inline bool any(const Vector2& v) { + return (v.x != 0) || (v.y != 0); +} + +inline bool any(const Vector3& v) { + return (v.x != 0) || (v.y != 0) || (v.z != 0); +} + +inline bool any(const Vector4& v) { + return (v.x != 0) || (v.y != 0) || (v.z != 0) || (v.w != 0); +} + +inline Vector2 clamp(const Vector2& v, const Vector2& a, const Vector2& b) { + return v.clamp(a, b); +} + +inline Vector3 clamp(const Vector3& v, const Vector3& a, const Vector3& b) { + return v.clamp(a, b); +} + +inline Vector4 clamp(const Vector4& v, const Vector4& a, const Vector4& b) { + return v.clamp(a, b); +} + +inline Vector2 lerp(const Vector2& v1, const Vector2& v2, float f) { + return v1.lerp(v2, f); +} + +inline Vector3 lerp(const Vector3& v1, const Vector3& v2, float f) { + return v1.lerp(v2, f); +} + +inline Vector4 lerp(const Vector4& v1, const Vector4& v2, float f) { + return v1.lerp(v2, f); +} + +inline Color1 lerp(const Color1& v1, const Color1& v2, float f) { + return v1.lerp(v2, f); +} + +inline Color3 lerp(const Color3& v1, const Color3& v2, float f) { + return v1.lerp(v2, f); +} + +inline Color4 lerp(const Color4& v1, const Color4& v2, float f) { + return v1.lerp(v2, f); +} + +inline Vector3 cross(const Vector3& v1, const Vector3& v2) { + return v1.cross(v2); +} + +inline double determinant(const Matrix3& m) { + return m.determinant(); +} + +inline double determinant(const Matrix4& m) { + return m.determinant(); +} + +inline Vector2 min(const Vector2& v1, const Vector2& v2) { + return v1.min(v2); +} + +inline Vector3 min(const Vector3& v1, const Vector3& v2) { + return v1.min(v2); +} + +inline Vector4 min(const Vector4& v1, const Vector4& v2) { + return v1.min(v2); +} + +inline Color3 min(const Color3& v1, const Color3& v2) { + return v1.min(v2); +} + +inline Color4 min(const Color4& v1, const Color4& v2) { + return v1.min(v2); +} + +inline Vector2 max(const Vector2& v1, const Vector2& v2) { + return v1.max(v2); +} + +inline Vector3 max(const Vector3& v1, const Vector3& v2) { + return v1.max(v2); +} + +inline Vector4 max(const Vector4& v1, const Vector4& v2) { + return v1.max(v2); +} + +inline Color3 max(const Color3& v1, const Color3& v2) { + return v1.max(v2); +} + +inline Color4 max(const Color4& v1, const Color4& v2) { + return v1.max(v2); +} + +inline Vector2 sign(const Vector2& v) { + return Vector2((float)sign(v.x), (float)sign(v.y)); +} + +inline Vector3 sign(const Vector3& v) { + return Vector3((float)sign(v.x), (float)sign(v.y), (float)sign(v.z)); +} + +inline Vector4 sign(const Vector4& v) { + return Vector4((float)sign(v.x), (float)sign(v.y), (float)sign(v.z), (float)sign(v.w)); +} + +inline float length(float v) { + return ::fabsf(v); +} + +inline float length(const Vector2& v) { + return v.length(); +} + +inline float length(const Vector3& v) { + return v.magnitude(); +} + +inline float length(const Vector4& v) { + return v.length(); +} + +/** + Computes the log of each component. Useful for + inverting the monitor gamma function or simulating + perceptual response. + */ +inline Color3 log(const Color3& c) { + return Color3(::logf(c.r), ::logf(c.g), ::logf(c.b)); +} + +} + +#endif diff --git a/externals/g3dlite/doc-files/changelog.dox b/externals/g3dlite/doc-files/changelog.dox deleted file mode 100644 index fd52b99f271..00000000000 --- a/externals/g3dlite/doc-files/changelog.dox +++ /dev/null @@ -1,1872 +0,0 @@ -/** - @page changelog Change Log - -

- - Major version numbers introduce API changes that are not backwards - compatible. Minor versions are backwards compatible to the - previous major release, except for critical bug fixes. Deprecated functionality - will be supported until (at least) the next major release. - - -


- -

- Changes in 7.01: -

    -
  • Video file reading and writing via FFmpeg added -
  • Added computeBounds method to ArticulatedModel::Part that calls computeBounds on each TriList. Changed updateAll to automatically call computeBounds [Kyle] -
  • Added constructor to Matrix4 to construct a matrix from an upper-left 3x3 submatrix and an upper-right 3x1 submatrix [Kyle] -
  • Incompatible change: RegistryUtil functions now require an explicit value parameter instead of extracting the value from the key string. -
  • Incompatible change:GApp now calls the onLogic handler before the simulation handlers but after the user input and network handlers -
  • Incompatible change: Changed GHashCode and other functors to traits. See \link guidenewuser \endlink. Added typedefs and adapters to make this mostly backwards compatible. -
  • Added parallax occlusion mapping to G3D::SuperShader (specify Material::parallaxSteps > 1) -
  • Added normal mapping to G3D::SuperShader (specify Material::parallaxSteps == 0) -
  • G3D::Texture resizes textures that exceed the device maximum size -
  • G3D::Array now allows control over MIN_ELEMENTS and MIN_BYTES using template parameters -
  • Clarified G3D::Any file format in documentation -
  • G3D::Texture::PreProcess::gammaAdjust -
  • G3D::ShadowMap::lightProjection(), G3D::ShadowMap::lightFrame() -
  • Added Barycentric coordinates to CollisionDetection::isPointInTriangle -
  • G3D::RenderDevice::beginOpenGL, G3D::RenderDevice::endOpenGL -
  • PointAABSPTree::clearData -
  • AABSPTree -> KDTree -
  • GApp now allows the MidgetManager to process events in onEvent before the GApp::onEvent executes -
  • Added spotlight support to SuperShader -
  • Switched SuperShader to use ph -
  • Adjusted standard deviation used in G3D::GaussianBlur to provide smoother filtering -
  • Put HashTrait and EqualsTrait in their own headers separate from Table.h -
  • ArticulatedModel::facet -
  • Renamed GWindow to G3D::OSWindow -
  • ReferenceCountedPointer now asserts that the pointer is not NULL on method invocation -
  • G3D::ShadowMap now computes appropriate matrices for spot lights -
  • Added ImageFormat::convert [Danny and Kyle] -
  • 3- and 4- argument min and max -
  • G3D::GaussianBlur now correctly sets the output viewport -
  • G3D::Framebuffer::clear -
  • IFSModel and ArticulatedModel now load Princeton Shape Benchmark OFF files. -
  • G3D::Any CoordinateFrame now serialized using angles -
  • CameraControlWindow now prints angles in degrees -
  • ImageXXX classes now have a format() method -
  • OSWindow::create -
  • MeshAlg::toIndexedTriList now supports TRIANGLE_FAN input. -
  • Tuned Table and hash functions for performance [Kyle & Morgan] -
  • GEvent::toString -
  • G3D::TextInput now treats characters with ASCII code greater than 127 as symbols -
  • G3D::ThreadSet -
  • G3D::Texture::white -
  • G3D::Matrix4::upper3x3 -
  • G3D::Matrix4::homoMul -
  • ArticulateModel::fromFile now takes a Matrix4 instead of a CoordinateFrame to allow arbitrary linear transformations. -
  • ArticulatedModel::createCornellBox -
  • Material::createDiffuse -
  • ImageFormat::convert -
  • G3D::filenameBase -
  • Removed SDL_SysWMEvent, which was never supported by GEvent anyway -
  • Removed TextureFormat::SAME_AS_SCREEN to break dependence on OpenGL -
  • TextureFormat has been renamed to G3D::ImageFormat and moved into G3D.lib -
  • Added variable time control points to G3D::Spline -
  • Gui controls now have configureable GuiControl::setCaptionSize -
  • Gui controls now default to no indent if the caption is "" (use " " for indent with no caption) -
  • G3D::GuiContainer -
  • G3D::GThread::started -
  • buildg3d installation arguments changed--see -
  • G3D::Vector3int32 -
  • GuiButton now accepts an optional callback function/method -
  • FileDialog now accepts an extra "note" argument -
  • FileDialog::getFilename non-static to support subclassing -
  • System::currentDateString -
  • Expanded G3D::ArticulatedModel documentation -
  • Build system now executes on multiple processors (about 1.8x speedup for dual-core) -
  • Build system now caches dependencies (about 5x speedup for small incremental builds) -
  • Patched LOAD_EXTENSION to work around gcc pointer-to-function cast issues -
  • Tool buttons added to a G3D::GuiPane automatically align to the previous one. -
  • Added invisible GuiPane style -
  • G3D::uint128 [Kyle] -
  • Increased BSPMap rendering by 10% by reducing state changes -
  • Added prompt argument to FileDialog::getFilename -
  • G3D::PosedModel::getBoxBounds on an array -
  • G3D::PosedModel::getSphereBounds on an array -
  • Changed RenderDevice::screenshot to save .png instead of .jpg files -
  • G3D::SuperShader now supports a customMap and customConstant for experimenting with shaders. -
  • G3D::SuperShader now does not ever light the "back" of a bump-mapped poly, even if the bumps should create a light-facing surface -
  • G3D::Material promoted to its own class (was G3D::SuperShader::Material) -
  • G3D::Matrix2 -
  • G3D::VertexAndPixelShader::ArgList::size -
  • G3D::pathConcat -
  • G3D::WidgetManager::moveWidgetToBack -
  • SuperShader / NonShadowed.pix now uses arrays of lights instead of separate variables -
  • Reduced cost of release-mode Shader argument validation -
  • G3D::PosedModel::sortAndRender now performs view-frustum culling of objects -
  • G3D::Draw::lighting for visualizing light sources -
  • G3D::SuperShader::Pass::purgeCache -
  • G3D::GuiSlider::setRange -
  • G3D::GuiPane::addPane no longer takes a -
  • G3D::VertexAndPixelShader::ArgList::remove -
  • Optimized G3D::Matrix::pseudoInverse; now about 2x faster -
  • G3D::GLight::effectSphere -
  • G3D::GuiWindow::moveTo -
  • G3D::GuiWindow::setEnabled, enabled -
  • G3D::GuiButton now sizes to its caption -
  • G3D::GuiSlider now fires events on change and drag -
  • G3D::Shader arguments (in G3D::VertexAndPixelShader::ArgList) may now be "optional" -
  • G3D::GLight::point now has quadratic attenuation by default. -
  • G3D::ImageFormat::name -
  • g3dmath.h now includes inttypes.h on gcc and simulates it on visual studio -
  • G3D::RenderDevice::cullFace -
  • G3D::LineSegment2D::intersection -
  • G3D::BinaryInput::setEndian -
  • G3D::GEvent::MOUSE_BUTTON_CLICK -
  • Generalized ShadowMap to work with spotlights as well as directional lights -
  • G3D::GLCaps::supportsTexture, G3D::GLCaps::supportsRenderBuffer -
  • Opaque G3D::ArticulatedModels now support more than 2 non-shadow casting light sources -
  • Added proof symbol parsing to TextInput [Corey Taylor] -
  • Added G3D::AABox::corner() to match G3D::Box::corner() [Corey Taylor] -
  • OS X: G3D::CarbonWindow [Casey] -
  • OS X: iCompile now generates OS X application bundles and dmg files -
  • OS X build no longer depends on X11 -
  • G3D::FileDialog -
  • G3D::Table now allows overriding the default equality operator for keys -
  • Incompatible change: GApp::onBeforeSimulation now allows mutation of the timesteps -
  • Incompatible change: Merged GApp::simTime and idealSimTime (the sim time is now idealized) -
  • cmake now generates project files for Xcode, MinGW, and all Visual Studio versions [Corey Taylor] -
  • OS X: icompile and buildg3d now generate universal binaries on Intel machines -
  • G3D::PosedModel::objectSpaceTangents -
  • G3D::IFSModel::fromData -
  • G3D::MeshAlg::generateGrid -
  • G3D::BinaryOutput::ok() -
  • G3D::generateFilenameBase -
  • G3D::IFSModel::fromFile now defaults to not welding for improved performance -
  • G3D::IFSModel members are now protected to allow subclassing -
  • Removed G3D::uint in favor of G3D::uint32 [Corey Taylor] -
  • Added G3D::GMaterial(TextureRef) constructor -
  • Made G3D::GMaterial fields floats -
  • G3D::GuiControl::setCaption, G3D::GuiWindow::setCaption -
  • G3D::GuiControl can now be subclassed for custom user-defined controls -
  • G3D::GuiTheme::renderCanvas -
  • G3D::GuiTheme::pauseRendering, G3D::GuiTheme::resumeRendering -
  • G3D::PosedModel::sortAndRender -
  • G3D::Framebuffer can now attach cube map faces -
  • System::describeSystem now prints current working directory and application name -
  • Added /usr/local/-G3D dir- to system data file path [Kai Schroeder] -
  • Various patches for detecting new CPUs in System.cpp [Corey Taylor] -
  • g3d_Index macro now available in G3D::Shader GLSL code -
  • G3D::BackgroundWidget -
  • G3D::TriangleShape -
  • Fix: incompatible change OSWindow::Settings::asynchronous is now spelled correclty, with two "n"s -
  • Fix: Fixes for point-in-triangle and moving-sphere-fixed-tri; previous code projected onto the wrong axes, so barycentric coords were wrong for nearly vertical triangles. -
  • Fix: Changed some doubles to floats in G3D::Triangle -
  • Fix: Changed all of the isXXX(char) methods to take unsigned char arguments so that they can parse extended symbols -
  • Fix: AABSPTree::deserializeStructure was missing a return statement [Derex] -
  • Fix: Draw::plane was drawing the plane reflected through the origin [Macklin Chaffee] -
  • Fix: Added template parameters to friends in AABSPTree and PointAABSPTree [expiring_frog] -
  • Fix: System::findDataFile uses data directory set by GApp -
  • Fix: AtomicInt32 decrement returns int32 instead of uint32 -
  • Fix: OS X function keys now work correctly under CarbonWindow -
  • Fix: OS X modifier keys now work correctly under CarbonWindow -
  • Fix: OS X arrow keys now work correctly under CarbonWindow -
  • Fix: Rewrote buildg3d to fix many longstanding bugs, including mismatched 'bin' directories and confusion about the 'install' target -
  • Fix: gfxmeter reports now format correctly regardless of monitor width -
  • Fix: patch to initialize correctly on the Mesa library, which crashes when requesting DEPTH24_STENCIL8 -
  • Fix: stringSplit now works correctly for adjacent split characters [Akita Noek] -
  • Fix: Draw::axes labels now obey current viewport -
  • Fix: GuiWindow now loses focus when hidden -
  • Fix: GFont::draw2D now computes correct horizontal bounds on text -
  • Fix: GuiPane no longer renders when invisible -
  • Fix: Clicking off of all GuiWindows makes none of them have focus -
  • Fix: Win32Window now allows windows programmatically positioned anywhere on a multiple monitor screen -
  • Fix: Win32Window now does not fail when dragging a GL context between multiple monitors -
  • Fix: SuperShader now correctly lights bump-mapped surfaces in tangent space [Kyle Whitson] -
  • Fix: GuiPane now renders its caption -
  • Fix: Rect2D::border now grows the correct way (positive = grow) -
  • Fix: Added % operator to TextInput -
  • Fix: Added multi-line printing to GConsole -
  • Fix: G3D::Texture can now create empty cube maps -
  • Fix: G3D::Table iterator now correctly parameterized on hashfunction and equality function as well as key and value -
  • Fix: G3D::Table now passes Values by reference when setting them, avoiding one copy -
  • Fix: various Framebuffer/empty texture initialization bugs on ATI cards -
  • Fix: uniform arrays for GLSL -
  • Fix: All aliasing warnings have been fixed no longer needs -fno-strict-aliasing [Corey Taylor] -
  • Fix: [ 1829704 ] debugAssert in Array::operator[](unsigned int n) wrong -
  • Fix: GuiWindow::pack now recursively packs all child panes -
  • Fix: patch to continue build when javac isn't found on both windows and linux [Corey Taylor] -
  • Fix: [ 1599139 ] Fixes to make buildg3d work on non C:\ windows systems [Patrick Burke] -
  • Fix: Added faster overloads of GImage::stripAlpha() and GImage::insertRedAsAlpha() [Corey Taylor] -
  • Fix: GImage::save() with odd-widths bmp files [Corey Taylor] -
  • Fix: Draw::capule renders properly (capule was not visible) [Corey Taylor] -
  • Fix: Patched ShadowMap to work around ATI and OS X driver shadow map bugs. - Incompatible change:Required changing several interfaces to take ShadowMapRef arguments. -
  • Fix: GCamera::Frustum was facing backwards -
  • Fix: [ 1774479 ] texture glformats wrong (caused incorrect font rendering on Intel) -
  • Fix: ArticulatedModel static methods do not force loading of shaders unless an ArticulatedModel has actually been loaded. -
  • Fix: RenderDevice::setAlphaWrite/setColorWrite implemented correctly -
  • Fix: Implemented ImageFormat::fromCode -
  • Fix: [ 1766509 ] Texture doesn't handle 3D textures correctly -
  • Fix: Separate bool, float, and int back ends for GLSL shaders -
- -
-

- Changes in 7.00: -

    -
  • Upgraded to iCompile 0.5.3. Requires users to delete their old ice.txt and ~/.icompile files -
  • Key to toggle the user camera is now F2 (was Tab) -
  • Support for g++ 4.1 [Corey] -
  • Patches for 64-bit compilation [Corey] -
  • WinMain is now compiled as C++ code (fixed some "manifest" errors on certain VC8 installations) -
  • G3D::ShadowMap -
  • Cleaned up and documented G3D::GCamera project/unproject API [Jeff Marsceill] -
  • Made G3D::MD2Model::Pose easier to use -
  • G3D::Matrix -
  • Added G3D::Texture methods for reading back color and depth textures -
  • G3D::RenderDevice::getFixedFunctionLighting -
  • G3D::debugPrintf -> G3D::consolePrintf -
  • G3D::GApp::debugPrintf -> G3D::screenPrintf -
  • Reduced ArticulatedModel and MD2Model push/popState calls -
  • G3D::Shader now defines platform and graphics vendor macros -
  • User camera control requires right mouse click to move -
  • G3D::AnyVal::fromFile, G3D::AnyVal::load, G3D::AnyVal::save -
  • G3D::AnyVal now uses copy-on-mutate for fast Array/Table copies -
  • G3D::AnyVal no longer separates table entries with ";" -
  • G3D::AnyVal now provides casts to basic data types -
  • G3D::AnyVal G3D::Rect2D and G3D::AABox types -
  • G3D::NetListener, G3D::ReliableConduit, and G3D::LightweightConduit can now be created without an explicit NetworkDevice pointer -
  • GApp::onGraphics now takes posed model arguments -
  • G3D::RenderDevice::beginFrame no longer executes a pushState-- state will carry over between frames -
  • G3D::GUniqueID -
  • GApp::onPose -
  • All classes that read from files can now read data inside zipfiles. -
  • Changed G3D::hashCode(T) to ::GHashCode(T) [Corey] -
  • Removed "G3D::" from the printed portion of the documentation index to make it easier to read. -
  • OSWindow::fireEvent for inserting user events into the queue -
  • G3D::logPrintf -
  • System::findDataFile -
  • On OS X, G3D::FirstPersonManipulator now treats ctrl-click as right click -
  • Increased mouse sensitivity of G3D::FirstPersonManipulator on OS X -
  • System::getClipboardText, System::setClipboardText -
  • Widget::window() accessor -
  • Replaced SDLEvent with G3D::GEvent -
  • Increased GFont rendering performance, added GFont::send2DQuads for fast rendering of large amounts of text -
  • G3D::GFont now supports fonts with 256 characters (.fnt file format version 2) -
  • Upgraded to the OpenGL 2.0 glext/glxext/wglext headers -
  • G3D::GuiTheme, G3D::GuiText -
  • G3D::UprightFrame, G3D::UprightSpline -
  • G3D::Spline -
  • G3D::RenderDevice::clip2D -
  • G3D::Win32Window now returns events for up to 5 mouse buttons -
  • Significantly changed GEvent delivery and Widget mechanisms to incorporate notions of focus--see upgrade.html -
  • Motion events (joystick/mouse) can no longer be cancelled by Widget::onEvent -
  • Mouse motion events for all platforms -
  • G3D::PosedModel::Ref::sendGeometry -
  • G3D::RenderDevice::pushState(FramebufferRef) -
  • G3D::Texture::PreProcess::computeNormalMap -
  • direct.h is now included by fileutils.h on Win32 to ensure that chdir, mkdir, etc. are available -
  • Changed distribution directories to place include, lib, and bin under a directory named after the platform - and all other files one directory up. -
  • G3D::GCamera::unproject -
  • Made G3D::Ray non-virtual for efficiency -
  • RenderDevice::alphaWrite now defaults to true -
  • Changed G3D install directory from g3d-7_00 to g3d-7.00 -
  • On a GL 2.0 or greater driver, G3D::GLCaps now assumes the presence of all GL2 extensions even if they are not explicitly listed by the card [Corey Taylor] -
  • debugPrintf now flushes stderr on Unix systems -
  • G3D::Lighting::fromSky -
  • G3D::Texture::newGLTexture2D [Corey Taylor] -
  • Added 10-bit cinema texture formats [Corey Taylor] -
  • Added G3D::ArticulatedModel to the core (includes 3DS loading) -
  • Added G3D::SuperShader to the core -
  • Merged GApp and GApplet into GApp to make the common case easier to implement -
  • Removed GApp::debugMode options, removed "debug" prefix from most fields. -
  • G3D::zipfileExists for testing if a filename path contains a .zip to be opened [Eric] -
  • G3D::isZipfile tests the header of a file to see if it is a .zip [Eric] -
  • G3D::zipRead and G3D::zipClose to open and close .zip files [Eric] -
  • G3D::fileExists supports filename paths that contain .zip [Eric] -
  • G3D::fileLength supports filename paths that contain .zip [Eric] -
  • G3D::getFiles and G3D::getDirs support filename paths that contain .zip [Eric] -
  • Texture::isSupportedImage - static method, returns true if a filename exists and is compatible with Texture [Eric] -
  • Viewer (tool) - Allows drag and drop viewing of many supported file formats [Eric] -
  • GFXMeter (tool) - Updated for 7.00 compatibility: GApplet structure removed [Eric] -
  • OSWindow::Settings has an allowMaximize field. Win32Window will have an activated 'Maximize' button if true [Eric] -
  • GApp2::debugCamera -> GApp2::defaultCamera -
  • GApp2::debugController -> GApp2::defaultController -
  • Made GApp2::debugText private -
  • Added g3d_WorldLight0 to the G3D shader extensions -
  • Added Shader support for GL_FLOAT_MAT3_ARB uniforms -
  • Tab (command completion) no longer auto-repeats in GConsole -
  • GConsole now limits the key repeat rate to the framerate -
  • Removed GApp::Settings::useNetwork because it was no longer needed--Win32 does not trigger firewall checks anymore -
  • Optimized AABSPTree balance and queries; now about 20% faster than 6.10, but requires 30 bytes more memory per member -
  • G3D::Array::pop now shrinks the underlying array by default (Array::popRemove does not shrink the array and is faster) -
  • Fast O(n), non-destructive G3D::Array::partition and G3D::Array::medianPartition -
  • Increased ReliableConduit read attempts before timeout from 10 to 100 -
  • G3D::GImage::pixel1 now returns G3D::Color1uint8* -
  • G3D::Color1, G3D::Color1uint8 -
  • G3D::Image1, G3D::Image1uint8 -
  • G3D::Image3, G3D::Image3uint8 -
  • G3D::Image4, G3D::Image4uint8 -
  • BinaryInput::flipEndian32, BinaryInput::flipEndian16 -
  • Texture::createEmpty now intializes invertY = true, which is usually desirable for Framebuffer rendering. -
  • G3D::Map2D -
  • G3D::Vector4int8 -
  • G3D::PointShape -
  • G3D::GImage::RGBAtoRGB -
  • Added GLEW compatibility [nico] -
  • Added data-files directory to the locations searched for G3D demo data -
  • On Win32, assertions now print ot the Output window as well as the dialog box. -
  • On Win32, $TEMP is now used for the logfile location instead of c:\tmp -
  • G3D::GKey replaces old SDL key enumeration -
  • Decreased memory requirements and increased balance speed of G3D::AABSPTree by adding a level of indirection - between tree nodes and the data stored in them. -
  • Added OSWindow::Settings::caption -
  • Win32 programs must call the macro G3D_START_AT_MAIN(); at top-level if they do not define WinMain themselves. -
  • Win32 switched from MBCS to UNICODE for the binaries (G3D sources compile under either, but UNICODE is the VC8 default) -
  • Replaced SDL event types with G3D event types -
  • Added support for GL_ARB_point_sprite -
  • Win32 programs must call the macro G3D_START_AT_MAIN(); at top-level if they do not define WinMain themselves. -
  • Win32 switched from MBCS to UNICODE for the binaries (G3D sources compile under either) -
  • Changed G3D::GApp::main to return an int -
  • Added header support for GL_EXT_geometry_shader4 ("Geometry shaders") -
  • Changed IFSModel::create to IFSModel::fromFile -
  • G3D::BSPMap for loading Quake3 .bsp files -
  • G3D::TextInput::Settings::caseSensitive -
  • G3D::TextInput::readBoolean, G3D::TextInput::Settings::trueSymbols, G3D::TextInput::Settings::falseSymbols, G3D::TextOutput::Settings::trueSymbol, G3D::TextOutput::Settings::falseSymbol, G3D::TextOutput::writeBoolean, G3D::Token::BOOLEAN_TYPE -
  • G3D::TextInput::Settings::msvcSpecials now defaults to true -
  • Made the input to G3D::tessellateComplexPolygon a constant array reference -
  • Removed SDL from Win32 build -
  • Increased maximum ReliableConduit message size to 60 MB -
  • Removed error macro -
  • G3D::GConsole -
  • Rect2D::lerp -
  • Added GL_EXT_packed_depth_stencil -
  • Added G3D::ImageFormat::DEPTH24_STENCIL8 packed stencil mode -
  • getOpenGLState now includes GL_LIGHT_MODEL_TWO_SIDE value -
  • Made ThirdPersonManipulator constructor protected (use ThirdPersonManipulator::create now) -
  • G3D::ToneMap -
  • Changed Renderbuffer::createEmpty argument order to match Texture::createEmpty -
  • G3D::IFSModel can now remove degenerate faces on load -
  • G3D::MD2Model::textureFromFile -
  • Replaced AABSPTree::beginRayIntersection with simpler AABSPTree::intersectRay interface. -
  • G3D::MD2Model now uses floating point texture coordinates, which makes it easier to - write pixel shaders for MD2Models -
  • G3D::GImage::computeNormalMap now accepts a scale factor indicating how steep the input bump map is -
  • Added G3D::Shader support for the GLSL #version directive -
  • Optimized G3D::GImage::computeNormalMap to use primarily integer math -
  • G3D::AABox::contains(AABox) -
  • Added large file (>2GB) support to BinaryInput [Peter] -
  • Renamed graphics3d.h to G3D/G3D.h -
  • Renamed GLG3D.h to GLG3D/GLG3D.h -
  • Renamed G3DAll.h to G3D/G3DAll.h -
  • G3D::Quat::unitize now normalizes in place -
  • Added G3D::Quat::operator*= -
  • Removed G3D::FirstPersonManipulator's constructor--use the static G3D::FirstPersonManipulator::create method now. -
  • Changed BSPMap leaf bounds from Box to AABox--50% improvement in frustum culling speed -
  • Optimized BSPMap rendering performance -
  • Removed all deprecated APIs -
  • All accessors of the form "getXXX" that take no arguments are now named just "xxx" -
  • G3D::Sky::create is now named G3D::Sky::fromFile and no longer accepts a G3D::RenderDevice. G3D::Sky::render now requires a RenderDevice. -
  • G3D::GFont::fromFile no longer accepts a G3D::RenderDevice and G3D::GFont::draw2D now requires a RenderDevice. -
  • Removed an assertion in BinaryInput requiring that compressed buffers be copied on construction [Nick Bray] -
  • Removed CoordinateFrame::zLookDirection (use -1) -
  • Removed Capsule::endPoint (use point) -
  • Removed CoordinateFrame::getStrafeVector (use rightVector) -
  • Removed static constants (use equivalent lower-case methods) -
  • Removed Cylinder::getPoint1 (use point) -
  • Fix: BSPMap::getStartingPosition now works correctly on all maps [Jeff] -
  • Fix: Workaround for ATI drivers that do not support zero-area scissor region -
  • Fix: GL_EXT_texture_3D -> GL_EXT_texture3D -
  • Fix: ARB_texture_cube_map and EXT_texture_cube_map are now aliases on all cards -
  • Fix: EXT_texture_edge_clamp and SGIS_texture_edge_clamp are now aliases on all cards -
  • Fix: G3D::Sky now turns off lighting -
  • Fix: Win32Window now returns mousebutton and motion events according to the GEvent spec -
  • Fix: Win32Window now operates correctly in fullscreen mode -
  • Fix: Fixed TGA decode to load from the middle of a binaryinput -
  • Fix: Added texture coordinates to posed MD2Models -
  • Fix: prompt/debugAssert now correctly responds to button presses on OS X -
  • Fix: GConsole now filename completes after the first word -
  • Fix: RenderDevice::getDepthBufferValue now checks for the presence of a depth buffer. -
  • Fix: G3D::AABSPTree now correctly handles members with infinite bounds on ray intersection tests -
  • Fix: Removed use of tmpfile on Unix -
  • Fix: Java ReliableConduit now properly waits if the buffer is full when sending -
  • Fix: [ 1607693 ] Triangles/Second display is now correct (rates were too low in 6.10) -
  • Fix: NetworkDevice now does not perform a test broadcast during initialization -
  • Fix: G3D::LightweightConduit::ok is now false if any error occurs during initialization -
  • Fix: BSPMAP for cards without glMultiDrawElementsEXT -
  • Fix: [ 1584335 ] ReliableConduit incorrectly assumes it's ok -
  • Fix: RenderDevide::push2D no longer resets the frameBuffer. -
  • Fix: Framebuffer logic for counting number of attachments was broken -
  • Fix: [ 1581986 ] Matrix3::fromAxisAngle now normalizes the input vector -
  • Fix: [1490643] Linux/FreeBSD/OS X binaries are now compiled with -fno-strict-aliasing, which fixes some - memory corruption problems that occurred with full optimizations. -
  • Fix: Fixed all warnings on gcc-4.1 and VC8. -
  • Fix: Matrix and CoordinateFrame serializers inside G3D::AnyVal dropped data -
  • Fix: [ 1535759 ] valgrind finds initialization/deletion errors in TextOutput, Matrix [Chris Demetriou] -
  • Fix: Patched MD2Model to automatically reduce animation times to less than 100000; large time were overflowing double->int conversion and causing animations to appear scrambled. -
  • Fix: [ 1535292 ] global Table hashCode overloads broken [Chris Demetriou] -
  • Fix: [ 1535736 ] Fixed System.cpp memory allocator to compile on 64-bit machines correctly [Chris Demetriou] -
- -
-

- Changes in 6.10: -

    -
  • Optimized G3D::CoordinateFrame::pointToObjectSpace to be fully inlined via left-multiplication -
  • G3D::Matrix4::orthogonalProjection from a G3D::Rect2D -
  • G3D::RenderDevice::swapBuffers -
  • G3D::AnyVal -
  • G3D::ThirdPersonManipulator -
  • Added support for GL_SGIS_texture_lod in Texture. -
  • Fix: [ 1490655 ] MeshAlg::Edge::containVertex goes off the end of the array -
  • Fix: [ 1511729 ] NVIDIA rectangle generates errors in mipmap code -
  • Fix: [ 1507296 ] RenderDevice must swapBuffer on resize -
-
-

- Changes in 6.09: -

    -
  • glDepthBoundsEXT -
  • G3D::Quat::sameRotation -
  • Full loading of the GL_ATI_separate_stencil extension, support within RenderDevice -
  • platform.h undefines WIN32_LEAN_AND_MEAN, NOMINMAX after it has defined them -
  • G3D::Texture::Settings::maxMipMap -
  • Renamed Texture::Parameters to Texture::Settings (backwards compatible typedef added) -
  • Optimized IFSModel rendering by increasing internal VAR cache size and reducing the number of state changes. - Can now render more than 1000 IFSModels at 30 fps on GeForce 7800. -
  • G3D::System::mallocStatus -
  • Range checking on Vector2int16::operator[] -
  • GImage::BAYER_G8R8_B8G8_to_R8G8B8_MHC, GImage::BAYER_B8G8_G8R8_to_R8G8B8_MHC -
  • IFSModel and MD2Model now allocated their posed models using System::malloc -
  • Increased the memory maintained by G3D::System for buffer pools up to a total of 13 MB: - 8 MB tiny (preallocated), 1 MB small (on demand), 4 MB medium (on demand). This was observed to - dramatically increase performance (15x) in real programs that were - performance limited by memory allocation time. -
  • NetworkDevice now uses Winsock2.0 on Windows (controlled by the G3D_WINSOCK_MAJOR_VERSION/G3D_WINSOCK_MINOR_VERSION settings in NetAddress.h) -
  • G3D::Manipulator -
  • G3D::GApplet now runs installed G3D::GModules (except for graphics, which is left to the progrmamer) -
  • G3D::GApp::addWidget, G3D::GApplet::addWidget, G3D::GApp::removeWidget, G3D::GApplet::removeWidget -
  • G3D::Widget, G3D::WidgetManager -
  • G3D::System::getEnv() -
  • G3D::PosedModel2D -
  • G3D::DXCaps -
  • Increased precision of several Quat operations -
  • G3D::Quat::fuzzyEq -
  • G3D::Quat::operator- -
  • G3D::LineSegment::length, G3D::LineSegment::point -
  • Increased fuzzyEpsilon by a factor of 10 to take into account the new float32 focus of the APIs -
  • G3D::RegistryUtil -
  • G3D::LineSegment2D -
  • G3D::ConvexPolygon2D -
  • G3D::AxesShape -
  • contrib/shaders/showDepth -
  • G3D::Crypto with MD5 and CRC32 hashes -
  • TextureManager::findTexture, TextureManager::cacheTexture [Erik] -
  • Win32Window::_directInput created on-demand [Erik] -
  • WeakReferenceCountedPointer has more comparison operators [Erik] -
  • GImage::resolveFormat utility function [Erik] -
  • GLCaps supports MESA -
  • G3D::Win32Window and G3D::SDLWindow now release input capture and make the mouse visible on destruction -
  • G3D::OSWindow::setInputCaptureCount, G3D::OSWindow::inputCaptureCount, G3D::OSWindow::incInputCaptureCount, G3D::OSWindow::decInputCaptureCount -
  • GImage::makeCheckerboard -
  • G3D::Vector3::one() -
  • G3D::Shader now supports g3d_size(sampler2D) and g3d_invSize(sampler2D) extensions in GLSL shaders. -
  • Renamed GAppSettings to G3D::GApp::Settings (old name is supported but deprecated) -
  • Renamed GWindowSettings to G3D::OSWindow::Settings (old name is supported but deprecated) -
  • Renamed TextInput::Options to G3D::TextInput::Options (old name is supported but deprecated) -
  • G3D::FPManualController::setAutoActive for World of Warcraft style controller -
  • G3D::isSlash, G3D::isQuote -
  • G3D::GApplet::onEvent can now consume (i.e., prevent G3D::GApp from seeing) the event -
  • G3D::CoordinateFrame::fuzzyIsIdentity, G3D::CoordinateFrame::isIdentity, G3D::CoordinateFrame::fuzzyEq -
  • Matrix3::isOrthonormal -
  • [1421201] Removed excess gl (NVIDIA) headers -
  • Win32Window destructor now releases the mouse if it was captured and the current GL context is that window and the window was not created from an existing HDC/HWND -
  • Fix: com.graphics3d.g3d.ReliableConduit now correctly selects on the waiting socket -
  • Fix: [ 1166057 ] AABSPTree::beginBoxIntersection -
  • Fix: GLCaps::supports(ImageFormat) now returns correct results on all cards -
  • Fix: Shadow map rendering of default PosedModels now enables lighting -
  • Fix: G3D::UserInput now restores the mouse position after pureDeltaMouse is turned off -
  • Fix: G3D::Win32Window now clips precisely to the client area during an input grab. -
  • Fix: [ 1383042 ] free static variables on shutdown -
  • Fix: [1449115 ] Texture loading for odd-byte rows -
  • Fix: G3D::Win32Window now produces correct character and scan codes for key events -
  • Fix: G3D::GApplet::onEvent calls GApplet::processEvent by default -
  • Fix: [ 1444320 ] TextInput parsed ".1" as "1" instead of "0.1" -
  • Fix: G3D::Shape::type is now const -
  • Fix: 0 --> 0.0f FrameBuffer.h [Erik] -
  • Fix: Fixed Texture read-back dimensions for cube-map -
  • Fix: Missing #include in SkyParameters.h [Erik] -
  • Fix: Quad triangle counts are now accurate (were off by factor of 4 in 6.08) -
  • Fix: contrib/ArticulatedModel now correctly masks all components using the diffuse alpha in fixed function mode -
  • Fix: G3D::CoordinateFrame::getHeading was flipped front-to-back -
  • Fix: [ 1404487 ] Missing Alt key up/down events on Win32 -
  • Fix: [ 1484924 ] collisionTimeForMovingPointFixedBox normals -
-

-


- Changes in 6.08: -
    -
  • Moved Win32 linker statements out of platform.h for IncrediBuild compatibility. -
  • G3D::Texture and G3D::Sky now accept a rescaling factor -
  • Added GFont::fromMemory() [Corey] -
  • Added optional argument to Quat::slerp() for slerp/lerp angle threshold. [Corey] -
  • Across-the-board performance optimizations. Most apps should render 10% faster. - Includes removal of Milestones when using VBO VAR [Nick Bray], GFont::draw2D and - Draw::rect2D stripped down to raw OpenGL, consistent internal use of float, - increased RenderDevice state change optimization. -
  • Minimized header interdependencies (GLG3D headers no longer include all of G3D) -
  • Added GThread and GMutex classes. [Corey] -
  • Added ImageFormat::fromCode(). [Corey] -
  • Added Plane::distance() and Plane::closestPoint() helper methods. [Corey] -
  • G3D::ImageFormat::code, G3D::ImageFormat::colorSpace -
  • incompatible change G3D::MeshAlg::computeTangentSpace basis now computes a right-handed coordinate frame, - where the binormal direction is the negative of the direction it faced in G3D 6.07. -
  • Exposed G3D::RenderDevice::beforePrimitive and G3D::RenderDevice::afterPrimitive to end-user code for - integrating raw OpenGL calls. -
  • G3D::Framebuffer and G3D::Renderbuffer to implement the Framebuffer_object extension [Dan Hilferty] -
  • G3D::Shader::hasArgument -
  • G3D::Texture::getImage -
  • Changed SECOND, MINUTE, DAY, HOUR, SUNRISE, SUNSET, MIDNIGHT, METER, KILOMETER to enum values instead of #defines -
  • G3D::Texture::Parameters; deprecated most Texture constructors in favor of ones that use this class -
  • Moved most image manipulation routines into GImage. -
  • G3D::GImage now allocates the underlying buffer in multiples of bytes to allow slight overflor for MMX algorithms -
  • G3D::GImage::BAYER_R8G8_G8R8_to_R8G8B8_MHC -
  • G3D::GImage::R8G8B8_to_Y8U8V8 -
  • G3D::GImage::Y8U8V8_to_R8G8B8 -
  • G3D::GImage now supports PPM binary -
  • Various Rect2D helpers [Nick Bray] -
  • ConvexPolyhedron improved clipping [Nick Bray] -
  • G3D::System::build -
  • G3D::System::calloc -
  • G3D::GImage::convertToRGBA -
  • contrib/AVI can read most AVI files on Windows. -
  • contrib/wxGWindow now uses wxWidgets 2.6.2 -
  • G3D_DEBUG now controls whether debug code is enabled; it defaults to the value of _DEBUG -
  • zlib upgraded to 1.2.3 [Corey] -
  • zlib now statically linked on Win32 (no longer requires zlib1.dll at runtime) [Corey] -
  • G3D::MeshShape -
  • Changed std::string hashCode to use CRC32 to reduce collisions -
  • G3D::crc32 -
  • Added occlusion query #defines [Nick Bray] -
  • G3D::Win32Window now shares textures and vertex buffers across all GL contexts -
  • G3D::Win32Window now enforces single-threading among GL contexts -
  • G3D::GLCaps::slowVBO -
  • G3D::VARArea now uses main memory vertex buffers on cards with slow VBO implementations. -
  • G3D::Matrix3::toString [Peter] -
  • G3D::Matrix4::toString [Peter] -
  • G3D::Color3::fromHSV [Peter] -
  • G3D::Color3::toHSV [Peter] -
  • G3D::Color3::jetColorMap [Peter] -
  • Optimized G3D::iRound (now faster than casting!) -
  • G3D::MD2Model::create now accepts a scale factor -
  • #G3D_DEPRECATED macro -
  • #G3D_CHECK_PRINTF_ARGS, #G3D_CHECK_VPRINTF_ARGS macros to allow - checking of printf argument strings under gcc at compile time with - -Wformat. -
  • G3D::TextInput::filename -
  • G3D::TextInput::Options::msvcSpecials -
  • G3D::TextInput::Options::startingLineNumberOffset -
  • G3D::TextInput::readSymbolToken [cgd] -
  • G3D::TextInput::readStringToken [cgd] -
  • G3D_DEPRECATED macro -
  • Threadsafe G3D::ReferenceCountedPointer -
  • G3D::AtomicInt32 -
  • G3D::GThread [Corey] -
  • G3D::Array::popDiscard -
  • Optimized multi-argument Array::append -
  • G3D::GFont 2x faster than in G3D 6.07 -
  • G3D::RenderDevice::pushState 2x faster than in G3D 6.07 -
  • G3D::RenderDevice::pushState no longer stores GL texgen and fog information -
  • G3D::Draw::fastRect2D -
  • G3D::System::outOfMemoryCallback -
  • G3D::Queue::fastClear [Chris Demetriou] -
  • G3D::Rect2D::x0y1 and x1y0 -
  • G3D::GLCaps bug tests now run in a separate GL context [Erik Cassel] -
  • G3D::GApplet tracks real and simulation time. -
  • contrib/Q3Map updated to correctly render instanced objects [Alex Rice] -
  • G3D::OSWindow subclasses now required to invoke OSWindow::loadExtensions -
  • G3D::Quat::log for non-unit quats and for real-only quats. -
  • G3D::GApplet::doUserInput -
  • G3D::GApp prints time for each component -
  • G3D::Stopwatch -
  • G3D::OSWindow::renderDevice() -
  • G3D::OSWindow::current() -
  • G3D::GLCaps::hasBug_redBlueMipmapSwap and workaround for G3D::Texture on Radeon 7500 -
  • Fix: CollisionDetection::penetrationDepthForFixedSphereFixedPlane() contact point and normal values. [Corey] -
  • Fix: Quat::slerp has invalid shortest path [Corey] -
  • Fix: G3D::drawFeatureEdges now uses correctly normalized face edges (and offers a crease angle) -
  • Fix: G3D::SDLWindow now releases the mouse on Linux during an assertion. -
  • Fix: All keys are reset to up when Win32Window loses focus. [Corey] -
  • Fix: gaussRandom is unit gaussian [Corey] -
  • Fix: [ 1418276 ] 6.08: Unsupported format for depth texture -
  • Fix: Ignoring extra/unused set Shader arguments. [Corey] -
  • Fix: [ 1229205 ] uniform texture array (Could not set indexed array uniforms). [Corey] -
  • Fix: incompatible change BinaryInput/BinaryOutput copy constructors and assignments were accessible. [Corey] -
  • Fix: RenderDevice::screenshotPic would corrupt GImage's heap. [Corey] -
  • Fix: Alt-Tab window switching caused an invalid Alt key state. [Corey] -
  • Fix: Incorrect window size event in Win32Window sent to OpenGL. [Corey] -
  • Fix: [ 1227915 ] Textures don't bind on ATI under GLSL. -
  • Fix: [ 1358477 ] ray-plane intersection bug [Dan Keefe] -
  • Fix: [ 1370665 ] hash_map moved to stdext in VC8 (2005) -
  • Fix: ToneMap extended to use DIM_2D_NPOT instead of DIM_2D_RECT -
  • Fix: Texture::copyFromScreen now works with DIM_2D_NPOT textures -
  • Fix: Wrapped debugAssertM in do {} while (0) to ensure correct compilation in single-line statements [ERik Cassel] -
  • Fix: G3D::Draw::cylinder now renders the bottom correctly -
  • Fix: Array::front now compiles under gcc -
  • Fix: G3D::Ray::distance used to measure against the origin [David] -
  • Fix: [ 1293151 ] ArticulatedModel clipping on Radeon -- disabled auto-mipmap generation on mobile radeon 9xxx -
  • Fix: G3D::TextInput now parses ^=, character 255 correctly [cgd] -
  • Fix: G3D::TextInput now reports line numbers correctly with raw newlines [cgd] -
  • Fix: .ICO files with transparency loaded incorrectly [Corey] -
  • Fix: G3D::Draw::rect2DBorder inner border was 1 pixel too thick. -
  • Fix: [ 1326173 ] Win32Window::init should call makeCurrent.[Erik Cassel] -
  • Fix: [ 1326423 ] G3D::Queue::_copy broken [Chris Demetriou] -
  • Fix: [ 1313293 ] 6.08: TextInput gets symbol extendedType() wrong [Chris Demetriou] -
  • Fix: IFSModel::save, for PLY2 forgot newlines [Peter] -
  • Fix: Quat(Matrix3) now computes trace correctly (gave negative quats in some cases) -
  • Fix: Setting RenderDevice::polygonOffset now always produces a depth shift, - even for faces perpendicular to the view axis. -
  • Fix: GImage now auto-resolves formats for files with 1 character base names -
  • Fix: WeakReferenceCountedPointer cycle bug -
  • Fix: Corrected lag encountered when using some ReliableConduit constructors [Dan Keefe] -
- -

-


- Changes in 6.07: -
    -
  • G3D::OSWindow::makeCurrent -
  • Win32 release binaries now built with no debug information (used to have line numbers) -
  • AABox::AABox enforces the constraint low <= high -
  • Optimized G3D::Array, Table, Queue, and Set for performance. Now significantly (up to 10x) faster - than their std::counterparts. -
  • G3D::Vector3(Vector2, float) constructor -
  • G3D::Vector2::fastDirection -
  • G3D::TextInput::Options::cComments -
  • G3D::TextInput::Options::escapeSequencesInStrings -
  • G3D::TextInput::Options::otherCommentCharacter2 -
  • G3D::TextInput::WrongString -
  • GLCaps::supports_GL_ATI_separate_stencil -
  • GLCaps can now test a card/driver and detect specific bugs: -
    • G3D::GLCaps::hasBug_glMultiTexCoord3fvARB -
    • G3D::GLCaps::hasBug_normalMapTexGen -
    -
  • G3D::ReferenceCountedPointer::downcast for non VC6 compilers -
  • Improved G3D::ReferenceCountedPointer documentation to make subclassing features clearer -
  • Moved typedef for uint into G3D namespace and into g3d (was in glg3d) -
  • G3D::Shape -
  • G3D::Cylinder -
  • G3D::System::malloc, G3D::System::realloc, G3D::System::free for fast allocation of small objects -
  • G3D::Draw::plane -
  • G3D::Draw::cylinder -
  • G3D::gaussRandom -
  • GCamera deserialize(BinaryInput) & serialize(BinaryOutput) functions [Peter] -
  • G3D::GApp now writes a description of the whole system to the log to aid debugging. -
  • [ 1217928 ] OpenGL occlusion query entry points are loaded on initialization -
  • New texture interpolation modes: BILINEAR_MIPMAP, NEAREST_MIPMAP, NEAREST_NO_MIPMAP -
  • New texture formats: -
      -
    • G3D::ImageFormat::L16; -
    • G3D::ImageFormat::L16F; -
    • G3D::ImageFormat::L32F; -
    • G3D::ImageFormat::A16; -
    • G3D::ImageFormat::A16F; -
    • G3D::ImageFormat::A32F; -
    • G3D::ImageFormat::LA4; -
    • G3D::ImageFormat::LA16; -
    • G3D::ImageFormat::LA16F; -
    • G3D::ImageFormat::LA32F; -
    • G3D::ImageFormat::RGB16; -
    • G3D::ImageFormat::RGB16F; -
    • G3D::ImageFormat::RGB32F; -
    • G3D::ImageFormat::RGBA16; -
    • G3D::ImageFormat::RGBA16F; -
    • G3D::ImageFormat::RGBA32F; -
    -
  • isValidPointer and isValidHeapPointer no longer check the Win32 debug heap in order to support offset and padded memory blocks. -
  • Restructured unit tests -
  • G3D::CoordinateFrame::lookRay [David Baszucki] -
  • G3D::System::describeSystem, G3D::NetworkDevice::describeSystem, G3D::RenderDevice::describeSystem -
  • G3D::Array performance tuning for short arrays and arrays of small objects -
  • Added glext.h entries for GL_ARB_draw_buffers, GL_ARB_texture_rectangle, - GL_ARB_color_buffer_float, GL_ARB_half_float_pixel, GL_ARB_texture_float, - and GL_ARB_pixel_buffer_object extensions -
  • IFSModel::create added weld option, defaults to true (to keep compatibility). [Peter] -
  • G3D::RenderDevice::alphaTestReference, RenderDevice::alphaTest -
  • G3D::VAR::set -
  • G3D::Log::vprintf -
  • G3D::WeakReferenceCountedPointer -
  • GCC 4.0 build support added [Corey] -
  • G3D::CoordinateFrame::lookAt now gives a valid output even when look == up -
  • contrib/GChunk -
  • GLCaps now loads GL_EXT_framebuffer_object functions -
  • Added MSVC 6 support for C99 restrict keyword -
  • G3D::Win32Window properly resizes viewport on window resize [Corey] -
  • G3D::BinaryFormat, G3D::byteSize, G3D::binaryFormatOf -
  • Removed dead ManualCameraControllerHelper code -
  • Added consistent area and volume methods to geometric primitives, deprecated old methods. -
  • Fast G3D::BinaryInput::read / G3D::BinaryOutput::write methods for arrays -
  • Enabled cube mapping on Radeon mobility cards and added a workaround to the known problems with texcoords on those cards. -
  • Can now create G3D::Win32Window with existing HWND and HDC [Corey] -
  • G3D::VertexAndPixelShader::ArgList::set(std::string, Array)-- [ 1192401 ] Shader support arrays -
  • Fix: SDLWindow used std::string's instead of C strings in printf and format inside some exception handling code. [Peter] -
  • G3D::X11Window (same as SDLWindow in this release) -
  • Fix: [ 1277854 ] Win32Window fails on 24-bit modes -
  • RFE: [ 1242466 ] Inline Matrix3 methods -
  • Fix: [ 1226272 ] end caps of capsules in wrong position -
  • Fix: G3D::ImageFormat::LA8 now has 8-bits per channel -
  • Fix: [ 1124491 ] Remove GL_SAMPLER_2DRECT_ARB -
  • Fix: [ 1257113 ] G3D::Queue problems comining pushFront and pushBack -
  • Fix: MeshAlg::Weld now linear time (was O(n^2) due to a bug) -
  • Fix: [ 1298873 ] fast & correct CoordinateFrame::lerp -
- -

-


- Changes in 6.06: -
    -
  • G3D::Lighting::emissiveScale -
  • G3D::RenderDevice::drawBuffer -
  • G3D::RenderDevice::debugNumMinorStateChanges, debugNumMinorOpenGLStateChanges, debugNumMajorStateChanges, debugNumMajorOpenGLStateChanges. -
  • In stereo mode, Texture::copyFromScreen automatically chooses the left/right buffer to read based on the current glDrawBuffer -
  • contrib/ArticulatedModel/ToneMap -
  • Lazy state changes for shaders -
  • 50% performance improvement for G3D::BinaryInput, G3D::BinaryOutput when machine endian matches file endian -
  • Textures load with default of maxAnisotroy = 2.0 -
  • maxAnisotropy argument to G3D::Texture constructors. -
  • GLCaps now loads GL_ATI_fragment_shader extension -
  • contrib/ArticulatedModel now supports rigid body hierarchies -
  • Added TEX_SUBTRACT, TEX_ADD_SIGNED, TEX_DOT3, TEX_DOT3_RGBA modes for G3D::RenderDevice::setTextureCombineMode -
  • G3D::RenderDevice now cleans up all static G3D::VARArea s when it shuts down -
  • FIX: [ 1208157 ] GLSL slow on ATI -
  • FIX: Off-by-one on viewport scale for 2D rendering -
  • FIX: MeshAlg::computeTangentSpaceBasis now works correctly -
  • FIX: 6.05 enabled all fixed function lights by default. This caused major performance problems on some cards. -
  • FIX: Extended cube map workaround to all Radeon Mobility cards -
  • FIX: Added check for glBlendEq before calling in RenderDevice -
  • FIX: Added a test for GL_EXT_texture_env_add in RenderDevice -
  • FIX: [ 1191817 ] unsigned warnings in BinaryInput -
- -
-

- Changes in 6.05: -

    -
  • G3D::BAYER_G8B8_R8G8_to_R8G8B8_MHC -
  • G3D::Quarter_R8G8B8_to_BAYER_G8B8_R8G8 -
  • G3D::BAYER_G8B8_R8G8_to_Quarter_R8G8B8 -
  • contrib/Matrix -
  • contrib/Java -
  • Texture::alphaOnlyVersion -
  • Draw::sphere speed improved over 25% with single quad strip (improves Draw::capsule) [Corey] -
  • Allow 1-channel GImage saving - BMP (expanded to RGB), PNG [Corey] -
  • Allow 1-channel GImage loading - PNG [Corey] -
  • Added shader and framebuffer extensions to glext.h -
  • All files used during current execution are available via G3D::getFiles() [Corey] -
  • Implemented OSX version of glGetCurrentContext with CGL. [Corey + Derek] -
  • ReferenceCountedObject is-in-heap checks were removed to allow better multiple and virtual inheritance for reference counted objects. ReferenceCountedPointer still appropriately checks does an is-in-heap check on assignment. [Corey] -
  • Added Dev C++ compatability -
  • glGetAttribLocationARB -
  • Changed GLight == operator to not use memcpy (was causing issues due to byte padding on some compilers) -
  • Made CoordinateFrame destructor non-virtual (eliminates vtable) -
  • Added new FAQ documentation -
  • Added support to G3D::BinaryInput and G3D::BinaryOutput - reading and writing huge (larger than available memory) files. - Files are still restricted to about 2 GB total, and compressed - files must fit entirely in memory. -
  • Tweaked allocation strategy for small G3D::Array -
  • G3D::Texture::rect2DBounds, G3D::Texture::vector2Bounds -
  • G3D::Vector4 * G3D::Vector4, Vector4 / Vector4 -
  • G3D::Array::operator=(std::vector) -
  • G3D::Sky::getEnvironmentMap now returns the top texture on machines - that don't support cube maps. -
  • glDisableAllTextures() -
  • G3D::setFailureHook -
  • G3D::Shader::fromStrings now accepts optional names for the vertex and pixel shader -
  • G3D::Shader no longer requires values for declared but unused uniform variables -
  • G3D::RenderDevice now stores texture matrix at 32-bit precision (for faster push/popState) -
  • G3D::RenderDevice::setTextureLODBias -
  • G3D::Shader now supports shadow map arguments -
  • G3D::Shader::ArgList checks to see if Texture arguments are null -
  • G3D::RenderDevice::setAlphaWrite now defaults to true if the OSWindow has an alpha channel. -
  • G3D::RenderDevice::screenshotPic now supports alpha -
  • contrib/VideoSerializer -
  • G3D::BinaryOutput::writeBits, G3d::BinaryInput::readBits -
  • G3D::Sky can now be initialized with a NULL renderDevice, provided a non-null one - is used with the G3D::Sky::render method. -
  • G3D::pi(), G3D::halfPi(), G3D::twoPi() added to replace defines [Corey] -
  • contrib/Q3Map -
  • Increased G3D::Draw::sphere performance using vertex arrays. -
  • G3D::Array::fastClear -
  • G3D::AABSPTree::insert(Array) -
  • G3D::Texture::sizeOfAllTexturesInMemory -
  • G3D::VARArea::sizeOfAllVARAreasInMemory -
  • G3D::RenderDevice stores cameraToWorldMatrixInverse for faster coordinate system changes. -
  • inlined G3D::Matrix3::operator= for performance -
  • Created installer for Windows install [Corey] -
  • Reorganized the documentation topic index based on abstraction level, added hyperlinks to demo/contrib code -
  • G3D::ReliableConduit and G3D::LightweightConduit now send and receive - objects directly; no need to make a G3D::NetMessage. G3D::NetMessage - and associated methods are now deprecated. -
  • Win32 GUI G3D::prompt now auto-expands \\n to \\r\\n in prompt string [Corey] -
  • G3D::Draw::frustum -
  • Increased timeout and attempts for G3D::ReliableConduit to handle huge (1 MB) packets -
  • G3D::BinaryOutput::reset (memory writing only; not supported for disk) -
  • Reduced overhead for G3D::ReliableConduit and - G3D::LightWeightConduit send routines -
  • Added PPM/PGM/PBM ASCII encode/decode support to G3D::GImage [Corey] -
  • New G3D::PosedModel rendering methods appropriate for shadow casting - (with efficient default implementations). -
  • G3D::Lighting -
  • Changed RenderDevice::TEX_INTERPOLATE to mean GL_DECAL and added TEX_BLEND for GL_BLEND -
  • G3D::CoordinateFrame::upVector -
  • G3D::GLight::diffuse -
  • G3D::Rect2D::contains is now const -
  • Rewrote G3D::BinaryOutput to not use G3D::Array -
  • G3D::MD2Model::textureMatrix -
  • G3D::MeshAlg::computeBounds(vertex, index, ...) -
  • G3D::RenderDevice::colorWriteEnabled(), depthWriteEnabled, alphaWriteEnabled -
  • G3D::RenderDevice::setSpecularCoefficient(Color3) -
  • G3D::VAR::maxSize -
  • G3D::RenderDevice::enableTwoSidedLighting -
  • G3D::PosedModel::hasTransparency -
  • G3D::PosedModel::sort -
  • G3D::RenderDevice::renderMode -
  • G3D::MeshAlg::computeNormals(geometry, indexArray); -
  • contrib/ArticulatedModel (beta 3DS support) -
  • G3D::RenderDevice::swapBuffersAutomatically allows caller to suppress page flip. -
  • Added coordinate system documentation. -
  • RenderDevice::enableClip2D, RenderDevice::disableClip2D (scissor region) -
  • contrib/wxGWindow is stable and full featured-- use wxWidgets 2.5.3 with G3D! -
  • G3D::fileIsNewer -
  • G3D::isDirectory -
  • G3D::filenameContainsWildcards -
  • G3D::filenamePath -
  • G3D::Draw::lineSegment now accepts a scale (allowing arrows and axes to thicken appropriately) -
  • G3D::Rect2D::largestCenteredSubRect -
  • G3D::Matrix4::serialize, G3D::Matrix4::deserialize -
  • glTexImage3DEXT -
  • Removed glut.lib and glut.dll from the win32-lib directory. -
  • G3D::writeStringToFile, G3D::TextOutput, and G3D::BinaryOutput now flush by default (safe, not fast). -
  • Shifted push2D by 0.375 pixels as recommended in the OpenGL guide to bias integer coords towards pixel centers -
  • G3D::Draw::rect2DBorder -
  • G3D::Rect2D::border -
  • G3D::RenderDevice now creates a G3D::Win32Window on Windows instead of a G3D::SDLWindow. SDLWindow is now - deprecated on Windows. -
  • G3D::VARArea now updates allocation sizes instead of G3D::VAR internally. Added - more accessor methods to VARArea to futher remove VAR from VARArea internals. [Corey] -
  • VARSystem.cpp moved to VARArea.cpp - filename change only! [Corey] -
  • Linux build system updated: - Builds only static libraries, Does not require libtool/libtoolize anymore, - Does not check for or require libraries that normally linked with the .so files, - Automatically builds Test project with iCompile during install. [Corey] -
  • G3D::Quat::deserialize, G3D::Quat::serialize -
  • G3D::PhysicsFrame::deserialize, G3D::PhysicsFrame::serialize -
  • G3D::TextInput::Options::singleQuotedStrings (defaults to true, changing the behavior - from previous versions). -
  • G3D::Token::extendedType returns information disambiguating characters and strings - and floats and ints. -
  • Added data/ah64-body and ah64-rotor -
  • demos/Network_Demo now uses a helicopter model instead of a plane -
  • G3D::VARArea::gl_vertexBufferObject and G3D::VARArea::gl_basePointer for breaking - the VARArea abstraction. -
  • GLG3D.h no longer links against SDLMain.lib on Windows if _CONSOLE is defined - (since console programs have no WinMain). -
  • SDL's redefinition of main is cleared when not linking sdlmain.lib [Corey] -
  • Moved contrib/Win32Window to G3D::Win32Window -
  • G3D::TextInput::readSymbols -
  • contrib/Image [Morgan] -
  • contrib/wxGWindow [Morgan] -
  • Added support for full-screen antialiasing to contrib/Win32Window -
  • Added joystick support to contrib/Win32Window [Corey] -
  • Win32Window fully-implements OSWindow [Corey] -
  • Texture now supports DDS(2D/CubeMap) and PNG files [Corey] -
  • Added Win32 pbuffer routines (no G3D wrapper, though-- we're waiting for the new ARB API). -
  • G3D::PosedModel::texCoords -
  • G3D::IFSModel now loads IFS 1.1 [Peter] -
  • G3D::IFSModel now loads and saves PLY2 files (plain text IFS format) [Peter] -
  • Automatically switch to glCompressedTexImage2D in G3D::Texture::fromMemory [Corey] -
  • Added G3D::Sky::fromCubeMap for preloaded CubeMap Texture::Ref's [Corey] -
  • Added G3D::Sky::fromFile and deprecated Sky::create [Corey] -
  • Demo and Test projects now build with iCompile, which is included [Corey] -
  • Fix: TextOutput::writeString now escapes special characters -
  • Fix: AABSPTree::serializeStructure -
  • Fix: Properly handle gl_ uniforms on Radeon for Shader -
  • Fix: [ 875467 ] OS X debugBreak (requires default XCode debug menu item 'Break on DebugStr()') [Corey + Derek] -
  • Fix: Can make a G3D::Texture::fromGImage with one channel (defaults to L8 format) -
  • Fix: [ 1149972 ] 6.05: Make Sky render correctly on low-end cards (no Cube mapping) [Corey] -
  • Fix: [ 1032742 ] OS X _DEBUG not defined [Derek] -
  • Fix: 16-bit integer reads in BinaryInput that always reversed endianness. (OSX file reading) [Corey + Derek] -
  • Fix: Matrix4 operator[] was returning a matrix value cast to a pointer [Corey] -
  • Fix: Matrix3 and Matrix4 had missing float* / const float* operators [Corey] -
  • Fix: Rect2D::clip broken for types other than Vector2 -
  • Fix: RenderDevice::configureShadowMap result depends on objectToWorldMatrix -
  • Fix: [ 1150650 ] DebugBreak() undefined -
  • Fix: [ 1111534 ] Network Demo crashes starting 2nd server on same machine -
  • Fix: [ 1102091 ] ReliableConduit::receive times out -
  • Fix: Implemented MD2Model::objectSpaceBoundingX methods. -
  • Fix: G3D::Triangle::area is now zero for zero-area triangles (was inf) -
  • Fix: AABSPTree with extent on MSVC 6 no longer enters infinite loop in std::sort -
  • Fix: [ 1105641 ] Does not build with g++ 3.4.x [Corey] -
  • Fix: [ 1103619 ] RenderDevice::countPrimitive is wrong (changed to RenderDevice::countTriangles) [Corey] -
  • Fix: AABSPTree::BoxIntersectionIterator doesn't compile -
  • Fix: [ 1101680 ] copyfile won't overwrite (on Windows now overwrites) [Corey] -
  • Fix: [ 1101646 ] GCamera::frustum incorrect for non-square viewport -
  • Fix: Ultra bright lens flare at sunset [Nicholas Bray] -
  • Fix: IP address strings were reversed by NetAddress(std::string) -
  • Fix: TextInput now returns end of file token for files without trailing whitespace -
  • Fix: [ 1094166 ] 6.05: Release mouse stuck on x-axis [Corey + Morgan] -
  • Fix: Recognize buggy ATI Radeon Mobility cube maps and work around -
  • Fix: Textures now initialize without setting error bit on cards without GL_ARB_shadow -
  • Fix: filenameBaseExt now operates correctly on strings with both \ and / slashes. -
  • Fix: [ 1062659 ] BinaryInput::BinaryInput() memory leak -
  • Fix: Removed RenderDevice::polygonCount, which was never used. -
  • Fix: TextInput::readNumber no longer accepts double preceeding +/- on numbers when Options::signedNumbers is true -
  • Fix: [ 1038733 ] OSWindow cannot set icon properly [Corey] -
  • Fix: [ 939400 ] Linux mouse set position (Wild camera swinging on startup) [Corey] -
  • Fix: [ 1042591 ] Software GL Causes Assertion [Corey] -
  • Fix: [ 1036634 ] debugAssert doesn't work on MSVC 7 [Corey] -
  • Fix: [ 1049024 ] Fix compile warnings from gcc/Linux build [Corey] -
  • Fix: [ 1051272 ] Win32Window doesn't use GWindowSettings properly. [Corey] -
  • Fix: Win32Window clips the proper cursor region during input capture. [Corey] -
  • Fix: GWindows now center and maximize on the primary monitor for Windows. -
  • Fix: [ 1052945 ] TextOutput wordWrap starts on newlines -
  • Fix: [ 1050957 ] TextInput readNumber support for capital 'E' numbers. -
  • Fix: [ 1049674 ] TextInput failes on X. numbers. -
  • Fix: [ 1044028 ] Linux TextOutput Warning -
  • Fix: [ 1032750 ] Grayscale JPG errors [Corey] -
  • Fix: [ 1036225 ] Encode TGA support strips alpha channel [Corey] -
  • Fix: [ 1038631 ] CoordinateFrame::slerp (Quat::slerp has fix) [Corey] -
  • Fix: [ 1033686 ] GImage::GImage(filename) dies on certain (BMP) images [Corey] -
  • Fix: Texture mapping modes for pre-OpenGL 1.3 cards [Dan & Morgan] -
- -
-

- Changes in 6.04: -

    -
  • G3D Manual! [ Morgan and Sascha ] -
  • Initial MSVC7 build script. MSVC7 is not an officially supported platform - however the release contains MSVC7 precompiled binaries and the build script - will automatically build on both 6 and 7. -
  • Improved performance of G3D::writeStringToFile -
  • G3D::ReferenceCountedPointer assignment now allows compile time subtyping -
  • G3D::ReferenceCountedPointer != operator -
  • G3D::ReferenceCountedPointer::notNull -
  • G3D::GLight::directional now normalizes the light vector -
  • G3D::setAssertionHook -
  • [ 1029256 ] G3D::Shader / G3D::VertexAndPixelShader define g3d_ uniforms inside shaders -
  • static G3D::IFSModel::save/load for writing/reading IFS files -
  • G3D::TextInput allows ' inside quoted strings -
  • G3D::TextInput allows \ as a symbol token -
  • G3D::TextInput supports an arbitrary comment character (e.g. '#') -
  • Precompiled binaries for VisualC++ 7 (.NET 2002/2003) -
  • VisualC++ 7 (.NET 2002/2003) supported by build script -
  • Build now MOVEs binaries instead of COPYing them on Windows (allows - two compilers to output to the same location) -
  • G3D Guide overview documentation -
  • Changelog and Error FAQ moved under Doxygen -
  • Build scripts and documentation now under the 'doc' .dsp on Windows -
  • Textures now support a DepthReadMode that can be used to perform hardware - shadow map comparisions. RenderDevice::configureShadowMap now requires - an appropriately configured texture-- in previous releases it would - reconfigure the texture for you. -
  • G3D::UserInput::keyReleased, G3D::UserInput::ReleasedKeys -
  • G3D::Array::randomElement -
  • G3D::Array::insert -
  • G3D::RenderDevice::getObjectToWorldMatrix and getCameraToWorldMatrix now return - const CoordinateFrame& -
  • Optimized G3D::Array::randomize -
  • G3D::cyclicCatmullRomSpline -
  • G3D::wrap -
  • contrib/AudioDevice -
  • G3D::System::time(); -
  • More precise System::sleep -
  • G3D::IFSModel::pose with no arguments -
  • G3D::AABSPTree::serializeStructure, deserializeStructure, -
  • serialize(Vector3::Axis, BinaryOutput), deserialize(Vector3::Axis, BinaryInput), -
  • "glslc" GLSL compiler in the tools directory for getting compile-time errors from shaders -
  • GLCaps::init now takes optional debug log -
  • G3D::VertexAndPixelShader static constructors take optional 'debug' argument -
  • GWindowSettings::visible; Win32Window can now start invisible -
  • [ 991147 ] glBlendEquationEXT, RenderDevice::BlendEq, min, max, subtract, reverse subtract alpha blending -
  • [ 989785 ] Draw::rect2D -
  • GLCaps::numTextureCoords, GLCaps::numTextureUnits, GLCaps::numTextures -
  • GLCaps::G3D_MAX_TEXTURE_UNITS -
  • Rect2D::corner -
  • GCamera::getFrustum, GCamera::frustum, GCamera::Frustum, GCamera::Frustum::Face -
  • Plane constructor that accepts Vector4s (possibly at infinity) -
  • AABox::inf, AABox::zero, AABox::maxFinite -
  • AABox::intersects(Sphere) -
  • Vector3::minFinite, Vector3::maxFinite -
  • Plane::halfSpaceContainsFinite -
  • Plane::halfSpaceContains(Vector4) -
  • AABSPTree::getIntersectingMembers(Array) -
  • AABSPTree::getIntersectingMembers(GCamera::Frustum) for view-frustum culling -
  • AABSPTree::getIntersectingMembers(Sphere) -
  • AABox::split -
  • Extended AABox::culledBy, Box::culledBy, and Sphere::culledBy with extra - information for bounding volume hierarchies -
  • G3D::computeNormalMap -
  • Matrix3::fuzzyEq(Matrix3) -
  • Removed System::sleep(0.02) from GLG3D demo to give more accurate performance measure -
  • [ 965824 ] changed link library defaults -
  • serialize/deserialize for int, bool, double, float, std::string -
  • G3D::TextOutput -
  • [ 976924 ] Texture::texelWidth -
  • [ 973413 ] VertexAndPixelShader::ArgList::set can be called more than once per variable -
  • OSWindow::setIcon(std::string filename) -
  • Texture::fromMemory that takes a single image (instead of an array of images) -
  • [972604] RenderDevice::setTextureMatrix(uint, Matrix4) -
  • [972747] Rect2D::center -
  • GImage and Texture now load ICO files -
  • GL_SAMPLER_1D_ARB, 2D, 3D, CUBE -
  • Win32Window mouse events -
  • Added normals to AABox collision results -
  • Fix: [ 1026534 ]various cast bugs using Ref types. - Removed G3D::ReferenceCountedPointer implicit cast to underlying pointer type - This is technically an incompatible change, however we found no occurance - in the library or demos using this that was not a bug! -
  • Fix: VAR constructor takes VARAreaRef instead of VARArea* Incompatible change -
  • Fix: ManualCameraController is prevented from looking precisely along the Y-axis, which would cause - a singularity. -
  • Fix: Added '?' as a valid symbol Token -
  • Fix: [ 946235 ] GFont::align right w/ fixed_spacing -
  • Fix: [ 1001033 ] RenderDevice with 0 texture units -
  • Fix: GLCaps:: ARB stencil two side -> EXT stencil two side (stencilled shadows were broken) -
  • Fix: [ 993449 ] vsnprintf crashes MSVC 7 -
  • Fix: [ 991320 ] Pointer truncation Warnings -
  • Fix: [ 981440 ] AUTO with Texture::fromMemory -
  • Fix: Plane::halfSpaceContains now works for infinite and semi-infinite points -
  • Fix: [ 979032 ] Quat <-> Matrix3 roundtrip inverts -
  • Fix: [ 976743 ] document GLCaps functions -
  • Fix: [ 976746 ] #include GLCaps in g3dall -
  • Fix: [ 973550 ] sampler2DRect now supported in GLSL shaders (NVIDIA only; ATI drivers are broken) -
  • Fix: [ 973490 ] Win32Window width/height off by non-client amount -
  • Fix: [ 961827 ] In debug mode, RenderDevice tries to access - GL_MAX_TEXTURE_IMAGE_UNITS_ARB and an assertion fails on cards that - don't support it. -
  • Fix: Texture binding for VertexAndPixelShader -
-
-

- Changes in 6.03: -

    -
  • Matrix4::approxCoordinateFrame -
  • Vector2(const Vector2int16&) [Giulio] -
  • RenderDevice::setObjectShader -
  • RenderDevice::setVertexAndPixelShader -
  • G3D::RenderDevice supports "..._CURRENT" as an option for most settings -
  • inf -> inf(), nan -> nan(), NAN -> NAN() - This is an incompatible change-- it was needed to fix a bug with the order - of initialization of globals -
  • GImage::sizeInMemory -
  • Defined std::ostream << NetAddress, std::ostream << Vector3 -
  • 'build doc' copies the contrib directory to the install directory -
  • LightweightConduit::PacketSizeException -
  • Quat::unitRandom() [Giulio] -
  • Color3::wheelRandom -
  • GImage::save and encode now const [Thanks Arni Mar Jonsson] -
  • LightweightConduit::send that accepts multiple destinations -
  • ReliableConduit::multisend -
  • Moved IFSBuilder from demos to contrib -
  • LightweightConduit and ReliableConduit send/receive can now take references as well as pointers -
  • RenderDevice::clear() that takes no arguments -
  • RenderDevice::setShader -
  • G3D::GApp now catches ShaderGroup::ArgumentError exceptions -
  • System::operatingSystem() now includes a version number on Linux -
  • SDLWindow no longer initializes the audio system; use SDL_InitSubsytem if you need audio. -
  • Extended GLenumToString with GL_SHADER_OBJECTS_ARB types. -
  • NVIDIA p-buffer: GLX_SAMPLE_BUFFERS_ARB, GLX_SAMPLES_ARB, GLX_FLOAT_COMPONENTS_NV, - glXDestroyGLXPbufferSGIX, glXChooseFBConfigSGIX, glXCreateGLXPbufferSGIX, - glXCreateContextWithConfigSGIX, glXQueryGLXPbufferSGIX -
  • NVIDIA swap lock: glXJoinSwapGroupNV, glXBindSwapBarrierNV, glXQuerySwapGroupNV, - glXQueryMaxSwapGroupsNV, glXQueryFrameCountNV, glXResetFrameCountNV -
  • OSWindow::requiresMainLoop, OSWindow::runMainLoop (Beta) -
  • OSWindow::pollEvent, SDLWindow::pollEvent -
  • G3D::GApp accepts an optional OSWindow on construction -
  • G3D::VertexAndPixelShader, G3D::ObjectShader (Beta) -
  • Deprecated GPUProgram, VertexProgram, and PixelProgram (the OpenGL 1.5 shaders - follow a different paradigm than the OpenGL 1.3 ones, so the G3D API must change - to match it). -
  • Support for GL_ARB_vertex_shader, GL_ARB_fragment_shader, and GL_ARB_shader_objects -
  • G3D::drawFeatureEdges -
  • const Array& G3D::MD2Model::PosedModel::objectSpaceFaceNormals(); -
  • G3D::RenderDevice::sendSequentialIndices -
  • Network_Demo -
  • contrib/Win32Window -
  • contrib/pingtest -
  • contrib/GlutWindow [Morgan and Dan Keefe] -
  • contrib/ObjModel [Corey Taylor] -
  • G3D::GLCaps -
  • GAppSettings::logFilename -
  • Deprecated RenderDevice::suportsOpenGLExtension, RenderDevice::supportsImageFormat, - other supports shortcuts (use GLCaps instead). -
  • DiscoveryClient::cleanup -
  • Optimized BinaryInput::readUInt32, readUInt16 -
  • Extended network documentation -
  • 'fastlib' build target for G3D library developers -
  • glGetVector2, glGetVector3, glGetVector4 -
  • float * Quat (double * Quat already existed) -
  • GApp automatically generates g3d-license.txt at runtime ([RFE#856338] CREDIT.TXT) -
  • G3D::license -
  • Removed several large files (tag, ppt, exe) from the source zipfile, bringing it down to 3 MB -
  • Improved CoordinateFrame:pointToObjectSpace() (RFE#715996) [Giulio] -
  • [RFE#945935] Make static constants into functions [Giulio] -
  • Fix: LightweightConduit::send verifies that the packet size is smaller than the UDP limit -
  • Fix: Multitexture on ATI and Wildcat cards -
  • Fix: Incorrect occlusion in GLG3D_Demo (was caused by global constant problem) -
  • Fix: [BUG#949377] Checks for stencil extensions [Giulio] -
  • Fix: [BUG#922725] Non-multitexture implementation for getTextureState() [Giulio] -
  • Fix: Restore ambient light color after RenderDevice::popState -
  • Fix: RenderDevice now initializes OpenGL extensions before testing for multitexture [Erik Cassel, Dan Keefe] -
  • Fix: Bottom clipping plane of GCamera frustum now correct (was slanted incorrectly, making frustum too big) -
  • Fix: GFont::draw2D now returns correct y value (used to be too small) -
  • Fix: NetworkDevice now returns useful hostname on Linux (used to be "localhost") -
  • Fix: The conduit returned from NetworkDevice::createReliableConduit now has ok() == false when connect fails -
  • Fix: Tangent space computation of constant u, v now correct (was missing a factor of 2, leading to slight errors) [Max McGuire] -
  • Fix: [ 925456 ] select broken on Linux (Networking was broken on Linux) -
  • Fix: getDepthBufferValue off by 1 [Andi Fein] -
- -
-

- Changes in 6.02: -

    -
  • Default constructor for Line. -
  • Various patches to make G3D work with the CAVE [Dan Keefe] -
  • AABox::set -
  • Made OSWindow::setPosition non-const -
  • VARArea now tests for the presence of all VBO extensions, on the freak chance that - a driver has only partial support (due to a bug) -
  • Linux build statically links OpenGL 1.2.1 and loads extensions through OpenGL 1.5 - to work around Wildcat Linux driver bug (Windows and Mac statically link OpenGL 1.1 - and load extensions through OpenGL 1.5) -
  • Triangle stores precomputed edge lengths -
  • Ray-triangle with vertex weights -
  • Highly optimized ray-triangle intersection test [Tomas Moller & Ben Trumbore] -
  • Create a texture from 6 different cube-map filenames -
  • Added contrib directory built as part of the 'doc' target -
  • contrib/CoreyGWindow: OSWindow implementations for various platforms -
  • AABSPSet::beginRayIntersection [Pete Hopkins] -
  • AABSPTree::beginBoxIntersection -
  • CollisionDetection::intersectionTimeForMovingPointFixedAABox, Ray::intersectionTime(AABox) - [Pierre Terdiman and Andrew Woo] -
  • Triangle::center -
  • Renamed KDTreeSet to AABSPTree, old name is #defined -
  • RenderDevice now works on cards without multitexture -
  • void glTexCoord(const G3D::Vector4& t); [Dan Keefe] -
  • Overloaded float, double, and int * Matrix3 -
  • Fix: [ 923944 ] Matrix/Quat ambiguity -
  • Fix: fuzzyEq(inf, inf) is true -
  • Fix: Triangle::randomPoint returns values outside the triangle -
  • Fix: [ 913763 ] tokenTypeToString(Token::END) -
  • Fix: Compute number of texture coordinates before RenderDevice::setVideoMode [Dan Keefe] -
  • Changed the default depth bits to '0' for wider compatibility - (Fix: Unable to create OpenGL screen: Couldn't find matching GLX visual) -
  • Fix: [912305] Table, Queue, and Set assignment operators do not free old values -
  • Fix: Separate specular and Multisample on Tablet PC w/ Trident [Dan Keefe] -
  • Fix: Linux debug build now has line numbers -
  • Upgraded to SDL 1.2.7 - Fix: [ 838030 ] SDL 1.2.6 blocks prompt - Fix: FSAA does not work under SDL - Fix: Default Win32 refresh rate -
  • Draw::vertexVectors -
  • New meshes from Brown University: hemisphere.ifs, curvy.ifs, head.ifs, - closed-low-poly-teapot.ifs, bump.ifs -
  • GLight::specular -
  • SDLWindow::setWindowDimensions and setWindowPosition now work on Win32 -
  • GWindowSettings::x, GWindowSettings::y, GWindowSettings::center -
  • System::setEnv -
  • [ 909999 ] OSWindow Joystick interface -
  • double * Quat ([ 909305 ] scalar * {quat, vector, matrix}) -
  • Increased the precision of several Vector2 and Vector3 methods -
  • MeshAlg::computeNormals now returns 0 instead of NaN for degenerate normals -
  • Updated main-no-GApp.cpp for 6.02 -
  • RenderDevice::screenshotPic can copy from the back buffer -
  • Improved VAR documentation. -
  • If NO_SDL_MAIN is defined, G3D does not attempt to link against sdlmain.lib -
  • UserInput::setPureDeltaMouse -
  • UserInput::mouseXY, mouseX, mouseY -
  • UserInput::mouseDXY -
  • Deprecated UserInput keyMapping constructor argument -
  • RenderDevice::setDrawBuffer [Dan Keefe] -
  • GFont::draw3D [Dan Keefe] -
  • GImage::pixel3(x, y) and GImage::pixel4(x, y) -
  • debugAssert, debugBreak, debugAssertM, etc. all release input grab - when an assertion fails (Win32 and Linux) and restore it when the - program continues (Win32). This also fixes the DirectInput laggy - cursor that occurs after a break. -
- -
-

- Changes in 6.01: -

    -
  • Default constructor for G3D::LineSegment -
  • Rect2D::clipPoly (Pete & Morgan) -
  • Draw::poly2D, Draw::poly2DOutline (Pete & Morgan) -
  • Added instructions for rotated text to G3D::GFont::draw2D -
  • Fix: iRandom now compiles correctly under gcc. -
  • Fix: [ 852076 ] Compute better/faster vertex normals in MeshAlg - MeshAlg::computeNormals now weighs adjacent faces by their area -
  • Fix: [ 896028 ] Textures broken on Trident TabletPC (Dan Keefe) -
  • Fix: [ 860800 ] ManualCameraController cursor jumps -
  • Fix: G3D::UserInput no longer offsets the mouse position by 1/2 pixel -
  • Fix: Alt-Tab no longer toggles the GApp camera before switching windows -
  • Fix: [ 901248 ] Font bounds y-value incorrect -
  • Fix: G3D::PhysicsFrame::toCoordinateFrame() was rotated by 90 degrees -
  • Fix: [ 895493 ] Radeon 7500 Cube Map -
  • Fix: G3D::MeshAlg::computeWeld produces linker errors on Linux -
  • G3D::TextInput::peekLineNumber(), G3D::TextInput::peekCharacterNumber() -
  • G3D::GAppSettings::dataDir -
  • html/gettingstarted.html -
  • G3D::MeshAlg::debugCheckConsistency -
  • G3D::MD2Model and G3D::IFSModel now weld their adjacency information -
  • Renamed/retyped G3D::PosedModel::adjacentFaces to G3D::PosedModel::vertices - (most programs can be fixed by changing the type from Array< Array > to - Array and adjacentVertexArray[v] to vertexArray[v].faceIndex) -
  • Shadow volumes now use the welded adjacency information -
  • G3D::PosedModel now offers both welded and non-welded adjacency information -
  • G3D::contains for C-Arrays -
  • Generate .tag files in the build -
  • G3D::MeshAlg::computeAdjacency does not merge colocated vertices -
  • G3D::MeshAlg::computeAdjacency does not remove degenerate faces and edges -
  • G3D::MeshAlg::Vertex -
  • G3D::Vector3::directionOrZero -
  • G3D::GMaterial -
  • ManualCameraController renamed to G3D::FPCameraController -
  • glGetCurrentContext (beta) -
  • G3D::RenderDevice::supportsImageFormat -
  • G3D::Vector3::magnitude -
  • G3D::Vector3::cross() [returns Matrix3] -
  • G3D::Quat changes (API is still in beta) -
  • G3D::Quat::norm now returns the 2-norm, not the function Dave Eberly uses. -
  • Matrix3 default constructor -
  • Switched UserInput to use SDLWindow internally -
  • Switched RenderDevice to use SDLWindow internally -
  • G3D::Window -
  • G3D::SDLWindow -
  • Renamed G3D::RenderDeviceSettings to G3D::WindowSettings (with a typedef for the old name) -
  • IFSModel now loads models with up to 10 million polygons (like the buddha). -
  • Internal G3D::KDTreeSet state now private. -
- -
-

- Changes in 6.00: -

    -
  • FIX: warning: passing `double' for argument 1 of `void G3D::Queue::repackAndRealloc(int)' -
  • Optimized static Matrix3::transpose (36 cycle) and - Matrix3::mul (52 cycle) variations. -
  • Changed some lerp arguments from float to double -
  • MeshAlg::computeTangentSpaceBasis -
  • Draw::axes now uses scale to compute axis length -
  • New ParallaxBump demo -
  • Changed several Vector3 return values from float to double -
  • Real-world stars, sun, and moon path (Nick Musurca) -
  • Now compiles under MSVC++ 7.0 (David Baszucki) -
  • Now compiles under g++ OS/X (Ben Landon) -
  • Changed the default RenderDeviceSettings::alphaBits to 0 in the hope that it - will work with more graphics cards. -
  • Matrix3::fromX methods became factory methods -
  • G3D::sinc -
  • Multi-platform lib directories -
  • Vector3::average(), Color3::average(), Vector3::sum(), Color3::sum() -
  • Ray::reflect, Ray::refract -
  • Physically correct sky model -
  • FIX: Older graphics cards can now initialize properly -
  • Increased fuzzyEpsilon to 0.000001 -
  • Color3::max, Color3::min, Color4::max, Color4::min -
  • Array::sortSubArray -
  • GCamera::getClipPlanes now takes a G3D::Array -
  • G3D::AABox -
  • Box::randomInteriorPoint, Box::randomSurfacePoint -
  • Vector3::cosRandom, Vector3::hemiRandom, Vector3::reflectAbout, Vector3::reflectionDirection, Vector3::refractionDirection -
  • log(Color3) -
  • Upgraded to zlib 1.2.1 -
  • VAR::valid (Peter) -
  • System::getLocalTime, System::getTicks -
  • High-performance cycle count and time queries on Linux -
  • UserInput::anyKeyPressed -
  • G3D::Box now provides axes, center, and extent information - (serialization is backwards compatible to 5.xx) -
  • TextInput's exceptions now provide file, line, and character numbers - as well as preformatted error messages in the style of MSVC++. -
  • G3D::Texture::fromGImage -
  • G3D::TextInput now parses hex numbers of the form 0x##### -
  • G3D::CollisionDetection::penetrationDepthForFixedSphereFixedPlane -
  • G3D::CollisionDetection::penetrationDepthForFixedSphereFixedBox -
  • G3D::beginMarkShadows, G3D::endMarkShadows, G3D::markShadows -
  • GFont::draw2D now returns the string bounds -
  • Sphere::surfaceArea, Sphere::volume, Box::surfaceArea, Box::volume -
  • Two-sided stencil operations -
  • Removed G3D::Real -
  • FIX: [ 855947 ] Fonts are broken on Radeon -
  • Switched vertex arrays to use the new ARB_vertex_buffer_object extension. - Compared to 5.xx rendering speed: NVIDIA/Win32 is the same (fast), - ATI and Linux rendering are about 10x faster. The API has changed - slightly-- most significant, the vertex, normal, color, etc. arrays - must all come from the same VARArea now. -
  • Disabled the "conditional is constant" level 4 warning on Windows - that is triggered by the for-loop scoping fix. -
  • G3D::SkyParameters::directionalLight -
  • G3D::TextureManager (Peter S. & Morgan) -
  • Flipped skybox X-axis to match OpenGL cube map coordinates -
  • Texture now uses hardware MIP-map generation -
  • Texture::copyFromScreen for cube map faces -
  • RenderDevice::configureReflectionMap -
  • RenderDevice::configureShadowMap -
  • Renamed CFont to GFont -
  • Renamed CImage to GImage -
  • G3D::Matrix3::getRow -
  • Added optional argument drawCelestialBodies to Sky::create. -
  • RenderDevice::getTextureMatrix -
  • Depth Textures -
  • Texture::createEmpty -
  • RenderDevice::setViewport has flipped the y-axis since version 5.00 -
  • ReferenceCountedPointer::isLastReference -
  • Support for textures beyond the number of texture units (which occurs on NVIDIA cards) -
  • G3D::PosedModel -
  • G3D::IFSModel -
  • G3D::CoordinateFrame::normalToObjectSpace, G3D::CoordinateFrame::normalToWorldSpace -
  • Simplified arguments on Texture::copyFromScreen -
  • Moved Camera in GLG3D to GCamera in G3D -
  • Moved setProjectionAndCameraMatrix from Camera to RenderDevice -
  • Moved G3D::Rect2D to G3D from GLG3D, changed interface -
  • G3D::setRenderMode -
  • G3D::RenderDevice::setSpecularCoefficient, G3D::RenderDevice::setShininess -
  • G3D::GLight -
  • Renamed G3D::RenderDevice::configureDirectionalLight, configurePointLight to G3D::RenderDevice::setLight -
  • Changed G3D::Rect2D to use doubles -
  • G3D::Camera::setPosition() -
  • G3D::Camera::lookAt() -
  • G3D::ManualCameraController::setPosition() -
  • G3D::System::getTick, G3D::System::getLocalTime -
  • Fixed [ 839618 ] peak var only updated on reset() -
  • G3D::Array::findIndex (thanks to David Baszucki for the suggestion) -
  • Removed RenderDevice::setProjectionMatrix3D and RenderDevice::setProjectionMatrix2D -
  • RenderDevice::project -
  • RenderDevice::push2D() now uses the current viewport instead of full screen by default -
  • RenderDevice::getViewport -
  • G3D::SimTime -
  • Sky::render no longer needs a camera matrix (it gets it from the render device) -
  • SkyRef, Sky::create() -
  • Removed Sky::getName -
  • Removed RenderDevice::setAmbientLightLevel (duplicated RenderDevice::setAmbientLightColor) -
  • G3D::GApp, G3D::GApplet, G3D::GAppSettings -
  • RenderDevice::getCardDescription -
  • GPUProgram interface for setting program constants [Peter, Morgan & Dan] -
  • RenderDevice::getModelViewMatrix -
  • RenderDevice::getModelViewProjectionMatrix -
  • RenderDevice::getProjectionMatrix -
  • Documented some more common compiler errors. -
  • Moved RenderDevice::debugDraw methods to the Draw class, changed rendering from - cylinders to lines for wireframe (for performance) -
  • Ray::direction no longer has unit length -
  • Line::point, Line::direction -
  • LineSegment::endPoint -
  • IFSBuilder loads Brown University Sketch Model (sm) format -
  • New IFS models: angel, distributor-cap, dragon2, duck, elephant, hippo, hub, mech-part, rotor, sandal, trumpet, venus-torso, woman -
  • RenderDevices are now optionally resizable -
  • MeshAlg::computeWeld -
  • Array::randomize -
  • Table now refuses to push the load factor above 19/20 and stops rehashing -
  • Table always keeps an odd number of buckets -
  • Sphere::randomInteriorPoint, Sphere::randomSurfacePoint -
  • LineSegment::randomPoint -
  • Hardcoded some common paths into demoFindData -
  • Deprecated old RenderDevice::init method. -
  • Full screen anti-aliasing (FSAA) -
  • G3D::RenderDeviceSettings -
  • All 2, 3, and 4 character swizzles for Vector2, Vector3, Vector4 are defined. -
  • G3D::rsqrt -
  • Most vector methods are also defined as functions now -
  • sign(Vector2), sign(Vector3), sign(Vector4) -
  • G3D::Matrix4 -
  • Changed G3D_VER from double to integer -
  • G3D::lerp -
  • Changed G3D::PI, G3D::HALF_PI, and G3D::TWO_PI to #defines -
  • Vector2::clamp, Vector3::clamp, Vector4::clamp -
  • Changed order of arguments to all lerp methods to match DirectX/Cg -
  • Changed order of arguments to G3D::clamp and G3D::iClamp to match DirectX/Cg -
  • G3D::ManualCameraController::ManualCameraController now requires a G3D::UserInput -
  • G3D::UserInput::appHasFocus -
  • G3D::ManualCameraController now stops tracking the mouse when the app loses focus -
  • G3D::ManualCameraController::setActive -
  • G3D::ManualCameraController now manages the mouse cursor instead of G3D::RenderDevice -
  • G3D::UserInput::getMouseXY, G3D::UserInput::getXY -
  • RenderDevice::debugDrawVertexNormals -
  • GPUProgram, VertexProgram, and PixelProgram now recognize the output of the - Cg compiler and automatically bind constants. -
  • RenderDevice now loads glActiveStencilFaceEXT -
  • RenderDevice::numTextureCoords -
  • Moved changelog to a separate page -
  • Reformatted overview to be smaller -
  • Added model debugging info to the IFSBuilder display -
  • Welded some broken vertices in the teapot.ifs file -
  • Renamed Font.* to CFont.* -
  • CFont::draw2DString renamed to CFont::draw2D (use a #define to port old code) -
  • MeshAlg -
  • RenderDevice now enables GL_COLOR_MATERIAL by default -
  • msgBox -
  • MD2 model gallery in documentation (Kevin) -
  • MD2Documentor (Kevin) -
  • debugAssertGLOk macro -
  • VertexProgram now supports NVIDIA Vertex Program 2.0 -
  • RenderDevice now loads glGenProgramsNV, glDeleteProgramsNV, glBindProgramNV, glLoadProgramNV, glTrackMatrixNV, glProgramParameter4fvNV, glGetProgramParameterfvNV, glGetProgramParameterdvNV extensions -
  • VertexProgram and PixelProgram static factory methods now return reference counted values. -
  • Split the reference value from RenderDevice::setStencilTest into setStencilConstant -
  • RenderDevice::STENCIL_INVERT, RenderDevice::STENCIL_REPLACE, RenderDevice::STENCIL_ZERO -
  • Added brighten argument to Texture::fromFile -
  • Increased CImage JPEG save quality -
  • RenderDevice::screenshot now returns the name of the file that was written -
  • nextPowerOf2 renamed to ceilPow2 -
  • System::alignedMalloc, System::alignedFree -
  • Carbon, Crackman, Edenmill, Futurist, Interplanetary, - Iomanoid, Starlight, Lesser, and Wild fonts by Ray Larabie. - Like all of our fonts, they are free, but please consider a - donation to him if you like them. http://www.larabiefonts.com/ -
  • MD2Model_Demo -
  • G3D::MD2Model -
  • FIX: Fixed a bug in Array shrinking that could cause memory corruption -
  • FIX: RenderDevice windows with an aspect ratio of less than 1 now allowed. -
  • FIX: TextInput now parses '#', '~', '~=', '&', '&&', '|', '||' correctly -
  • VARArea::reset() now waits for rendering calls using its vertex - arrays to complete before wiping the memory. -
  • G3D::filenameBaseExt, G3D::filenameExt -
  • VARArea::finish() -
  • Milestone -
  • TextInput::Options::signedNumbers -
  • RenderDevice now loads glFlushVertexArrayRangeNV -
  • Vector2int16 -
  • RenderDevice::freeVARSize() -
  • Array now allocates 16-byte aligned pointers. -
  • Decreased the default camera movement rate by 50% for better resolution. -
  • RenderDevice enables GL_NORMALIZE by default -
  • Improved the performance of Array::append/Array::push/Array::next -
  • Fix: [ 875219 ] Array::sort must use std::sort -
  • Array::next -
  • Array::reverse -
  • PCX file loading -
  • Test images -
  • Color3uint8 as uint8[] addressing -
  • Color4uint8 as uint8[] addressing -
  • Removed const from VAR::pointer -
  • ReferenceCountedPointer::isNull -
  • alwaysAssertM -
  • Log::common, Log::getCommonLogFilename -
  • Switched from static to dynamic linking of zlib -
  • Upgraded to zlib 1.1.3 -
  • On Win32 the lib list is automatically updated through pragmas - (5.xx programs should revert to linking against default libraries) -
  • Increased default sky quality to 1.00 -
  • G3D::CFontRef -
  • RenderDevice now loads all register combiner extensions (NVIDIA only) -
  • Sky::getEnvironmentMap -
  • Sky implementation now uses a cube map (when one is available) -
  • G3D::Sky constructor now takes a render device -
  • Rotated Sky box 90 degrees to match environment maps -
  • G3D::Sky now takes the environment filenames as "sky_*.jpg" instead of "sky_ft.jpg" -
  • Added default filename for Sky constructor -
  • Added caustics textures created with Kjell Andersson's generator http://www.lysator.liu.se/~kand/caustics/ -
  • #defined "for" under MSVC so that it obeys C99 scoping rules -
  • System::consoleKeyPressed -
  • System::consoleClearScreen -
  • System::consoleReadKey -
  • NetMessage::type() -
  • Changed the Conduit message protocol to include a message type. - The API is backwards compatible to 5.01 even though the protocol is not. -
  • Removed optional argument maxSize from LightweightConduit::receive. -
  • NetAddress::serialize -
  • NetAddress::deserialize -
  • NetAddress == NetAddress -
  • hashCode(NetAddress) -
  • RenderDevice::init now prints ATI or NVIDIA driver version to the log under Windows -
  • readme.html library build instructions now have downloads for required libraries -
  • Library list has changed for Win32 (added version.lib) -
  • System::cpuArchitecture -
  • System::operatingSystem -
  • double-precision Plane::getEquation -
  • Vector2::lerp -
  • Platform specific #defines G3D_WIN32, G3D_LINUX, G3D_OSX -
  • G3D::Array::contains -
  • G3D::Queue::contains -
  • G3D::ImageFormat -
  • G3D::Texture::DIM_CUBE_MAP -
  • G3D::Texture resizes non-power of two textures -
  • G3D::Texture constructors are completely changed from 5.01 (and hopefully easier to use) -
  • G3D::CImage now supports images with alpha -
  • Removed most of the width/height arguments from G3D::Camera methods -
  • BinaryInput::readBytes and BinaryOutput::writeBytes now take void* as an argument to avoid casting -
  • Plane::fromEquation -
  • Removed Plane::getNormal (use Plane::normal instead) -
  • Removed CDTriangle (use G3D::Triangle instead) -
  • Removed Font (use G3D::CFont instead) -
  • FIX: Camera::getClipPlanes now transforms infinite planes correctly. -
  • FIX: The last reference of an RGC pointer assigned to itself no - longer tries to collect before re-assigning -
- -
-

- Changes in 5.01 -

    -
  • G3D::tesselateComplexPolygon -
  • G3D::ConvexPolygon -
  • G3D::ConvexPolyhedron -
  • G3D::iClamp, G3D::clamp -
  • G3D::iWrap -
  • G3D::iRandom, G3D::random -
  • G3D::getFiles -
  • G3D::getDirs -
  • G3D::VAR::pointer -
  • G3D::realWorldLocalTime -
  • G3D::Texture::TRANSPARENT_BORDER -
  • DECLARE_GLFORMATOF -
  • G3D::System::machineEndian -
  • G3D::VertexProgram, G3D::VertexProgramRef, G3D::RenderDevice::setVertexProgram -
  • G3D::PixelProgram, G3D::PixelProgramRef, G3D::RenderDevice::setPixelProgram -
  • G3D::GPUProgram, G3D::GPUProgramRef -
  • G3D::sizeOfGLFormat -
  • G3D::RenderDevice::setVertexAttrib -
  • G3D::Vector2*=Vector2, /= Vector2, * Vector2, / Vector2 -
  • glFormatOf -
  • G3D::Color4uint8 -
  • G3D::Color3uint8 -
  • G3D::Vector3int16 -
  • G3D::System::currentProgramFilename -
  • CImage::insertRedAsAlpha -
  • CImage::stripAlpha -
  • Texture::hasAlpha -
  • Added support for TGA with alpha channel -
  • Re-implemented Texture to support a broader range of formats and cleaner implementation. -
  • Fix: Improved Texture::LUMINANCE support -
  • Added == and != overloads for Texture::Ref so that "a != NULL" is now legal and does not require a cast to Texture::Ref. -
  • G3D::CFont is a typedef for G3D::Font to avoid name conflicts with X11 Font under Linux. In future releases, the name Font will be deprecated. -
  • RenderDevice::setPointSize -
  • Added a new teapot (teapot.ifs) that is closed, with a properly fitting top. The classic teapot is now called "utah-teapot.ifs" (Sebastian Schuberth and Simon Winkelbach) -
  • RenderDevice::init now loads glPointParameterfvARB, glPointParameterfARB, - glMultiDrawArraysEXT, and glMultiDrawElementsEXT functions. -
  • GLenumToString(4) now returns "GL_TRIANGLES" instead of "GL_LINE_BIT" (both are correct) -
  • Added TextInput::Options to optionally allow C++ comments to - be treated as two slashes instead of a comment -
  • Added data/image/meter.jpg, a meter stick texture convenient for testing -
  • Added sansserif, news, and terminal fonts based on Bitstream's free fonts -
  • RenderDevice::numTextureUnits -
  • Added stars to night Sky -
  • Added classic GL dinosaur model as data/ifs/dinosaur.ifs -
  • Documented G3D::glGetProcAddress -
  • Fix: Texture now restored GL_ENABLE bits properly after creation -
  • Fix: Texture::sizeInMemory now accounts for MIP-map levels -
  • Fix: Fonts and skies now adjust their brightness for the screen gamma level -
  • Fix: Strange compilation bug was causing Sky to be black for some programs -
  • resolveFilename -
  • GLProgram_Demo to show how to use vertex programs in G3D -
  • Support for GL_ARB_vertex_program -
  • Modified ManualCameraController so that diagonal movement does not exceed - maximum rate. -
  • Added support for non-GL_FLOAT vertex arrays to RenderDevice -
  • Added support for Wavefront OBJ files to IFSBuilder -
  • Removed duplicate copies of SDL.dll from the source tree -
  • Renamed G3D::CDTriangle to G3D::Triangle -
  • Added several G3D::Triangle methods -
  • Moved CollisionDetection::primaryAxis to Vector3::primaryAxis -
  • Fix: Texture::sizeInMemory now returns correct results for RGB8 textures. -
  • Changed texture constructors in ways that slightly break backwards compatibility -
  • Deprecated several arguments to the texture constructors. -
- -
- Changes in 5.00 -
    -
  • Color3::operator*=(const Color3&) -
  • Color3::operator*(const Color3&) -
  • Eliminated duplicate GL headers [James O'Sullivan] -
  • Linux Makefiles [James O'Sullivan, Jordan Parker] -
  • RenderDevice::getProjectionMatrixParams -
  • RenderDevice::debugDrawCylinder -
  • Added an option to not copy input memory for BinaryInput -
  • Added data/ifs/sphere.ifs -
  • Added data/ifs/spikeball.ifs -
  • Added a new (imperfect) demo/tool that converts 3DS and MD2 to IFS. -
  • Added RenderDevice to the Font constructor -
  • Removed RenderDevice from Font::drawString -
  • Included glut32.lib, .dll, and .h (Version 3.7.6) in the distribution. - The windows glut port is by Nate Robbins and is from - http://www.xmission.com/~nate/glut.html. - glut was originally written by Mark Kilgard. -
  • Modified OpenGL headers to work cross platform, with the latest NVIDIA extensions -
  • Changed library name from graphics3D.lib to G3D.lib, same for - debug version. -
  • Changed directory structure and added readme.html to explain - the new setup. -
  • Changed BinaryInput::readBytes to allow reading onto the stack -
  • Added Vector4::isFinite -
  • G3D::CDTriangle (for 35% faster collision detection) -
  • CollisionDetection::closestPointToRectangle -
  • CollisionDetection::movingSpherePassesThroughFixedBox -
  • CollisionDetection::movingSpherePassesThroughFixedSphere -
  • Changed CollisionDetection::movingXFixedTriangle arguments -
  • CollisionDetection::collisionTimeForMovingSphereFixedSphere -
  • Changed CollisionDetection::distanceToX methods to closestPointToX -
  • Vector3::NAN3 -
  • Made Vector3::isUnit fuzzy -
  • Made Vector3::isZero fuzzy -
  • Fix: Texture(std::string, std::string) constructor now works for alpha-only textures. -
  • FIX: Array now calls copy constructor when resizing -
  • FIX: Triangle-sphere and rectangle-sphere collision detection - returned an incorrect collision location; now fixed. -
  • FIX: changed VectorX::isFinite to call isFinite (used to give bad result for NaNs) -
  • FIX: Used the normalized edge to compute intersection in - CollisionDetection::distanceToTrianglePerimeter -
  • FIX: Changed the order of corners returned from Box::getFaceCorners so the - face is ccw, facing out -
  • FIX: ManualCameraController::lookAt now faces along the -z axis. -
  • FIX: data/ifs/icosa.ifs model is now an icosahedron -
  • Made Set::begin() and Set::end() const -
  • Added ifdef _WIN32 all over for typedefing types from Windows to Linux and vice versa. -
  • G3D::isNaN, G3D::isFinite -
  • Added a single triangle triangle.ifs file -
  • G3D::LineSegment -
  • RenderDevice::debugDrawRay -
  • CoordinateFrame::toObjectSpace(Ray&) -
  • CoordinateFrame::toObjectSpace(Box&) -
  • CoordinateFrame::toObjectSpace(Sphere&) -
  • Changed CollisionDetection routines to return the surface normal of the - surface at the collision location. -
  • CollisionDetection::collisionTimeForMovingPointFixedCapsule -
  • CollisionDetection::collisionTimeForMovingSphereFixedCapsule -
  • G3D::Capsule class -
  • Removed e-mail addresses from contributor list to protect them from spammers -
  • Linux port [Hari Khalsa & Chris Kern] -
  • Added serialize and deserialize methods, deserializing constructor to - Vector2, Vector3, Vector4, Color3, Color4, Matrix3, CoordinateFrame, Box, - Sphere, Plane, Ray, Line, Capsule, LineSegment -
  • Moved parts of Plane.h into Plane.cpp -
  • BinaryInput::readBool8 and BinaryOutput::writeBool8 -
  • G3D::System [based on Michael Herf, Rob Wyatt, and Benjamin - Jurke's work] -
  • Networking infrastructure: G3D::NetworkDevice, G3D::NetAddress, - G3D::ReliableConduit, G3D::LightweightConduit, G3D::NetListener -
  • G3D::Camera -
  • Vector2::toString -
  • G3D::createTempFile -
  • G3D::fileLength -
  • UserInput::setKeyMapping -
  • UserInput::keyCodeToString, UserInput::stringToKeyCode -
  • JPEG library uses createTempFile -
  • JPEG library will allocate up to 6MB before resorting to temp - files-- faster and more reliable -
  • Moved SDL initialization to RenderDevice constructor from the init - method so extension can be used earlier -
  • Support for up to 8 texture units, no longer crashes on machines - that have more than 4 units -
  • Made Arrays allocate at least 32 bytes when resized to improve - performance of small char stacks -
  • Added UserInput key codes for mouse wheel buttons -
  • UserInput::keyPressed, UserInput::pressedKeys() -
  • UserInput::GKey -
  • Renamed UserInput::poll() to UserInput::endEvents(), added - UserInput::beginEvents() -
  • Moved custom UserInput key codes into an enum so they are - compile-time constants -
  • Changed all to for cross-platform [Rob & Chris] -
  • Moved LITTLE_ENDIAN and BIG_ENDIAN constants to an enum and renamed - them to G3D_LITTLE_ENDIAN and G3D_BIG_ENDIAN for cross-platform - [Rob & Chris] -
  • Permanently fixed the precision of Real to be 32-bit float. -
  • RenderDevice now loads the NVIDIA VAR fence extensions. -
  • Renamed RenderDevice::begin to RenderDevice::beginPrimitive, same - for end. -
  • Redesigned the vertex array system; see VAR and VARArea. -
  • Changed GLG3D demo to demonstrate the use of the new VAR and - VARArea classes -
  • CoordinateFrame(Vector3) constructor. -
  • Improved the performance of zero-radius sphere [aka point] - collision detection -
- -
-

- Changes in 4.01 -

    -
  • trimWhitespace() -
  • Pointwise multiplication and division for Vector3 -
  • Array::sort now uses > operator by default; two alternative sort methods allow qsort style sorting -
  • Texture::copyFromScreen -
  • Texture::invertY -
  • BinaryInput/BinaryOutput compression (via zlib) -
  • Alpha-only G3D::Texture mode -
  • G3D::Font and fonts in data/font -
  • Array::fastRemove -
  • TextInput [Morgan & Aaron] -
  • Color4::CLEAR -
  • Table [] operator now returns a non-const reference -
  • RenderDevice::getFrameRate, RenderDevice::getTriangleRate, RenderDevice::getTriangleCount -
  • ManualCameraController::setMoveRate, ManualCameraController::setTurnRate -
  • SkyParameters default constructor -
  • Vector2, Vector3, Vector4 isZero(), isUnit(), isFinite() -
  • Vector4::length(), Vector4::squaredLength() -
  • isValidPointer now returns false for 0xFEEEFEEE -
  • RenderDevice checks for texture compression extensions -
  • Restructured the directories for the CPP sources (only affects people who build G3D) -
  • Included NVIDIA and SGI OpenGL headers in the distribution, changed install notes -
  • Fixed a bug that previously prevented textures from being garbage collected -
  • Fixed Line::distance returning values too small -
  • Fixed Plane(normal, point) constructor to compute point from normalized direction [Kevin] -
  • LED font by Matthew Welch daffy-duck@worldnet.att.net -
  • VenusRising font by Ray Larabie drowsy@cheerful.com -
  • VideoFreak font by Jakob Fischer pizzadude@pizzadude.dk -
- -
-

- Changes in 4.00 -

    -
  • Moved texture combine modes from Textures onto RenderDevice texture units -
  • Documented RenderDevice::getHDC() (Windows only) -
  • Renamed RenderDevice::swapBuffers() to RenderDevice::endFrame(), added corresponding RenderDevice::beginFrame() -
  • Moved getNumJoySticks from RenderDevice to UserInput -
  • Added TEX_ADD combine mode -
  • Table::getKeys and Set::getMembers now have overloads that take an Array as input. -
  • BinaryOutput::getCArray -
  • RenderDevice::getObjectToWorldMatrix(), RenderDevice::getCameraToWorldMatrix() -
  • RenderDevice::debugDrawAxes(), RenderDevice::debugDrawBox(), RenderDevice::debugDrawSphere() -
  • Color3::Color3(const Vector3&) and Color4::Color4(const Vector4&) -
  • Moved hashCode(const Vector3&) and hashCode(const Vector4&) to the global namespace [Kevin] -
  • isValidPointer now returns false for 0xCCCCCCCC and 0xDEADBEEF -
  • Fix: RenderDevice::setPolygonOffset now affects polygons rendered in line and point mode -
  • Fix: Sun is now invisible after it goes below the horizon -
  • Fix: BinaryInput now supports endian-ness correctly in memory read mode -
  • Fix: Table.copyFrom and copy constructor now work -
- -
-

- Changes in 3.02 -

    -
  • Built libraries using "Multithreaded DLL" [Kevin & Darius] -
  • Added depth, color, and stencil bit depth preferences to G3D::RenderDevice -
  • G3D::Sky (plus sky directory in the data distribution) -
  • Sky cube data [Jauhn Dabz, jauhn@yahoo.com, http://nullpoint.fragland.net] -
  • G3D::UserInput -
  • G3D::ManualCameraController -
  • G3D::SkyParameters -
  • G3D::toSeconds, G3D::AMPM, G3D::GameTime, G3D::RealTime -
  • G3D::RenderDevice::project -
  • G3D::linearSpline -
  • G3D::Color3::fromARGB and G3D::Color4::fromARGB -
  • Added non-const G3D::Array::last() [Kevin] -
  • Modified G3D::RenderDevice::configureDirectionalLight to operate in world space -
  • Fix: Flipped the y-axis of G3D::RenderDevice::getDepthBufferValue so it matches the documentation. -
  • Removed brief descriptions from documentation -
  • Removed sqrt, sin, cos, etc. that conflict with standard library names -
  • Removed TWO_PI constant -
  • Removed G3D::Matrix3 virtual destructor -
  • Removed G3D::Quat virtual destructor [Kevin] -
- -
- Changes in 3.01 -
    -
  • Changed an assert() to debugAssert() in Queue.h -
  • G3D::Table doesn't grow the number of buckets under bad hash codes [Morgan & Darius] -
  • G3D::Table allocates only 10 initial buckets -
  • G3D::Table::debugGetLoad() -
  • G3D::CollisionDetection::collisionTimeForMovingPointFixedRectangle -
  • G3D::CollisionDetection::collisionTimeForMovingPointFixedBox -
  • G3D::Ray::intersectionTime, G3D::Ray::unit() -
  • G3D::Log [Morgan & Aaron] -
  • G3D::RenderDevice (OpenGL state abstraction. VertexBuffer support is beta only) -
  • G3D::Texture (includes texture compression, image loading, and texture rectangle) -
  • Added a comment to the vector classes noting that they can't be sublcassed [Kevin Egan] -
-
- Changes in 3.00 -
    -
  • G3D::NEWLINE -
  • writeStringToFile -
  • Fixed empty stringJoin bug -
  • Fixed parseFilename with no path bug -
  • Vector3::INF3, Vector3::ZERO3 -
  • G3D::PhysicsFrame (beta-- this interface is going to change in 4.00) -
  • G3D::Vector4 -
  • G3D::Queue -
  • Default constructor for G3D::CImage -
  • G3D::isValidHeapPointer, G3D::isValidPointer -
  • G3D::Ray -
  • CImage copy constructor, CImage::load -
  • Removed \#pragma once for gcc compatibility -
  • Renamed several hashcode methods to hashCode -
  • Fixed fuzzy math to work with infinite numbers -
  • Fixed Table::remove(), Set::remove() bug [Darius Jazayeri] -
  • G3D::CoordinateFrame.toObjectSpace(Vector4), G3D::CoordinateFrame.toWorldSpace(Vector4) -
  • Added the data directory -
  • G3D::CollisionDetection -
  • G3D::Sphere::culledBy() -
  • Added the GLG3D library [Morgan McGuire & Seth Block] -
  • Changed SDL_GL_Demo to use GLG3D, rotate triangle, and use color blending -
  • Fixed debugPrintf to handle long strings on Win32 -
  • Wrapped the MMX headers with \#ifdefs [Nate Miller] -
  • Moved OpenGL code out of CoordinateFrame.h/cpp -
  • Fixed BinaryInput readVector*, readColor* to read in correct order [Nate Miller] -
  • BinaryInput::readVector4, BinaryInput::readColor4, BinaryOutput::writeVector4, BinaryOutput::writeColor4 -
  • IFS_Demo for loading IFS files, dealing with models in OpenGL [Nate Miller] -
- -
-

- Changes in 2.00 -

    -
  • Vector2 members renamed to x,y from s,t -
  • Added SDL_GL_Demo and Win32_Demo -
  • Removed Group -
- -
-

- Changes in 1.10 -

    -
  • CImage, color conversion routines [Morgan McGuire, John Chisholm, and Edward Resnick] -
  • Array dereference for BinaryInput -
  • BinaryInput from memory -
  • BinaryOutput to memory -
  • toUpper(std::string), toLower(std::string) -
  • Group::clear() -
  • inf, nan as global constants (double precision) -
  • Can iterate over const Tables -
  • Table::deleteValues() -
  • Fixed an off-by-one bug in BinaryInput::readString() -
  • beginsWith() and wordWrap() string utilities -
  • prompt dialogs have fixed width font [Kurt Miller] -
  • iMax(), iMin() -
  • Array::sort() -
  • stringCompare(), stringPtrCompare() -
  • readFileAsString() -
  • Fixed textPrompt() to wait for input -
  • BinaryInput.getFilename(), BinaryOutput.getFilename() -
  • ReferenceCount [Justin Miller] -
  • endsWith() -
  • stringSplit(), stringJoin() -
  • Renamed format.* to stringutils.* -
  • fileExists(), parseFilename(), createDirectory(), copyFile() -
  • highestBit() [Jukka Liimatta] -
  • flipRGBVertical() -
  • Changed all header guards to use G3D_ prefix -
  • ConvexPolyhedron -
  • Virtual destructors on almost all objects. -
  • RGBtoBGR() -
  • Color4 -
  • Array::pop(bool shrinkArray=true) -
  • Vector2::isFinite, Vector2::fuzzyEq, Vector::fuzzyNe -
-

- -


- Changes in 1.09 -
    -
  • Removed pointer hash [Aaron Orenstein] -
  • Changed some includes from quotes to pointy brackets [Aaron Orenstein] -
  • Sphere::toString() -
  • Plane::toString() -
  • Added a change log -
- - */ diff --git a/externals/g3dlite/doc-files/contributors.dox b/externals/g3dlite/doc-files/contributors.dox deleted file mode 100644 index 3cd946a0bf1..00000000000 --- a/externals/g3dlite/doc-files/contributors.dox +++ /dev/null @@ -1,85 +0,0 @@ -/** -@page contributors G3D Developer Credits - - Team Members -
7.01 Release Team -
Morgan McGuire [Williams College] - Project Manager -
Corey Taylor [EA] - Assistant Project Manager and Linux Lead -
Casey O'Donnell [RPI] - OS X Lead -
Dan Keefe [Brown University] - Developer -
Kyle Whitson [Williams College] - Developer -
Danny Yuxing Huang [Williams College] - Developer - - Previous Contributors and Cited Sources
This library - contains code and resources contributed by the following people, or - based open code and articles by them. Starred (*) developers are - previous members of the %G3D team. - -

David Baszucki -
Seth Block -
Nicholas Bray -
Nick Capens -
Erik Cassel -
John Chisholm* -
Jauhn Dabz -
Erik de Castro Lopo -
Rich Deeson* -
Chris Demetriou -
L. Peter Deutsch -
Dmitri* -
Dave Eberly -
Kevin Egan* -
Cass Everitt -
Dan Fast* -
Andi Fein -
Jakob Fischer -
Dan Keefe* -
Harishabd Khalsa -
Nicolai Haehnle -
Michael Herf -
Daniel Hilferty* -
Pete Hopkins -
Danny Yuxing Huang -
Peter Hunt -
Robert Hunter -
Ed Johnson -
Benjamin Jurke -
Chris Kern -
Independent JPEG Group -
Darius Jazayeri -
Ben Landon* -
Thomas G. Lane -
Ray Larabie -
Jukka Liimatta -
Giulio Mainardi -
Jeff Marsceill -
Max McGuire -
Morgan McGuire -
Justin Miller -
Kurt Miller -
Nate Miller -
Tomas Moller -
Eric Muller* -
Nick Musurca -
Akita Noek -
James O'Sullivan* -
Aaron Orenstein -
Jordan Parker -
Edward Resnick -
Alex Rice -
Jack Ritter -
Nate Robbins -
Joshua Schpok* -
Sebastian Schubert -
SGI -
Ben Shine* -
Peter Sibley* -
Gabe Taubman* -
Corey Taylor* -
Pierre Terdiman -
Ben Trumbore -
Matthew Welch -
Simon Winkelbach -
Laura Wollstadt -
Andrew Woo -*/ diff --git a/externals/g3dlite/doc-files/license.dox b/externals/g3dlite/doc-files/license.dox deleted file mode 100644 index b4302651fbf..00000000000 --- a/externals/g3dlite/doc-files/license.dox +++ /dev/null @@ -1,120 +0,0 @@ -/** @page license License - -\htmlonly -
- -Introduction - -Installation
-\endhtmlonly - -@section intent Intent of License - (This section is informal and not legally binding.) - -
This library is free code-- you can use it without charge and - it is minimally legally encumbered. Unlike some other free libraries, - we do not require you to release - your source code or make your own program open source. - -

I intend the license (below) to protect me and the other - contributors from liability and allow you to use the source however - you want. You can make your own closed or open-source programs, - sell them, give them away, whatever. - -

- You have an obligation to say "this software is based in part on - the work of the Independent JPEG Group" in your documentation or - application help if you use the G3D::GImage class because it is based on - the IJG library. The OpenGL headers and ZLib headers included may - be freely distributed provided their copyright notices remain - intact. - -

- For convenience, G3D::license is a function that returns the license - string you must put in your documentation. G3D::GApp will automatically - write a file (g3d-license.txt) to disk with the contents of this - license unless you tell it not to. - -

- Most of the data resources have either entered the public domain and have - been in several published papers or are data that I have explicitly - received permission to distribute with G3D. The G3D fonts are actually font - images, not TrueType font descriptions and may be freely - distributed. As a rule of thumb, you can freely use and distribute - anything you find in the data directory but may need permission to use - it in a commercial product. Check the various copyright.txt files - in the data directories for specific information. - -

- - You are required by the BSD license to acknowledge G3D in your - documentation. This can be as minimal as a note buried in the - fine print at the end of a manual or a text file accompanying - your program. I appreciate it if you acknowledged the library - more publicly but you aren't required to. - -

- - Likewise, you are encouraged but not required to submit patches to - improve the library for the benefit of all. E-mail me with bugs, - patches, and questions.

- - -Morgan McGuire - <matrix@graphics3d.com> - -


- - @section reallicense License - - G3D is licensed under the BSD license, - with portions controlled by the IJG license, - PNG Reference Library license and - GNU Lesser General Public License (LGPL). - - - -
This product uses software from the G3D project (http://g3d-cpp.sf.net) -
Copyright © 2000-2008, Morgan McGuire -
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 Morgan McGuire, Williams College, Brown University, nor the names of - its contributors may be used to endorse or promote products derived from - this software without specific prior written permission. -

- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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 must also agree to be bound by the terms of the Independent JPEG - Group license for the portions of this library that are based - on the work of the Independent JPEG Group, if you use those - portions. Note: if you do not use the G3D::GImage class, - this clause does not apply to you because the linker will - strip that code from your project. The IJG-README.TXT file contains the - Independent JPEG Group license. - - - - */ \ No newline at end of file diff --git a/externals/g3dlite/win/VC90/g3dlite.vcproj b/externals/g3dlite/win/VC90/g3dlite.vcproj deleted file mode 100644 index e76d610ab69..00000000000 --- a/externals/g3dlite/win/VC90/g3dlite.vcproj +++ /dev/null @@ -1,463 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/externals/g3dlite/win/g3dlite.sln b/externals/g3dlite/win/g3dlite.sln deleted file mode 100644 index 875374e3944..00000000000 --- a/externals/g3dlite/win/g3dlite.sln +++ /dev/null @@ -1,25 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "g3dlite", "VC90\g3dlite.vcproj", "{8072769E-CF10-48BF-B9E1-12752A5DAC6E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug|Win32.ActiveCfg = Debug|Win32 - {8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug|Win32.Build.0 = Debug|Win32 - {8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug|x64.ActiveCfg = Debug|x64 - {8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug|x64.Build.0 = Debug|x64 - {8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Release|Win32.ActiveCfg = Release|Win32 - {8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Release|Win32.Build.0 = Release|Win32 - {8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Release|x64.ActiveCfg = Release|x64 - {8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/externals/g3dlite/zip.lib/include/zip/ioapi.h b/externals/g3dlite/zip.lib/include/zip/ioapi.h deleted file mode 100644 index 7d457baab34..00000000000 --- a/externals/g3dlite/zip.lib/include/zip/ioapi.h +++ /dev/null @@ -1,75 +0,0 @@ -/* ioapi.h -- IO base function header for compress/uncompress .zip - files using zlib + zip or unzip API - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant -*/ - -#ifndef _ZLIBIOAPI_H -#define _ZLIBIOAPI_H - - -#define ZLIB_FILEFUNC_SEEK_CUR (1) -#define ZLIB_FILEFUNC_SEEK_END (2) -#define ZLIB_FILEFUNC_SEEK_SET (0) - -#define ZLIB_FILEFUNC_MODE_READ (1) -#define ZLIB_FILEFUNC_MODE_WRITE (2) -#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) - -#define ZLIB_FILEFUNC_MODE_EXISTING (4) -#define ZLIB_FILEFUNC_MODE_CREATE (8) - - -#ifndef ZCALLBACK - -#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) -#define ZCALLBACK CALLBACK -#else -#define ZCALLBACK -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); -typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); -typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); -typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); -typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); -typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); - -typedef struct zlib_filefunc_def_s -{ - open_file_func zopen_file; - read_file_func zread_file; - write_file_func zwrite_file; - tell_file_func ztell_file; - seek_file_func zseek_file; - close_file_func zclose_file; - testerror_file_func zerror_file; - voidpf opaque; -} zlib_filefunc_def; - - - -void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); - -#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) -#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) -#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) -#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) -#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) -#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) - - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/externals/g3dlite/zip.lib/include/zip/unzip.h b/externals/g3dlite/zip.lib/include/zip/unzip.h deleted file mode 100644 index b247937c807..00000000000 --- a/externals/g3dlite/zip.lib/include/zip/unzip.h +++ /dev/null @@ -1,354 +0,0 @@ -/* unzip.h -- IO for uncompress .zip files using zlib - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g - WinZip, InfoZip tools and compatible. - - Multi volume ZipFile (span) are not supported. - Encryption compatible with pkzip 2.04g only supported - Old compressions used by old PKZip 1.x are not supported - - - I WAIT FEEDBACK at mail info@winimage.com - Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution - - Condition of use and distribution are the same than zlib : - - 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. - - -*/ - -/* for more info about .ZIP format, see - http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip - http://www.info-zip.org/pub/infozip/doc/ - PkWare has also a specification at : - ftp://ftp.pkware.com/probdesc.zip -*/ - -#ifndef _unz_H -#define _unz_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ZLIB_H -#include "zlib.h" -#endif - -#ifndef _ZLIBIOAPI_H -#include "ioapi.h" -#endif - -#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) -/* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ -typedef struct TagunzFile__ { int unused; } unzFile__; -typedef unzFile__ *unzFile; -#else -typedef voidp unzFile; -#endif - - -#define UNZ_OK (0) -#define UNZ_END_OF_LIST_OF_FILE (-100) -#define UNZ_ERRNO (Z_ERRNO) -#define UNZ_EOF (0) -#define UNZ_PARAMERROR (-102) -#define UNZ_BADZIPFILE (-103) -#define UNZ_INTERNALERROR (-104) -#define UNZ_CRCERROR (-105) - -/* tm_unz contain date/time info */ -typedef struct tm_unz_s -{ - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ -} tm_unz; - -/* unz_global_info structure contain global data about the ZIPfile - These data comes from the end of central dir */ -typedef struct unz_global_info_s -{ - uLong number_entry; /* total number of entries in - the central dir on this disk */ - uLong size_comment; /* size of the global comment of the zipfile */ -} unz_global_info; - - -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_info_s -{ - uLong version; /* version made by 2 bytes */ - uLong version_needed; /* version needed to extract 2 bytes */ - uLong flag; /* general purpose bit flag 2 bytes */ - uLong compression_method; /* compression method 2 bytes */ - uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ - uLong crc; /* crc-32 4 bytes */ - uLong compressed_size; /* compressed size 4 bytes */ - uLong uncompressed_size; /* uncompressed size 4 bytes */ - uLong size_filename; /* filename length 2 bytes */ - uLong size_file_extra; /* extra field length 2 bytes */ - uLong size_file_comment; /* file comment length 2 bytes */ - - uLong disk_num_start; /* disk number start 2 bytes */ - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ - - tm_unz tmu_date; -} unz_file_info; - -extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, - const char* fileName2, - int iCaseSensitivity)); -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) -*/ - - -extern unzFile ZEXPORT unzOpen OF((const char *path)); -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer - "zlib/zlib113.zip". - If the zipfile cannot be opened (file don't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ - -extern unzFile ZEXPORT unzOpen2 OF((const char *path, - zlib_filefunc_def* pzlib_filefunc_def)); -/* - Open a Zip file, like unzOpen, but provide a set of file low level API - for read/write the zip file (see ioapi.h) -*/ - -extern int ZEXPORT unzClose OF((unzFile file)); -/* - Close a ZipFile opened with unzipOpen. - If there is files inside the .Zip opened with unzOpenCurrentFile (see later), - these files MUST be closed with unzipCloseCurrentFile before call unzipClose. - return UNZ_OK if there is no problem. */ - -extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, - unz_global_info *pglobal_info)); -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ - - -extern int ZEXPORT unzGetGlobalComment OF((unzFile file, - char *szComment, - uLong uSizeBuf)); -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ - - -/***************************************************************************/ -/* Unzip package allow you browse the directory of the zipfile */ - -extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ - -extern int ZEXPORT unzGoToNextFile OF((unzFile file)); -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ - -extern int ZEXPORT unzLocateFile OF((unzFile file, - const char *szFileName, - int iCaseSensitivity)); -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ - - -/* ****************************************** */ -/* Ryan supplied functions */ -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_pos_s -{ - uLong pos_in_zip_directory; /* offset in zip file directory */ - uLong num_of_file; /* # of file */ -} unz_file_pos; - -extern int ZEXPORT unzGetFilePos( - unzFile file, - unz_file_pos* file_pos); - -extern int ZEXPORT unzGoToFilePos( - unzFile file, - unz_file_pos* file_pos); - -/* ****************************************** */ - -extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); -/* - Get Info about the current file - if pfile_info!=NULL, the *pfile_info structure will contain somes info about - the current file - if szFileName!=NULL, the filemane string will be copied in szFileName - (fileNameBufferSize is the size of the buffer) - if extraField!=NULL, the extra field information will be copied in extraField - (extraFieldBufferSize is the size of the buffer). - This is the Central-header version of the extra field - if szComment!=NULL, the comment string of the file will be copied in szComment - (commentBufferSize is the size of the buffer) -*/ - -/***************************************************************************/ -/* for reading the content of the current zipfile, you can open it, read data - from it, and close it (you can close it before reading all the file) - */ - -extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); -/* - Open for reading data the current file in the zipfile. - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, - const char* password)); -/* - Open for reading data the current file in the zipfile. - password is a crypting password - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, - int* method, - int* level, - int raw)); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - if raw==1 - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - -extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, - int* method, - int* level, - int raw, - const char* password)); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - if raw==1 - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - - -extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); -/* - Close the file in zip opened with unzOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ - -extern int ZEXPORT unzReadCurrentFile OF((unzFile file, - voidp buf, - unsigned len)); -/* - Read bytes from the current file (opened by unzOpenCurrentFile) - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ - -extern z_off_t ZEXPORT unztell OF((unzFile file)); -/* - Give the current position in uncompressed data -*/ - -extern int ZEXPORT unzeof OF((unzFile file)); -/* - return 1 if the end of file was reached, 0 elsewhere -*/ - -extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, - voidp buf, - unsigned len)); -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ - -/***************************************************************************/ - -/* Get the current file offset */ -extern uLong ZEXPORT unzGetOffset (unzFile file); - -/* Set the current file offset */ -extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); - - - -#ifdef __cplusplus -} -#endif - -#endif /* _unz_H */ diff --git a/externals/g3dlite/zip.lib/include/zip/zip.h b/externals/g3dlite/zip.lib/include/zip/zip.h deleted file mode 100644 index acacce83b9b..00000000000 --- a/externals/g3dlite/zip.lib/include/zip/zip.h +++ /dev/null @@ -1,235 +0,0 @@ -/* zip.h -- IO for compress .zip files using zlib - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - This unzip package allow creates .ZIP file, compatible with PKZip 2.04g - WinZip, InfoZip tools and compatible. - Multi volume ZipFile (span) are not supported. - Encryption compatible with pkzip 2.04g only supported - Old compressions used by old PKZip 1.x are not supported - - For uncompress .zip file, look at unzip.h - - - I WAIT FEEDBACK at mail info@winimage.com - Visit also http://www.winimage.com/zLibDll/unzip.html for evolution - - Condition of use and distribution are the same than zlib : - - 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. - - -*/ - -/* for more info about .ZIP format, see - http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip - http://www.info-zip.org/pub/infozip/doc/ - PkWare has also a specification at : - ftp://ftp.pkware.com/probdesc.zip -*/ - -#ifndef _zip_H -#define _zip_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ZLIB_H -#include "zlib.h" -#endif - -#ifndef _ZLIBIOAPI_H -#include "ioapi.h" -#endif - -#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) -/* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ -typedef struct TagzipFile__ { int unused; } zipFile__; -typedef zipFile__ *zipFile; -#else -typedef voidp zipFile; -#endif - -#define ZIP_OK (0) -#define ZIP_EOF (0) -#define ZIP_ERRNO (Z_ERRNO) -#define ZIP_PARAMERROR (-102) -#define ZIP_BADZIPFILE (-103) -#define ZIP_INTERNALERROR (-104) - -#ifndef DEF_MEM_LEVEL -# if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -# else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -# endif -#endif -/* default memLevel */ - -/* tm_zip contain date/time info */ -typedef struct tm_zip_s -{ - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ -} tm_zip; - -typedef struct -{ - tm_zip tmz_date; /* date in understandable format */ - uLong dosDate; /* if dos_date == 0, tmu_date is used */ -/* uLong flag; */ /* general purpose bit flag 2 bytes */ - - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ -} zip_fileinfo; - -typedef const char* zipcharpc; - - -#define APPEND_STATUS_CREATE (0) -#define APPEND_STATUS_CREATEAFTER (1) -#define APPEND_STATUS_ADDINZIP (2) - -extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); -/* - Create a zipfile. - pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on - an Unix computer "zlib/zlib113.zip". - if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip - will be created at the end of the file. - (useful if the file contain a self extractor code) - if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will - add files in existing zip (be sure you don't add file that doesn't exist) - If the zipfile cannot be opened, the return value is NULL. - Else, the return value is a zipFile Handle, usable with other function - of this zip package. -*/ - -/* Note : there is no delete function into a zipfile. - If you want delete file into a zipfile, you must open a zipfile, and create another - Of couse, you can use RAW reading and writing to copy the file you did not want delte -*/ - -extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, - int append, - zipcharpc* globalcomment, - zlib_filefunc_def* pzlib_filefunc_def)); - -extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level)); -/* - Open a file in the ZIP for writing. - filename : the filename in zip (if NULL, '-' without quote will be used - *zipfi contain supplemental information - if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local - contains the extrafield data the the local header - if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global - contains the extrafield data the the local header - if comment != NULL, comment contain the comment string - method contain the compression method (0 for store, Z_DEFLATED for deflate) - level contain the level of compression (can be Z_DEFAULT_COMPRESSION) -*/ - - -extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw)); - -/* - Same than zipOpenNewFileInZip, except if raw=1, we write raw file - */ - -extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCtypting)); - -/* - Same than zipOpenNewFileInZip2, except - windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 - password : crypting password (NULL for no crypting) - crcForCtypting : crc of file to compress (needed for crypting) - */ - - -extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, - const void* buf, - unsigned len)); -/* - Write data in the zipfile -*/ - -extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); -/* - Close the current file in the zipfile -*/ - -extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, - uLong uncompressed_size, - uLong crc32)); -/* - Close the current file in the zipfile, for fiel opened with - parameter raw=1 in zipOpenNewFileInZip2 - uncompressed_size and crc32 are value for the uncompressed size -*/ - -extern int ZEXPORT zipClose OF((zipFile file, - const char* global_comment)); -/* - Close the zipfile -*/ - -#ifdef __cplusplus -} -#endif - -#endif /* _zip_H */ diff --git a/externals/g3dlite/zip.lib/source/crypt.h b/externals/g3dlite/zip.lib/source/crypt.h deleted file mode 100644 index 622f4bc2ec4..00000000000 --- a/externals/g3dlite/zip.lib/source/crypt.h +++ /dev/null @@ -1,132 +0,0 @@ -/* crypt.h -- base code for crypt/uncrypt ZIPfile - - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - This code is a modified version of crypting code in Infozip distribution - - The encryption/decryption parts of this source code (as opposed to the - non-echoing password parts) were originally written in Europe. The - whole source package can be freely distributed, including from the USA. - (Prior to January 2000, re-export from the US was a violation of US law.) - - This encryption code is a direct transcription of the algorithm from - Roger Schlafly, described by Phil Katz in the file appnote.txt. This - file (appnote.txt) is distributed with the PKZIP program (even in the - version without encryption capabilities). - - If you don't need crypting in your application, just define symbols - NOCRYPT and NOUNCRYPT. - - This code support the "Traditional PKWARE Encryption". - - The new AES encryption added on Zip format by Winzip (see the page - http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong - Encryption is not supported. -*/ - -#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) - -/*********************************************************************** - * Return the next byte in the pseudo-random sequence - */ -static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) -{ - unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an - * unpredictable manner on 16-bit systems; not a problem - * with any known compiler so far, though */ - - temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; - return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); -} - -/*********************************************************************** - * Update the encryption keys with the next byte of plain text - */ -static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) -{ - (*(pkeys+0)) = CRC32((*(pkeys+0)), c); - (*(pkeys+1)) += (*(pkeys+0)) & 0xff; - (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; - { - register int keyshift = (int)((*(pkeys+1)) >> 24); - (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); - } - return c; -} - - -/*********************************************************************** - * Initialize the encryption keys and the random header according to - * the given password. - */ -static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) -{ - *(pkeys+0) = 305419896L; - *(pkeys+1) = 591751049L; - *(pkeys+2) = 878082192L; - while (*passwd != '\0') { - update_keys(pkeys,pcrc_32_tab,(int)*passwd); - passwd++; - } -} - -#define zdecode(pkeys,pcrc_32_tab,c) \ - (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) - -#define zencode(pkeys,pcrc_32_tab,c,t) \ - (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) - -#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED - -#define RAND_HEAD_LEN 12 - /* "last resort" source for second part of crypt seed pattern */ -# ifndef ZCR_SEED2 -# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ -# endif - -static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) - const char *passwd; /* password string */ - unsigned char *buf; /* where to write header */ - int bufSize; - unsigned long* pkeys; - const unsigned long* pcrc_32_tab; - unsigned long crcForCrypting; -{ - int n; /* index in random header */ - int t; /* temporary */ - int c; /* random byte */ - unsigned char header[RAND_HEAD_LEN-2]; /* random header */ - static unsigned calls = 0; /* ensure different random header each time */ - - if (bufSize> 7) & 0xff; - header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); - } - /* Encrypt random header (last two bytes is high word of crc) */ - init_keys(passwd, pkeys, pcrc_32_tab); - for (n = 0; n < RAND_HEAD_LEN-2; n++) - { - buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); - } - buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); - buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); - return n; -} - -#endif diff --git a/externals/g3dlite/zip.lib/source/ioapi.c b/externals/g3dlite/zip.lib/source/ioapi.c deleted file mode 100644 index f1bee23e64b..00000000000 --- a/externals/g3dlite/zip.lib/source/ioapi.c +++ /dev/null @@ -1,177 +0,0 @@ -/* ioapi.c -- IO base function header for compress/uncompress .zip - files using zlib + zip or unzip API - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant -*/ - -#include -#include -#include - -#include "zlib.h" -#include "ioapi.h" - - - -/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ - -#ifndef SEEK_CUR -#define SEEK_CUR 1 -#endif - -#ifndef SEEK_END -#define SEEK_END 2 -#endif - -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif - -voidpf ZCALLBACK fopen_file_func OF(( - voidpf opaque, - const char* filename, - int mode)); - -uLong ZCALLBACK fread_file_func OF(( - voidpf opaque, - voidpf stream, - void* buf, - uLong size)); - -uLong ZCALLBACK fwrite_file_func OF(( - voidpf opaque, - voidpf stream, - const void* buf, - uLong size)); - -long ZCALLBACK ftell_file_func OF(( - voidpf opaque, - voidpf stream)); - -long ZCALLBACK fseek_file_func OF(( - voidpf opaque, - voidpf stream, - uLong offset, - int origin)); - -int ZCALLBACK fclose_file_func OF(( - voidpf opaque, - voidpf stream)); - -int ZCALLBACK ferror_file_func OF(( - voidpf opaque, - voidpf stream)); - - -voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) - voidpf opaque; - const char* filename; - int mode; -{ - FILE* file = NULL; - const char* mode_fopen = NULL; - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - mode_fopen = "rb"; - else - if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - mode_fopen = "r+b"; - else - if (mode & ZLIB_FILEFUNC_MODE_CREATE) - mode_fopen = "wb"; - - if ((filename!=NULL) && (mode_fopen != NULL)) - file = fopen(filename, mode_fopen); - return file; -} - - -uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) - voidpf opaque; - voidpf stream; - void* buf; - uLong size; -{ - uLong ret; - ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - - -uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) - voidpf opaque; - voidpf stream; - const void* buf; - uLong size; -{ - uLong ret; - ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - -long ZCALLBACK ftell_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - long ret; - ret = ftell((FILE *)stream); - return ret; -} - -long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) - voidpf opaque; - voidpf stream; - uLong offset; - int origin; -{ - int fseek_origin=0; - long ret; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - fseek_origin = SEEK_CUR; - break; - case ZLIB_FILEFUNC_SEEK_END : - fseek_origin = SEEK_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - fseek_origin = SEEK_SET; - break; - default: return -1; - } - ret = 0; - fseek((FILE *)stream, offset, fseek_origin); - return ret; -} - -int ZCALLBACK fclose_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - int ret; - ret = fclose((FILE *)stream); - return ret; -} - -int ZCALLBACK ferror_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - int ret; - ret = ferror((FILE *)stream); - return ret; -} - -void fill_fopen_filefunc (pzlib_filefunc_def) - zlib_filefunc_def* pzlib_filefunc_def; -{ - pzlib_filefunc_def->zopen_file = fopen_file_func; - pzlib_filefunc_def->zread_file = fread_file_func; - pzlib_filefunc_def->zwrite_file = fwrite_file_func; - pzlib_filefunc_def->ztell_file = ftell_file_func; - pzlib_filefunc_def->zseek_file = fseek_file_func; - pzlib_filefunc_def->zclose_file = fclose_file_func; - pzlib_filefunc_def->zerror_file = ferror_file_func; - pzlib_filefunc_def->opaque = NULL; -} diff --git a/externals/g3dlite/zip.lib/source/iowin32.c b/externals/g3dlite/zip.lib/source/iowin32.c deleted file mode 100644 index ce911e3636e..00000000000 --- a/externals/g3dlite/zip.lib/source/iowin32.c +++ /dev/null @@ -1,272 +0,0 @@ -#ifdef _MSC_VER -/* iowin32.c -- IO base function header for compress/uncompress .zip - files using zlib + zip or unzip API - This IO API version uses the Win32 API (for Microsoft Windows) - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant -*/ - -#include - -#include "zlib.h" -#include "ioapi.h" -#include "iowin32.h" - -#ifndef INVALID_HANDLE_VALUE -#define INVALID_HANDLE_VALUE (0xFFFFFFFF) -#endif - -#ifndef INVALID_SET_FILE_POINTER -#define INVALID_SET_FILE_POINTER ((DWORD)-1) -#endif - -voidpf ZCALLBACK win32_open_file_func OF(( - voidpf opaque, - const char* filename, - int mode)); - -uLong ZCALLBACK win32_read_file_func OF(( - voidpf opaque, - voidpf stream, - void* buf, - uLong size)); - -uLong ZCALLBACK win32_write_file_func OF(( - voidpf opaque, - voidpf stream, - const void* buf, - uLong size)); - -long ZCALLBACK win32_tell_file_func OF(( - voidpf opaque, - voidpf stream)); - -long ZCALLBACK win32_seek_file_func OF(( - voidpf opaque, - voidpf stream, - uLong offset, - int origin)); - -int ZCALLBACK win32_close_file_func OF(( - voidpf opaque, - voidpf stream)); - -int ZCALLBACK win32_error_file_func OF(( - voidpf opaque, - voidpf stream)); - -typedef struct -{ - HANDLE hf; - int error; -} WIN32FILE_IOWIN; - -voidpf ZCALLBACK win32_open_file_func (opaque, filename, mode) - voidpf opaque; - const char* filename; - int mode; -{ - const char* mode_fopen = NULL; - DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; - HANDLE hFile = 0; - voidpf ret=NULL; - - dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0; - - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - { - dwDesiredAccess = GENERIC_READ; - dwCreationDisposition = OPEN_EXISTING; - dwShareMode = FILE_SHARE_READ; - } - else - if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - { - dwDesiredAccess = GENERIC_WRITE | GENERIC_READ; - dwCreationDisposition = OPEN_EXISTING; - } - else - if (mode & ZLIB_FILEFUNC_MODE_CREATE) - { - dwDesiredAccess = GENERIC_WRITE | GENERIC_READ; - dwCreationDisposition = CREATE_ALWAYS; - } - - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, - dwCreationDisposition, dwFlagsAndAttributes, NULL); - - if (hFile == INVALID_HANDLE_VALUE) - hFile = NULL; - - if (hFile != NULL) - { - WIN32FILE_IOWIN w32fiow; - w32fiow.hf = hFile; - w32fiow.error = 0; - ret = malloc(sizeof(WIN32FILE_IOWIN)); - if (ret==NULL) - CloseHandle(hFile); - else *((WIN32FILE_IOWIN*)ret) = w32fiow; - } - return ret; -} - - -uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size) - voidpf opaque; - voidpf stream; - void* buf; - uLong size; -{ - uLong ret=0; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - if (hFile != NULL) - if (!ReadFile(hFile, buf, size, &ret, NULL)) - { - DWORD dwErr = GetLastError(); - if (dwErr == ERROR_HANDLE_EOF) - dwErr = 0; - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - } - - return ret; -} - - -uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size) - voidpf opaque; - voidpf stream; - const void* buf; - uLong size; -{ - uLong ret=0; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - - if (hFile !=NULL) - if (!WriteFile(hFile, buf, size, &ret, NULL)) - { - DWORD dwErr = GetLastError(); - if (dwErr == ERROR_HANDLE_EOF) - dwErr = 0; - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - } - - return ret; -} - -long ZCALLBACK win32_tell_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - long ret=-1; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - if (hFile != NULL) - { - DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); - if (dwSet == INVALID_SET_FILE_POINTER) - { - DWORD dwErr = GetLastError(); - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - ret = -1; - } - else - ret=(long)dwSet; - } - return ret; -} - -long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin) - voidpf opaque; - voidpf stream; - uLong offset; - int origin; -{ - DWORD dwMoveMethod=0xFFFFFFFF; - HANDLE hFile = NULL; - - long ret=-1; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - dwMoveMethod = FILE_CURRENT; - break; - case ZLIB_FILEFUNC_SEEK_END : - dwMoveMethod = FILE_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - dwMoveMethod = FILE_BEGIN; - break; - default: return -1; - } - - if (hFile != NULL) - { - DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod); - if (dwSet == INVALID_SET_FILE_POINTER) - { - DWORD dwErr = GetLastError(); - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - ret = -1; - } - else - ret=0; - } - return ret; -} - -int ZCALLBACK win32_close_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - int ret=-1; - - if (stream!=NULL) - { - HANDLE hFile; - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - if (hFile != NULL) - { - CloseHandle(hFile); - ret=0; - } - free(stream); - } - return ret; -} - -int ZCALLBACK win32_error_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - int ret=-1; - if (stream!=NULL) - { - ret = ((WIN32FILE_IOWIN*)stream) -> error; - } - return ret; -} - -void fill_win32_filefunc (pzlib_filefunc_def) - zlib_filefunc_def* pzlib_filefunc_def; -{ - pzlib_filefunc_def->zopen_file = win32_open_file_func; - pzlib_filefunc_def->zread_file = win32_read_file_func; - pzlib_filefunc_def->zwrite_file = win32_write_file_func; - pzlib_filefunc_def->ztell_file = win32_tell_file_func; - pzlib_filefunc_def->zseek_file = win32_seek_file_func; - pzlib_filefunc_def->zclose_file = win32_close_file_func; - pzlib_filefunc_def->zerror_file = win32_error_file_func; - pzlib_filefunc_def->opaque=NULL; -} -#endif diff --git a/externals/g3dlite/zip.lib/source/iowin32.h b/externals/g3dlite/zip.lib/source/iowin32.h deleted file mode 100644 index 1978f6152dd..00000000000 --- a/externals/g3dlite/zip.lib/source/iowin32.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifdef _MSC_VER -/* iowin32.h -- IO base function header for compress/uncompress .zip - files using zlib + zip or unzip API - This IO API version uses the Win32 API (for Microsoft Windows) - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant -*/ - -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/externals/g3dlite/zip.lib/source/unzip.c b/externals/g3dlite/zip.lib/source/unzip.c deleted file mode 100644 index e80bc5bde7c..00000000000 --- a/externals/g3dlite/zip.lib/source/unzip.c +++ /dev/null @@ -1,1604 +0,0 @@ -/* unzip.c -- IO for uncompress .zip files using zlib - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - Read unzip.h for more info -*/ - -/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of -compatibility with older software. The following is from the original crypt.c. Code -woven in by Terry Thorsen 1/2003. -*/ -/* - Copyright (c) 1990-2000 Info-ZIP. All rights reserved. - - See the accompanying file LICENSE, version 2000-Apr-09 or later - (the contents of which are also included in zip.h) for terms of use. - If, for some reason, all these files are missing, the Info-ZIP license - also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html -*/ -/* - crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] - - The encryption/decryption parts of this source code (as opposed to the - non-echoing password parts) were originally written in Europe. The - whole source package can be freely distributed, including from the USA. - (Prior to January 2000, re-export from the US was a violation of US law.) - */ - -/* - This encryption code is a direct transcription of the algorithm from - Roger Schlafly, described by Phil Katz in the file appnote.txt. This - file (appnote.txt) is distributed with the PKZIP program (even in the - version without encryption capabilities). - */ - - -#include -#include -#include -#include "zlib.h" -#include "unzip.h" - -#ifdef STDC -# include -# include -# include -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include -#endif - - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - - -#ifndef CASESENSITIVITYDEFAULT_NO -# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) -# define CASESENSITIVITYDEFAULT_NO -# endif -#endif - - -#ifndef UNZ_BUFSIZE -#define UNZ_BUFSIZE (16384) -#endif - -#ifndef UNZ_MAXFILENAMEINZIP -#define UNZ_MAXFILENAMEINZIP (256) -#endif - -#ifndef ALLOC -# define ALLOC(size) (malloc(size)) -#endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif - -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) - - - - -const char unz_copyright[] = - " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; - -/* unz_file_info_interntal contain internal info about a file in zipfile*/ -typedef struct unz_file_info_internal_s -{ - uLong offset_curfile;/* relative offset of local header 4 bytes */ -} unz_file_info_internal; - - -/* file_in_zip_read_info_s contain internal information about a file in zipfile, - when reading and decompress it */ -typedef struct -{ - char *read_buffer; /* internal buffer for compressed data */ - z_stream stream; /* zLib stream structure for inflate */ - - uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ - uLong stream_initialised; /* flag set if stream structure is initialised*/ - - uLong offset_local_extrafield;/* offset of the local extra field */ - uInt size_local_extrafield;/* size of the local extra field */ - uLong pos_local_extrafield; /* position in the local extra field in read*/ - - uLong crc32; /* crc32 of all data uncompressed */ - uLong crc32_wait; /* crc32 we must obtain after decompress all */ - uLong rest_read_compressed; /* number of byte to be decompressed */ - uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ - zlib_filefunc_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - uLong compression_method; /* compression method (0==store) */ - uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - int raw; -} file_in_zip_read_info_s; - - -/* unz_s contain internal information about the zipfile -*/ -typedef struct -{ - zlib_filefunc_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - unz_global_info gi; /* public global information */ - uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - uLong num_file; /* number of the current file in the zipfile*/ - uLong pos_in_central_dir; /* pos of the current file in the central dir*/ - uLong current_file_ok; /* flag about the usability of the current file*/ - uLong central_pos; /* position of the beginning of the central dir*/ - - uLong size_central_dir; /* size of the central directory */ - uLong offset_central_dir; /* offset of start of central directory with - respect to the starting disk number */ - - unz_file_info cur_file_info; /* public info about the current file in zip*/ - unz_file_info_internal cur_file_info_internal; /* private info about it*/ - file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current - file if we are decompressing it */ - int encrypted; -# ifndef NOUNCRYPT - unsigned long keys[3]; /* keys defining the pseudo-random sequence */ - const unsigned long* pcrc_32_tab; -# endif -} unz_s; - - -#ifndef NOUNCRYPT -#include "crypt.h" -#endif - -/* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been sucessfully opened for reading. -*/ - - -local int unzlocal_getByte OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - int *pi)); - -local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - int *pi; -{ - unsigned char c; - int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); - if (err==1) - { - *pi = (int)c; - return UNZ_OK; - } - else - { - if (ZERROR(*pzlib_filefunc_def,filestream)) - return UNZ_ERRNO; - else - return UNZ_EOF; - } -} - - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int unzlocal_getShort OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - uLong *pX; -{ - uLong x = 0; - int i = 0; - int err = 0; - - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unzlocal_getLong OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - uLong *pX; -{ - uLong x = 0; - int i = 0; - int err = 0; - - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<24; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - - -/* My own strcmpi / strcasecmp */ -local int strcmpcasenosensitive_internal (fileName1,fileName2) - const char* fileName1; - const char* fileName2; -{ - for (;;) - { - char c1=*(fileName1++); - char c2=*(fileName2++); - if ((c1>='a') && (c1<='z')) - c1 -= 0x20; - if ((c2>='a') && (c2<='z')) - c2 -= 0x20; - if (c1=='\0') - return ((c2=='\0') ? 0 : -1); - if (c2=='\0') - return 1; - if (c1c2) - return 1; - } -} - - -#ifdef CASESENSITIVITYDEFAULT_NO -#define CASESENSITIVITYDEFAULTVALUE 2 -#else -#define CASESENSITIVITYDEFAULTVALUE 1 -#endif - -#ifndef STRCMPCASENOSENTIVEFUNCTION -#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal -#endif - -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) - -*/ -extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) - const char* fileName1; - const char* fileName2; - int iCaseSensitivity; -{ - if (iCaseSensitivity==0) - iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; - - if (iCaseSensitivity==1) - return strcmp(fileName1,fileName2); - - return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); -} - -#ifndef BUFREADCOMMENT -#define BUFREADCOMMENT (0x400) -#endif - -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -local uLong unzlocal_SearchCentralDir OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream)); - -local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; -{ - unsigned char* buf; - uLong uSizeFile; - uLong uBackRead; - uLong uMaxBack=0xffff; /* maximum size of global comment */ - uLong uPosFound=0; - - if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); - if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - return uPosFound; -} - -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer - "zlib/zlib114.zip". - If the zipfile cannot be opened (file doesn't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ -extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def) - const char *path; - zlib_filefunc_def* pzlib_filefunc_def; -{ - unz_s us; - unz_s *s; - uLong central_pos,uL; - - uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ - uLong number_entry_CD; /* total number of entries in - the central dir - (same than number_entry on nospan) */ - - int err=UNZ_OK; - - if (unz_copyright[0]!=' ') - return NULL; - - if (pzlib_filefunc_def==NULL) - fill_fopen_filefunc(&us.z_filefunc); - else - us.z_filefunc = *pzlib_filefunc_def; - - us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, - path, - ZLIB_FILEFUNC_MODE_READ | - ZLIB_FILEFUNC_MODE_EXISTING); - if (us.filestream==NULL) - return NULL; - - central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); - if (central_pos==0) - err=UNZ_ERRNO; - - if (ZSEEK(us.z_filefunc, us.filestream, - central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - /* the signature, already checked */ - if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of this disk */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of the disk with the start of the central directory */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir on this disk */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((number_entry_CD!=us.gi.number_entry) || - (number_disk_with_CD!=0) || - (number_disk!=0)) - err=UNZ_BADZIPFILE; - - /* size of the central directory */ - if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* offset of start of central directory with respect to the - starting disk number */ - if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* zipfile comment length */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((central_pospfile_in_zip_read!=NULL) - unzCloseCurrentFile(file); - - ZCLOSE(s->z_filefunc, s->filestream); - TRYFREE(s); - return UNZ_OK; -} - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) - unzFile file; - unz_global_info *pglobal_info; -{ - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - *pglobal_info=s->gi; - return UNZ_OK; -} - - -/* - Translate date/time from Dos format to tm_unz (readable more easilty) -*/ -local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) - uLong ulDosDate; - tm_unz* ptm; -{ - uLong uDate; - uDate = (uLong)(ulDosDate>>16); - ptm->tm_mday = (uInt)(uDate&0x1f) ; - ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; - ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; - - ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); - ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; - ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; -} - -/* - Get Info about the current file in the zipfile, with internal only info -*/ -local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, - unz_file_info *pfile_info, - unz_file_info_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); - -local int unzlocal_GetCurrentFileInfoInternal (file, - pfile_info, - pfile_info_internal, - szFileName, fileNameBufferSize, - extraField, extraFieldBufferSize, - szComment, commentBufferSize) - unzFile file; - unz_file_info *pfile_info; - unz_file_info_internal *pfile_info_internal; - char *szFileName; - uLong fileNameBufferSize; - void *extraField; - uLong extraFieldBufferSize; - char *szComment; - uLong commentBufferSize; -{ - unz_s* s; - unz_file_info file_info; - unz_file_info_internal file_info_internal; - int err=UNZ_OK; - uLong uMagic; - long lSeek=0; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (ZSEEK(s->z_filefunc, s->filestream, - s->pos_in_central_dir+s->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - - /* we check the magic */ - if (err==UNZ_OK) - { - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x02014b50) - err=UNZ_BADZIPFILE; - } - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) - err=UNZ_ERRNO; - - unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) - err=UNZ_ERRNO; - - lSeek+=file_info.size_filename; - if ((err==UNZ_OK) && (szFileName!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_filename0) && (fileNameBufferSize>0)) - if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek -= uSizeRead; - } - - - if ((err==UNZ_OK) && (extraField!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) - if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek += file_info.size_file_extra - uSizeRead; - } - else - lSeek+=file_info.size_file_extra; - - - if ((err==UNZ_OK) && (szComment!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - if ((file_info.size_file_comment>0) && (commentBufferSize>0)) - if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek+=file_info.size_file_comment - uSizeRead; - } - else - lSeek+=file_info.size_file_comment; - - if ((err==UNZ_OK) && (pfile_info!=NULL)) - *pfile_info=file_info; - - if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) - *pfile_info_internal=file_info_internal; - - return err; -} - - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. -*/ -extern int ZEXPORT unzGetCurrentFileInfo (file, - pfile_info, - szFileName, fileNameBufferSize, - extraField, extraFieldBufferSize, - szComment, commentBufferSize) - unzFile file; - unz_file_info *pfile_info; - char *szFileName; - uLong fileNameBufferSize; - void *extraField; - uLong extraFieldBufferSize; - char *szComment; - uLong commentBufferSize; -{ - return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); -} - -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ -extern int ZEXPORT unzGoToFirstFile (file) - unzFile file; -{ - int err=UNZ_OK; - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - s->pos_in_central_dir=s->offset_central_dir; - s->num_file=0; - err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ -extern int ZEXPORT unzGoToNextFile (file) - unzFile file; -{ - unz_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ - if (s->num_file+1==s->gi.number_entry) - return UNZ_END_OF_LIST_OF_FILE; - - s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + - s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; - s->num_file++; - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzipStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ -extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) - unzFile file; - const char *szFileName; - int iCaseSensitivity; -{ - unz_s* s; - int err; - - /* We remember the 'current' position in the file so that we can jump - * back there if we fail. - */ - unz_file_info cur_file_infoSaved; - unz_file_info_internal cur_file_info_internalSaved; - uLong num_fileSaved; - uLong pos_in_central_dirSaved; - - - if (file==NULL) - return UNZ_PARAMERROR; - - if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) - return UNZ_PARAMERROR; - - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - /* Save the current state */ - num_fileSaved = s->num_file; - pos_in_central_dirSaved = s->pos_in_central_dir; - cur_file_infoSaved = s->cur_file_info; - cur_file_info_internalSaved = s->cur_file_info_internal; - - err = unzGoToFirstFile(file); - - while (err == UNZ_OK) - { - char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; - err = unzGetCurrentFileInfo(file,NULL, - szCurrentFileName,sizeof(szCurrentFileName)-1, - NULL,0,NULL,0); - if (err == UNZ_OK) - { - if (unzStringFileNameCompare(szCurrentFileName, - szFileName,iCaseSensitivity)==0) - return UNZ_OK; - err = unzGoToNextFile(file); - } - } - - /* We failed, so restore the state of the 'current file' to where we - * were. - */ - s->num_file = num_fileSaved ; - s->pos_in_central_dir = pos_in_central_dirSaved ; - s->cur_file_info = cur_file_infoSaved; - s->cur_file_info_internal = cur_file_info_internalSaved; - return err; -} - - -/* -/////////////////////////////////////////// -// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) -// I need random access -// -// Further optimization could be realized by adding an ability -// to cache the directory in memory. The goal being a single -// comprehensive file read to put the file I need in a memory. -*/ - -/* -typedef struct unz_file_pos_s -{ - uLong pos_in_zip_directory; // offset in file - uLong num_of_file; // # of file -} unz_file_pos; -*/ - -extern int ZEXPORT unzGetFilePos(file, file_pos) - unzFile file; - unz_file_pos* file_pos; -{ - unz_s* s; - - if (file==NULL || file_pos==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - file_pos->pos_in_zip_directory = s->pos_in_central_dir; - file_pos->num_of_file = s->num_file; - - return UNZ_OK; -} - -extern int ZEXPORT unzGoToFilePos(file, file_pos) - unzFile file; - unz_file_pos* file_pos; -{ - unz_s* s; - int err; - - if (file==NULL || file_pos==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - /* jump to the right spot */ - s->pos_in_central_dir = file_pos->pos_in_zip_directory; - s->num_file = file_pos->num_of_file; - - /* set the current file */ - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - /* return results */ - s->current_file_ok = (err == UNZ_OK); - return err; -} - -/* -// Unzip Helper Functions - should be here? -/////////////////////////////////////////// -*/ - -/* - Read the local header of the current zipfile - Check the coherency of the local header and info in the end of central - directory about this file - store in *piSizeVar the size of extra info in local header - (filename and size of extra field data) -*/ -local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, - poffset_local_extrafield, - psize_local_extrafield) - unz_s* s; - uInt* piSizeVar; - uLong *poffset_local_extrafield; - uInt *psize_local_extrafield; -{ - uLong uMagic,uData,uFlags; - uLong size_filename; - uLong size_extra_field; - int err=UNZ_OK; - - *piSizeVar = 0; - *poffset_local_extrafield = 0; - *psize_local_extrafield = 0; - - if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + - s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - - if (err==UNZ_OK) - { - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x04034b50) - err=UNZ_BADZIPFILE; - } - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; -/* - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) - err=UNZ_BADZIPFILE; -*/ - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) - err=UNZ_BADZIPFILE; - - if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) - err=UNZ_BADZIPFILE; - - *piSizeVar += (uInt)size_filename; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) - err=UNZ_ERRNO; - *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + - SIZEZIPLOCALHEADER + size_filename; - *psize_local_extrafield = (uInt)size_extra_field; - - *piSizeVar += (uInt)size_extra_field; - - return err; -} - -/* - Open for reading data the current file in the zipfile. - If there is no error and the file is opened, the return value is UNZ_OK. -*/ -extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) - unzFile file; - int* method; - int* level; - int raw; - const char* password; -{ - int err=UNZ_OK; - uInt iSizeVar; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uLong offset_local_extrafield; /* offset of the local extra field */ - uInt size_local_extrafield; /* size of the local extra field */ -# ifndef NOUNCRYPT - char source[12]; -# else - if (password != NULL) - return UNZ_PARAMERROR; -# endif - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_PARAMERROR; - - if (s->pfile_in_zip_read != NULL) - unzCloseCurrentFile(file); - - if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, - &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) - return UNZ_BADZIPFILE; - - pfile_in_zip_read_info = (file_in_zip_read_info_s*) - ALLOC(sizeof(file_in_zip_read_info_s)); - if (pfile_in_zip_read_info==NULL) - return UNZ_INTERNALERROR; - - pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); - pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; - pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; - pfile_in_zip_read_info->pos_local_extrafield=0; - pfile_in_zip_read_info->raw=raw; - - if (pfile_in_zip_read_info->read_buffer==NULL) - { - TRYFREE(pfile_in_zip_read_info); - return UNZ_INTERNALERROR; - } - - pfile_in_zip_read_info->stream_initialised=0; - - if (method!=NULL) - *method = (int)s->cur_file_info.compression_method; - - if (level!=NULL) - { - *level = 6; - switch (s->cur_file_info.flag & 0x06) - { - case 6 : *level = 1; break; - case 4 : *level = 2; break; - case 2 : *level = 9; break; - } - } - - if ((s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; - pfile_in_zip_read_info->crc32=0; - pfile_in_zip_read_info->compression_method = - s->cur_file_info.compression_method; - pfile_in_zip_read_info->filestream=s->filestream; - pfile_in_zip_read_info->z_filefunc=s->z_filefunc; - pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; - - pfile_in_zip_read_info->stream.total_out = 0; - - if ((s->cur_file_info.compression_method==Z_DEFLATED) && - (!raw)) - { - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidpf)0; - pfile_in_zip_read_info->stream.next_in = (voidpf)0; - pfile_in_zip_read_info->stream.avail_in = 0; - - err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=1; - else - { - TRYFREE(pfile_in_zip_read_info); - return err; - } - /* windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. - * In unzip, i don't wait absolutely Z_STREAM_END because I known the - * size of both compressed and uncompressed data - */ - } - pfile_in_zip_read_info->rest_read_compressed = - s->cur_file_info.compressed_size ; - pfile_in_zip_read_info->rest_read_uncompressed = - s->cur_file_info.uncompressed_size ; - - - pfile_in_zip_read_info->pos_in_zipfile = - s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + - iSizeVar; - - pfile_in_zip_read_info->stream.avail_in = (uInt)0; - - s->pfile_in_zip_read = pfile_in_zip_read_info; - -# ifndef NOUNCRYPT - if (password != NULL) - { - int i; - s->pcrc_32_tab = get_crc_table(); - init_keys(password,s->keys,s->pcrc_32_tab); - if (ZSEEK(s->z_filefunc, s->filestream, - s->pfile_in_zip_read->pos_in_zipfile + - s->pfile_in_zip_read->byte_before_the_zipfile, - SEEK_SET)!=0) - return UNZ_INTERNALERROR; - if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12) - return UNZ_INTERNALERROR; - - for (i = 0; i<12; i++) - zdecode(s->keys,s->pcrc_32_tab,source[i]); - - s->pfile_in_zip_read->pos_in_zipfile+=12; - s->encrypted=1; - } -# endif - - - return UNZ_OK; -} - -extern int ZEXPORT unzOpenCurrentFile (file) - unzFile file; -{ - return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); -} - -extern int ZEXPORT unzOpenCurrentFilePassword (file, password) - unzFile file; - const char* password; -{ - return unzOpenCurrentFile3(file, NULL, NULL, 0, password); -} - -extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw) - unzFile file; - int* method; - int* level; - int raw; -{ - return unzOpenCurrentFile3(file, method, level, raw, NULL); -} - -/* - Read bytes from the current file. - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ -extern int ZEXPORT unzReadCurrentFile (file, buf, len) - unzFile file; - voidp buf; - unsigned len; -{ - int err=UNZ_OK; - uInt iRead = 0; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if ((pfile_in_zip_read_info->read_buffer == NULL)) - return UNZ_END_OF_LIST_OF_FILE; - if (len==0) - return 0; - - pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; - - pfile_in_zip_read_info->stream.avail_out = (uInt)len; - - if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && - (!(pfile_in_zip_read_info->raw))) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - - if ((len>pfile_in_zip_read_info->rest_read_compressed+ - pfile_in_zip_read_info->stream.avail_in) && - (pfile_in_zip_read_info->raw)) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_compressed+ - pfile_in_zip_read_info->stream.avail_in; - - while (pfile_in_zip_read_info->stream.avail_out>0) - { - if ((pfile_in_zip_read_info->stream.avail_in==0) && - (pfile_in_zip_read_info->rest_read_compressed>0)) - { - uInt uReadThis = UNZ_BUFSIZE; - if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; - if (uReadThis == 0) - return UNZ_EOF; - if (ZSEEK(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - if (ZREAD(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->read_buffer, - uReadThis)!=uReadThis) - return UNZ_ERRNO; - - -# ifndef NOUNCRYPT - if(s->encrypted) - { - uInt i; - for(i=0;iread_buffer[i] = - zdecode(s->keys,s->pcrc_32_tab, - pfile_in_zip_read_info->read_buffer[i]); - } -# endif - - - pfile_in_zip_read_info->pos_in_zipfile += uReadThis; - - pfile_in_zip_read_info->rest_read_compressed-=uReadThis; - - pfile_in_zip_read_info->stream.next_in = - (Bytef*)pfile_in_zip_read_info->read_buffer; - pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; - } - - if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) - { - uInt uDoCopy,i ; - - if ((pfile_in_zip_read_info->stream.avail_in == 0) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - return (iRead==0) ? UNZ_EOF : iRead; - - if (pfile_in_zip_read_info->stream.avail_out < - pfile_in_zip_read_info->stream.avail_in) - uDoCopy = pfile_in_zip_read_info->stream.avail_out ; - else - uDoCopy = pfile_in_zip_read_info->stream.avail_in ; - - for (i=0;istream.next_out+i) = - *(pfile_in_zip_read_info->stream.next_in+i); - - pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, - pfile_in_zip_read_info->stream.next_out, - uDoCopy); - pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; - pfile_in_zip_read_info->stream.avail_in -= uDoCopy; - pfile_in_zip_read_info->stream.avail_out -= uDoCopy; - pfile_in_zip_read_info->stream.next_out += uDoCopy; - pfile_in_zip_read_info->stream.next_in += uDoCopy; - pfile_in_zip_read_info->stream.total_out += uDoCopy; - iRead += uDoCopy; - } - else - { - uLong uTotalOutBefore,uTotalOutAfter; - const Bytef *bufBefore; - uLong uOutThis; - int flush=Z_SYNC_FLUSH; - - uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; - bufBefore = pfile_in_zip_read_info->stream.next_out; - - /* - if ((pfile_in_zip_read_info->rest_read_uncompressed == - pfile_in_zip_read_info->stream.avail_out) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - flush = Z_FINISH; - */ - err=inflate(&pfile_in_zip_read_info->stream,flush); - - if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) - err = Z_DATA_ERROR; - - uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; - uOutThis = uTotalOutAfter-uTotalOutBefore; - - pfile_in_zip_read_info->crc32 = - crc32(pfile_in_zip_read_info->crc32,bufBefore, - (uInt)(uOutThis)); - - pfile_in_zip_read_info->rest_read_uncompressed -= - uOutThis; - - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - - if (err==Z_STREAM_END) - return (iRead==0) ? UNZ_EOF : iRead; - if (err!=Z_OK) - break; - } - } - - if (err==Z_OK) - return iRead; - return err; -} - - -/* - Give the current position in uncompressed data -*/ -extern z_off_t ZEXPORT unztell (file) - unzFile file; -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - return (z_off_t)pfile_in_zip_read_info->stream.total_out; -} - - -/* - return 1 if the end of file was reached, 0 elsewhere -*/ -extern int ZEXPORT unzeof (file) - unzFile file; -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - return 1; - else - return 0; -} - - - -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field that can be read - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ -extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) - unzFile file; - voidp buf; - unsigned len; -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uInt read_now; - uLong size_to_read; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - size_to_read = (pfile_in_zip_read_info->size_local_extrafield - - pfile_in_zip_read_info->pos_local_extrafield); - - if (buf==NULL) - return (int)size_to_read; - - if (len>size_to_read) - read_now = (uInt)size_to_read; - else - read_now = (uInt)len ; - - if (read_now==0) - return 0; - - if (ZSEEK(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->offset_local_extrafield + - pfile_in_zip_read_info->pos_local_extrafield, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (ZREAD(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - buf,read_now)!=read_now) - return UNZ_ERRNO; - - return (int)read_now; -} - -/* - Close the file in zip opened with unzipOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ -extern int ZEXPORT unzCloseCurrentFile (file) - unzFile file; -{ - int err=UNZ_OK; - - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && - (!pfile_in_zip_read_info->raw)) - { - if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) - err=UNZ_CRCERROR; - } - - - TRYFREE(pfile_in_zip_read_info->read_buffer); - pfile_in_zip_read_info->read_buffer = NULL; - if (pfile_in_zip_read_info->stream_initialised) - inflateEnd(&pfile_in_zip_read_info->stream); - - pfile_in_zip_read_info->stream_initialised = 0; - TRYFREE(pfile_in_zip_read_info); - - s->pfile_in_zip_read=NULL; - - return err; -} - - -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ -extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) - unzFile file; - char *szComment; - uLong uSizeBuf; -{ - unz_s* s; - uLong uReadThis ; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - uReadThis = uSizeBuf; - if (uReadThis>s->gi.size_comment) - uReadThis = s->gi.size_comment; - - if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (uReadThis>0) - { - *szComment='\0'; - if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) - return UNZ_ERRNO; - } - - if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) - *(szComment+s->gi.size_comment)='\0'; - return (int)uReadThis; -} - -/* Additions by RX '2004 */ -extern uLong ZEXPORT unzGetOffset (file) - unzFile file; -{ - unz_s* s; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return 0; - if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) - if (s->num_file==s->gi.number_entry) - return 0; - return s->pos_in_central_dir; -} - -extern int ZEXPORT unzSetOffset (file, pos) - unzFile file; - uLong pos; -{ - unz_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - s->pos_in_central_dir = pos; - s->num_file = s->gi.number_entry; /* hack */ - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} diff --git a/externals/g3dlite/zip.lib/source/zip.c b/externals/g3dlite/zip.lib/source/zip.c deleted file mode 100644 index d5f9fe53d26..00000000000 --- a/externals/g3dlite/zip.lib/source/zip.c +++ /dev/null @@ -1,1221 +0,0 @@ -/* zip.c -- IO on .zip files using zlib - Version 1.01e, February 12th, 2005 - - 27 Dec 2004 Rolf Kalbermatter - Modification to zipOpen2 to support globalComment retrieval. - - Copyright (C) 1998-2005 Gilles Vollant - - Read zip.h for more info -*/ - - -#include -#include -#include -#include -#include "zlib.h" -#include "zip.h" - -#ifdef STDC -# include -# include -# include -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include -#endif - - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -#ifndef VERSIONMADEBY -# define VERSIONMADEBY (0x0) /* platform depedent */ -#endif - -#ifndef Z_BUFSIZE -#define Z_BUFSIZE (16384) -#endif - -#ifndef Z_MAXFILENAMEINZIP -#define Z_MAXFILENAMEINZIP (256) -#endif - -#ifndef ALLOC -# define ALLOC(size) (malloc(size)) -#endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif - -/* -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) -*/ - -/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ - -#ifndef SEEK_CUR -#define SEEK_CUR 1 -#endif - -#ifndef SEEK_END -#define SEEK_END 2 -#endif - -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif - -#ifndef DEF_MEM_LEVEL -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -#endif -const char zip_copyright[] = - " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; - - -#define SIZEDATA_INDATABLOCK (4096-(4*4)) - -#define LOCALHEADERMAGIC (0x04034b50) -#define CENTRALHEADERMAGIC (0x02014b50) -#define ENDHEADERMAGIC (0x06054b50) - -#define FLAG_LOCALHEADER_OFFSET (0x06) -#define CRC_LOCALHEADER_OFFSET (0x0e) - -#define SIZECENTRALHEADER (0x2e) /* 46 */ - -typedef struct linkedlist_datablock_internal_s -{ - struct linkedlist_datablock_internal_s* next_datablock; - uLong avail_in_this_block; - uLong filled_in_this_block; - uLong unused; /* for future use and alignement */ - unsigned char data[SIZEDATA_INDATABLOCK]; -} linkedlist_datablock_internal; - -typedef struct linkedlist_data_s -{ - linkedlist_datablock_internal* first_block; - linkedlist_datablock_internal* last_block; -} linkedlist_data; - - -typedef struct -{ - z_stream stream; /* zLib stream structure for inflate */ - int stream_initialised; /* 1 is stream is initialised */ - uInt pos_in_buffered_data; /* last written byte in buffered_data */ - - uLong pos_local_header; /* offset of the local header of the file - currenty writing */ - char* central_header; /* central header data for the current file */ - uLong size_centralheader; /* size of the central header for cur file */ - uLong flag; /* flag of the file currently writing */ - - int method; /* compression method of file currenty wr.*/ - int raw; /* 1 for directly writing raw data */ - Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ - uLong dosDate; - uLong crc32; - int encrypt; -#ifndef NOCRYPT - unsigned long keys[3]; /* keys defining the pseudo-random sequence */ - const unsigned long* pcrc_32_tab; - int crypt_header_size; -#endif -} curfile_info; - -typedef struct -{ - zlib_filefunc_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - linkedlist_data central_dir;/* datablock with central dir in construction*/ - int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ - curfile_info ci; /* info on the file curretly writing */ - - uLong begin_pos; /* position of the beginning of the zipfile */ - uLong add_position_when_writting_offset; - uLong number_entry; -#ifndef NO_ADDFILEINEXISTINGZIP - char *globalcomment; -#endif -} zip_internal; - - - -#ifndef NOCRYPT -#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED -#include "crypt.h" -#endif - -local linkedlist_datablock_internal* allocate_new_datablock() -{ - linkedlist_datablock_internal* ldi; - ldi = (linkedlist_datablock_internal*) - ALLOC(sizeof(linkedlist_datablock_internal)); - if (ldi!=NULL) - { - ldi->next_datablock = NULL ; - ldi->filled_in_this_block = 0 ; - ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; - } - return ldi; -} - -local void free_datablock(ldi) - linkedlist_datablock_internal* ldi; -{ - while (ldi!=NULL) - { - linkedlist_datablock_internal* ldinext = ldi->next_datablock; - TRYFREE(ldi); - ldi = ldinext; - } -} - -local void init_linkedlist(ll) - linkedlist_data* ll; -{ - ll->first_block = ll->last_block = NULL; -} - -/* -// Never used! -local void free_linkedlist(ll) - linkedlist_data* ll; -{ - free_datablock(ll->first_block); - ll->first_block = ll->last_block = NULL; -} -*/ - -local int add_data_in_datablock(ll,buf,len) - linkedlist_data* ll; - const void* buf; - uLong len; -{ - linkedlist_datablock_internal* ldi; - const unsigned char* from_copy; - - if (ll==NULL) - return ZIP_INTERNALERROR; - - if (ll->last_block == NULL) - { - ll->first_block = ll->last_block = allocate_new_datablock(); - if (ll->first_block == NULL) - return ZIP_INTERNALERROR; - } - - ldi = ll->last_block; - from_copy = (unsigned char*)buf; - - while (len>0) - { - uInt copy_this; - uInt i; - unsigned char* to_copy; - - if (ldi->avail_in_this_block==0) - { - ldi->next_datablock = allocate_new_datablock(); - if (ldi->next_datablock == NULL) - return ZIP_INTERNALERROR; - ldi = ldi->next_datablock ; - ll->last_block = ldi; - } - - if (ldi->avail_in_this_block < len) - copy_this = (uInt)ldi->avail_in_this_block; - else - copy_this = (uInt)len; - - to_copy = &(ldi->data[ldi->filled_in_this_block]); - - for (i=0;ifilled_in_this_block += copy_this; - ldi->avail_in_this_block -= copy_this; - from_copy += copy_this ; - len -= copy_this; - } - return ZIP_OK; -} - - - -/****************************************************************************/ - -#ifndef NO_ADDFILEINEXISTINGZIP -/* =========================================================================== - Inputs a long in LSB order to the given file - nbByte == 1, 2 or 4 (byte, short or long) -*/ - -local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, uLong x, int nbByte)); -local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - uLong x; - int nbByte; -{ - unsigned char buf[4]; - int n; - for (n = 0; n < nbByte; n++) - { - buf[n] = (unsigned char)(x & 0xff); - x >>= 8; - } - if (x != 0) - { /* data overflow - hack for ZIP64 (X Roche) */ - for (n = 0; n < nbByte; n++) - { - buf[n] = 0xff; - } - } - - if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) - return ZIP_ERRNO; - else - return ZIP_OK; -} - -local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte)); -local void ziplocal_putValue_inmemory (dest, x, nbByte) - void* dest; - uLong x; - int nbByte; -{ - unsigned char* buf=(unsigned char*)dest; - int n; - for (n = 0; n < nbByte; n++) { - buf[n] = (unsigned char)(x & 0xff); - x >>= 8; - } - - if (x != 0) - { /* data overflow - hack for ZIP64 */ - for (n = 0; n < nbByte; n++) - { - buf[n] = 0xff; - } - } -} - -/****************************************************************************/ - - -local uLong ziplocal_TmzDateToDosDate(ptm,dosDate) - const tm_zip* ptm; - uLong dosDate; -{ - uLong year = (uLong)ptm->tm_year; - if (year>1980) - year-=1980; - else if (year>80) - year-=80; - return - (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | - ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); -} - - -/****************************************************************************/ - -local int ziplocal_getByte OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - int *pi)); - -local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - int *pi; -{ - unsigned char c; - int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); - if (err==1) - { - *pi = (int)c; - return ZIP_OK; - } - else - { - if (ZERROR(*pzlib_filefunc_def,filestream)) - return ZIP_ERRNO; - else - return ZIP_EOF; - } -} - - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int ziplocal_getShort OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - uLong *pX; -{ - uLong x = 0; - int i = 0; - int err = 0; - - err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==ZIP_OK) - err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==ZIP_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int ziplocal_getLong OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - uLong *pX; -{ - uLong x = 0; - int i = 0; - int err = 0; - - err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==ZIP_OK) - err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==ZIP_OK) - err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<16; - - if (err==ZIP_OK) - err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<24; - - if (err==ZIP_OK) - *pX = x; - else - *pX = 0; - return err; -} - -#ifndef BUFREADCOMMENT -#define BUFREADCOMMENT (0x400) -#endif -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -local uLong ziplocal_SearchCentralDir OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream)); - -local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; -{ - unsigned char* buf; - uLong uSizeFile; - uLong uBackRead; - uLong uMaxBack=0xffff; /* maximum size of global comment */ - uLong uPosFound=0; - - if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); - if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - return uPosFound; -} -#endif /* !NO_ADDFILEINEXISTINGZIP*/ - -/************************************************************/ -extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def) - const char *pathname; - int append; - zipcharpc* globalcomment; - zlib_filefunc_def* pzlib_filefunc_def; -{ - zip_internal ziinit; - zip_internal* zi; - int err=ZIP_OK; - - - if (pzlib_filefunc_def==NULL) - fill_fopen_filefunc(&ziinit.z_filefunc); - else - ziinit.z_filefunc = *pzlib_filefunc_def; - - ziinit.filestream = (*(ziinit.z_filefunc.zopen_file)) - (ziinit.z_filefunc.opaque, - pathname, - (append == APPEND_STATUS_CREATE) ? - (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : - (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); - - if (ziinit.filestream == NULL) - return NULL; - ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream); - ziinit.in_opened_file_inzip = 0; - ziinit.ci.stream_initialised = 0; - ziinit.number_entry = 0; - ziinit.add_position_when_writting_offset = 0; - init_linkedlist(&(ziinit.central_dir)); - - - zi = (zip_internal*)ALLOC(sizeof(zip_internal)); - if (zi==NULL) - { - ZCLOSE(ziinit.z_filefunc,ziinit.filestream); - return NULL; - } - - /* now we add file in a zipfile */ -# ifndef NO_ADDFILEINEXISTINGZIP - ziinit.globalcomment = NULL; - if (append == APPEND_STATUS_ADDINZIP) - { - uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - - uLong size_central_dir; /* size of the central directory */ - uLong offset_central_dir; /* offset of start of central directory */ - uLong central_pos,uL; - - uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ - uLong number_entry; - uLong number_entry_CD; /* total number of entries in - the central dir - (same than number_entry on nospan) */ - uLong size_comment; - - central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream); - if (central_pos==0) - err=ZIP_ERRNO; - - if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, - central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=ZIP_ERRNO; - - /* the signature, already checked */ - if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK) - err=ZIP_ERRNO; - - /* number of this disk */ - if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK) - err=ZIP_ERRNO; - - /* number of the disk with the start of the central directory */ - if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK) - err=ZIP_ERRNO; - - /* total number of entries in the central dir on this disk */ - if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK) - err=ZIP_ERRNO; - - /* total number of entries in the central dir */ - if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK) - err=ZIP_ERRNO; - - if ((number_entry_CD!=number_entry) || - (number_disk_with_CD!=0) || - (number_disk!=0)) - err=ZIP_BADZIPFILE; - - /* size of the central directory */ - if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK) - err=ZIP_ERRNO; - - /* offset of start of central directory with respect to the - starting disk number */ - if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK) - err=ZIP_ERRNO; - - /* zipfile global comment length */ - if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK) - err=ZIP_ERRNO; - - if ((central_pos0) - { - ziinit.globalcomment = ALLOC(size_comment+1); - if (ziinit.globalcomment) - { - size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment); - ziinit.globalcomment[size_comment]=0; - } - } - - byte_before_the_zipfile = central_pos - - (offset_central_dir+size_central_dir); - ziinit.add_position_when_writting_offset = byte_before_the_zipfile; - - { - uLong size_central_dir_to_read = size_central_dir; - size_t buf_size = SIZEDATA_INDATABLOCK; - void* buf_read = (void*)ALLOC(buf_size); - if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, - offset_central_dir + byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET) != 0) - err=ZIP_ERRNO; - - while ((size_central_dir_to_read>0) && (err==ZIP_OK)) - { - uLong read_this = SIZEDATA_INDATABLOCK; - if (read_this > size_central_dir_to_read) - read_this = size_central_dir_to_read; - if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this) - err=ZIP_ERRNO; - - if (err==ZIP_OK) - err = add_data_in_datablock(&ziinit.central_dir,buf_read, - (uLong)read_this); - size_central_dir_to_read-=read_this; - } - TRYFREE(buf_read); - } - ziinit.begin_pos = byte_before_the_zipfile; - ziinit.number_entry = number_entry_CD; - - if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, - offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=ZIP_ERRNO; - } - - if (globalcomment) - { - *globalcomment = ziinit.globalcomment; - } -# endif /* !NO_ADDFILEINEXISTINGZIP*/ - - if (err != ZIP_OK) - { -# ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(ziinit.globalcomment); -# endif /* !NO_ADDFILEINEXISTINGZIP*/ - TRYFREE(zi); - return NULL; - } - else - { - *zi = ziinit; - return (zipFile)zi; - } -} - -extern zipFile ZEXPORT zipOpen (pathname, append) - const char *pathname; - int append; -{ - return zipOpen2(pathname,append,NULL,NULL); -} - -extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting) - zipFile file; - const char* filename; - const zip_fileinfo* zipfi; - const void* extrafield_local; - uInt size_extrafield_local; - const void* extrafield_global; - uInt size_extrafield_global; - const char* comment; - int method; - int level; - int raw; - int windowBits; - int memLevel; - int strategy; - const char* password; - uLong crcForCrypting; -{ - zip_internal* zi; - uInt size_filename; - uInt size_comment; - uInt i; - int err = ZIP_OK; - -# ifdef NOCRYPT - if (password != NULL) - return ZIP_PARAMERROR; -# endif - - if (file == NULL) - return ZIP_PARAMERROR; - if ((method!=0) && (method!=Z_DEFLATED)) - return ZIP_PARAMERROR; - - zi = (zip_internal*)file; - - if (zi->in_opened_file_inzip == 1) - { - err = zipCloseFileInZip (file); - if (err != ZIP_OK) - return err; - } - - - if (filename==NULL) - filename="-"; - - if (comment==NULL) - size_comment = 0; - else - size_comment = (uInt)strlen(comment); - - size_filename = (uInt)strlen(filename); - - if (zipfi == NULL) - zi->ci.dosDate = 0; - else - { - if (zipfi->dosDate != 0) - zi->ci.dosDate = zipfi->dosDate; - else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate); - } - - zi->ci.flag = 0; - if ((level==8) || (level==9)) - zi->ci.flag |= 2; - if ((level==2)) - zi->ci.flag |= 4; - if ((level==1)) - zi->ci.flag |= 6; - if (password != NULL) - zi->ci.flag |= 1; - - zi->ci.crc32 = 0; - zi->ci.method = method; - zi->ci.encrypt = 0; - zi->ci.stream_initialised = 0; - zi->ci.pos_in_buffered_data = 0; - zi->ci.raw = raw; - zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ; - zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + - size_extrafield_global + size_comment; - zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader); - - ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); - /* version info */ - ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2); - ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); - ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); - ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); - ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); - ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ - ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ - ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ - ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); - ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); - ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); - ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ - - if (zipfi==NULL) - ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); - else - ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); - - if (zipfi==NULL) - ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); - else - ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); - - ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4); - - for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); - - for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = - *(((const char*)extrafield_global)+i); - - for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ - size_extrafield_global+i) = *(comment+i); - if (zi->ci.central_header == NULL) - return ZIP_INTERNALERROR; - - /* write the local header */ - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4); - - if (err==ZIP_OK) - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ - if (err==ZIP_OK) - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); - - if (err==ZIP_OK) - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); - - if (err==ZIP_OK) - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); - - if (err==ZIP_OK) - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ - if (err==ZIP_OK) - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ - if (err==ZIP_OK) - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ - - if (err==ZIP_OK) - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); - - if (err==ZIP_OK) - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2); - - if ((err==ZIP_OK) && (size_filename>0)) - if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) - err = ZIP_ERRNO; - - if ((err==ZIP_OK) && (size_extrafield_local>0)) - if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local) - !=size_extrafield_local) - err = ZIP_ERRNO; - - zi->ci.stream.avail_in = (uInt)0; - zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.stream.next_out = zi->ci.buffered_data; - zi->ci.stream.total_in = 0; - zi->ci.stream.total_out = 0; - - if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) - { - zi->ci.stream.zalloc = (alloc_func)0; - zi->ci.stream.zfree = (free_func)0; - zi->ci.stream.opaque = (voidpf)0; - - if (windowBits>0) - windowBits = -windowBits; - - err = deflateInit2(&zi->ci.stream, level, - Z_DEFLATED, windowBits, memLevel, strategy); - - if (err==Z_OK) - zi->ci.stream_initialised = 1; - } -# ifndef NOCRYPT - zi->ci.crypt_header_size = 0; - if ((err==Z_OK) && (password != NULL)) - { - unsigned char bufHead[RAND_HEAD_LEN]; - unsigned int sizeHead; - zi->ci.encrypt = 1; - zi->ci.pcrc_32_tab = get_crc_table(); - /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ - - sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); - zi->ci.crypt_header_size = sizeHead; - - if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) - err = ZIP_ERRNO; - } -# endif - - if (err==Z_OK) - zi->in_opened_file_inzip = 1; - return err; -} - -extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw) - zipFile file; - const char* filename; - const zip_fileinfo* zipfi; - const void* extrafield_local; - uInt size_extrafield_local; - const void* extrafield_global; - uInt size_extrafield_global; - const char* comment; - int method; - int level; - int raw; -{ - return zipOpenNewFileInZip3 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0); -} - -extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level) - zipFile file; - const char* filename; - const zip_fileinfo* zipfi; - const void* extrafield_local; - uInt size_extrafield_local; - const void* extrafield_global; - uInt size_extrafield_global; - const char* comment; - int method; - int level; -{ - return zipOpenNewFileInZip2 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, 0); -} - -local int zipFlushWriteBuffer(zi) - zip_internal* zi; -{ - int err=ZIP_OK; - - if (zi->ci.encrypt != 0) - { -#ifndef NOCRYPT - uInt i; - int t; - for (i=0;ici.pos_in_buffered_data;i++) - zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, - zi->ci.buffered_data[i],t); -#endif - } - if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) - !=zi->ci.pos_in_buffered_data) - err = ZIP_ERRNO; - zi->ci.pos_in_buffered_data = 0; - return err; -} - -extern int ZEXPORT zipWriteInFileInZip (file, buf, len) - zipFile file; - const void* buf; - unsigned len; -{ - zip_internal* zi; - int err=ZIP_OK; - - if (file == NULL) - return ZIP_PARAMERROR; - zi = (zip_internal*)file; - - if (zi->in_opened_file_inzip == 0) - return ZIP_PARAMERROR; - - zi->ci.stream.next_in = (void*)buf; - zi->ci.stream.avail_in = len; - zi->ci.crc32 = crc32(zi->ci.crc32,buf,len); - - while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) - { - if (zi->ci.stream.avail_out == 0) - { - if (zipFlushWriteBuffer(zi) == ZIP_ERRNO) - err = ZIP_ERRNO; - zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.stream.next_out = zi->ci.buffered_data; - } - - - if(err != ZIP_OK) - break; - - if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) - { - uLong uTotalOutBefore = zi->ci.stream.total_out; - err=deflate(&zi->ci.stream, Z_NO_FLUSH); - zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; - - } - else - { - uInt copy_this,i; - if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) - copy_this = zi->ci.stream.avail_in; - else - copy_this = zi->ci.stream.avail_out; - for (i=0;ici.stream.next_out)+i) = - *(((const char*)zi->ci.stream.next_in)+i); - { - zi->ci.stream.avail_in -= copy_this; - zi->ci.stream.avail_out-= copy_this; - zi->ci.stream.next_in+= copy_this; - zi->ci.stream.next_out+= copy_this; - zi->ci.stream.total_in+= copy_this; - zi->ci.stream.total_out+= copy_this; - zi->ci.pos_in_buffered_data += copy_this; - } - } - } - - return err; -} - -extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32) - zipFile file; - uLong uncompressed_size; - uLong crc32; -{ - zip_internal* zi; - uLong compressed_size; - int err=ZIP_OK; - - if (file == NULL) - return ZIP_PARAMERROR; - zi = (zip_internal*)file; - - if (zi->in_opened_file_inzip == 0) - return ZIP_PARAMERROR; - zi->ci.stream.avail_in = 0; - - if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) - while (err==ZIP_OK) - { - uLong uTotalOutBefore; - if (zi->ci.stream.avail_out == 0) - { - if (zipFlushWriteBuffer(zi) == ZIP_ERRNO) - err = ZIP_ERRNO; - zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.stream.next_out = zi->ci.buffered_data; - } - uTotalOutBefore = zi->ci.stream.total_out; - err=deflate(&zi->ci.stream, Z_FINISH); - zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; - } - - if (err==Z_STREAM_END) - err=ZIP_OK; /* this is normal */ - - if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) - if (zipFlushWriteBuffer(zi)==ZIP_ERRNO) - err = ZIP_ERRNO; - - if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) - { - err=deflateEnd(&zi->ci.stream); - zi->ci.stream_initialised = 0; - } - - if (!zi->ci.raw) - { - crc32 = (uLong)zi->ci.crc32; - uncompressed_size = (uLong)zi->ci.stream.total_in; - } - compressed_size = (uLong)zi->ci.stream.total_out; -# ifndef NOCRYPT - compressed_size += zi->ci.crypt_header_size; -# endif - - ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ - ziplocal_putValue_inmemory(zi->ci.central_header+20, - compressed_size,4); /*compr size*/ - if (zi->ci.stream.data_type == Z_ASCII) - ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); - ziplocal_putValue_inmemory(zi->ci.central_header+24, - uncompressed_size,4); /*uncompr size*/ - - if (err==ZIP_OK) - err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header, - (uLong)zi->ci.size_centralheader); - free(zi->ci.central_header); - - if (err==ZIP_OK) - { - long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); - if (ZSEEK(zi->z_filefunc,zi->filestream, - zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) - err = ZIP_ERRNO; - - if (err==ZIP_OK) - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ - - if (err==ZIP_OK) /* compressed size, unknown */ - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); - - if (err==ZIP_OK) /* uncompressed size, unknown */ - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); - - if (ZSEEK(zi->z_filefunc,zi->filestream, - cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) - err = ZIP_ERRNO; - } - - zi->number_entry ++; - zi->in_opened_file_inzip = 0; - - return err; -} - -extern int ZEXPORT zipCloseFileInZip (file) - zipFile file; -{ - return zipCloseFileInZipRaw (file,0,0); -} - -extern int ZEXPORT zipClose (file, global_comment) - zipFile file; - const char* global_comment; -{ - zip_internal* zi; - int err = 0; - uLong size_centraldir = 0; - uLong centraldir_pos_inzip; - uInt size_global_comment; - if (file == NULL) - return ZIP_PARAMERROR; - zi = (zip_internal*)file; - - if (zi->in_opened_file_inzip == 1) - { - err = zipCloseFileInZip (file); - } - -#ifndef NO_ADDFILEINEXISTINGZIP - if (global_comment==NULL) - global_comment = zi->globalcomment; -#endif - if (global_comment==NULL) - size_global_comment = 0; - else - size_global_comment = (uInt)strlen(global_comment); - - centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); - if (err==ZIP_OK) - { - linkedlist_datablock_internal* ldi = zi->central_dir.first_block ; - while (ldi!=NULL) - { - if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) - if (ZWRITE(zi->z_filefunc,zi->filestream, - ldi->data,ldi->filled_in_this_block) - !=ldi->filled_in_this_block ) - err = ZIP_ERRNO; - - size_centraldir += ldi->filled_in_this_block; - ldi = ldi->next_datablock; - } - } - free_datablock(zi->central_dir.first_block); - - if (err==ZIP_OK) /* Magic End */ - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); - - if (err==ZIP_OK) /* number of this disk */ - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); - - if (err==ZIP_OK) /* number of the disk with the start of the central directory */ - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); - - if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); - - if (err==ZIP_OK) /* total number of entries in the central dir */ - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); - - if (err==ZIP_OK) /* size of the central directory */ - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); - - if (err==ZIP_OK) /* offset of start of central directory with respect to the - starting disk number */ - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream, - (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); - - if (err==ZIP_OK) /* zipfile comment length */ - err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); - - if ((err==ZIP_OK) && (size_global_comment>0)) - if (ZWRITE(zi->z_filefunc,zi->filestream, - global_comment,size_global_comment) != size_global_comment) - err = ZIP_ERRNO; - - if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0) - if (err == ZIP_OK) - err = ZIP_ERRNO; - -#ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(zi->globalcomment); -#endif - TRYFREE(zi); - - return err; -} diff --git a/src/server/collision/BoundingIntervalHierarchy.h b/src/server/collision/BoundingIntervalHierarchy.h index 2ee4e207c19..d4d41a66d30 100644 --- a/src/server/collision/BoundingIntervalHierarchy.h +++ b/src/server/collision/BoundingIntervalHierarchy.h @@ -19,11 +19,11 @@ #ifndef _BIH_H #define _BIH_H -#include "Vector3.h" -#include "Ray.h" -#include "AABox.h" +#include "G3D/Vector3.h" +#include "G3D/Ray.h" +#include "G3D/AABox.h" -#include +#include "Define.h" #include #include diff --git a/src/server/collision/CMakeLists.txt b/src/server/collision/CMakeLists.txt index a67cd8d660a..913ec7ecd01 100644 --- a/src/server/collision/CMakeLists.txt +++ b/src/server/collision/CMakeLists.txt @@ -24,13 +24,12 @@ SET(collision_STAT_SRCS include_directories( ${ACE_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/externals/g3dlite - ${CMAKE_SOURCE_DIR}/externals/g3dlite/G3D.lib - ${CMAKE_SOURCE_DIR}/externals/g3dlite/G3D.lib/include - ${CMAKE_SOURCE_DIR}/externals/g3dlite/G3D.lib/include/G3D ${CMAKE_SOURCE_DIR}/src/server/shared ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic ${CMAKE_SOURCE_DIR}/src/server/collision + ${CMAKE_SOURCE_DIR}/src/server/collision/Management ${CMAKE_SOURCE_DIR}/src/server/collision/Maps + ${CMAKE_SOURCE_DIR}/src/server/collision/Models ) add_library(collision STATIC ${collision_STAT_SRCS}) diff --git a/src/server/collision/Management/VMapManager2.h b/src/server/collision/Management/VMapManager2.h index 5f03b87b07f..953a8f11fa7 100644 --- a/src/server/collision/Management/VMapManager2.h +++ b/src/server/collision/Management/VMapManager2.h @@ -20,8 +20,8 @@ #define _VMAPMANAGER2_H #include "IVMapManager.h" -#include "Utilities/UnorderedMap.h" -#include "Platform/Define.h" +#include "Dynamic/UnorderedMap.h" +#include "Define.h" #include //=========================================================== diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp index d01b54a7564..0b9780130ed 100644 --- a/src/server/collision/Maps/TileAssembler.cpp +++ b/src/server/collision/Maps/TileAssembler.cpp @@ -19,7 +19,7 @@ #include "WorldModel.h" #include "TileAssembler.h" #include "MapTree.h" -#include "BIH.h" +#include "BoundingIntervalHierarchy.h" #include "VMapDefinitions.h" #include -- cgit v1.2.3 From 45e2a65fad6549ff93005ff166fba309c20259e0 Mon Sep 17 00:00:00 2001 From: click Date: Fri, 9 Jul 2010 18:02:46 +0200 Subject: Update VMap3 to "final" release (REEXTRACTION OF MAPS/VMAPS IS REQUIRED!) - thanks to Lynx3d (again) - add magic-header to .vmtile files - calculate waterlevels for non-flat surfaces in a more correct way - make MSVC shut up about float-issues - change logging around a bit (output function that the respective logentry comes from) - remove remaining Stormlib leftovers - set indoor/outdoor check to enabled by default (more blizzlike) --HG-- branch : trunk --- src/server/collision/Management/VMapManager2.cpp | 32 ++++++------ src/server/collision/Maps/MapTree.cpp | 64 ++++++++++++++---------- src/server/collision/Maps/MapTree.h | 1 + src/server/collision/Maps/TileAssembler.cpp | 28 ++++++----- src/server/collision/Models/ModelInstance.cpp | 23 +++++---- src/server/collision/Models/WorldModel.cpp | 63 +++++++++++++++++------ src/server/collision/VMapDefinitions.h | 22 ++++---- src/server/worldserver/worldserver.conf.dist | 6 +-- src/tools/vmap3_assembler/VMapAssembler.cpp | 4 +- src/tools/vmap3_extractor/dbcfile.h | 22 ++++++-- src/tools/vmap3_extractor/vmapexport.cpp | 2 +- 11 files changed, 165 insertions(+), 102 deletions(-) (limited to 'src/server/collision/Maps/TileAssembler.cpp') diff --git a/src/server/collision/Management/VMapManager2.cpp b/src/server/collision/Management/VMapManager2.cpp index 1936ba6ebba..61b202c9342 100644 --- a/src/server/collision/Management/VMapManager2.cpp +++ b/src/server/collision/Management/VMapManager2.cpp @@ -1,19 +1,19 @@ /* + * Copyright (C) 2008-2010 TrinityCore * Copyright (C) 2005-2010 MaNGOS * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . */ #include @@ -57,7 +57,7 @@ namespace VMAP Vector3 VMapManager2::convertPositionToInternalRep(float x, float y, float z) const { Vector3 pos; - const float mid = 0.5 * 64.0 * 533.33333333f; + const float mid = 0.5f * 64.0f * 533.33333333f; pos.x = mid - x; pos.y = mid - y; pos.z = z; @@ -70,7 +70,7 @@ namespace VMAP Vector3 VMapManager2::convertPositionToMangosRep(float x, float y, float z) const { Vector3 pos; - const float mid = 0.5 * 64.0 * 533.33333333f; + const float mid = 0.5f * 64.0f * 533.33333333f; pos.x = mid - x; pos.y = mid - y; pos.z = z; @@ -301,11 +301,11 @@ namespace VMAP WorldModel *worldmodel = new WorldModel(); if (!worldmodel->readFile(basepath + filename + ".vmo")) { - sLog.outError("VMapManager2: could not load '%s%s.vmo'!", basepath.c_str(), filename.c_str()); + sLog.outError("VMapManager2: could not load '%s%s.vmo'", basepath.c_str(), filename.c_str()); delete worldmodel; return NULL; } - sLog.outDebug("VMapManager2: loading file '%s%s'.", basepath.c_str(), filename.c_str()); + sLog.outDebug("VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str()); model = iLoadedModelFiles.insert(std::pair(filename, ManagedModel())).first; model->second.setModel(worldmodel); } @@ -318,7 +318,7 @@ namespace VMAP ModelFileMap::iterator model = iLoadedModelFiles.find(filename); if (model == iLoadedModelFiles.end()) { - sLog.outError("VMapManager2: trying to unload non-loaded file '%s'!", filename.c_str()); + sLog.outError("VMapManager2: trying to unload non-loaded file '%s'", filename.c_str()); return; } if( model->second.decRefCount() == 0) diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp index af92ec37ae7..e758581e2f8 100644 --- a/src/server/collision/Maps/MapTree.cpp +++ b/src/server/collision/Maps/MapTree.cpp @@ -1,19 +1,19 @@ /* + * Copyright (C) 2008-2010 TrinityCore * Copyright (C) 2005-2010 MaNGOS * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . */ #include "MapTree.h" @@ -57,7 +57,7 @@ namespace VMAP void operator()(const Vector3& point, uint32 entry) { #ifdef VMAP_DEBUG - sLog.outDebug("trying to intersect '%s'", prims[entry].name.c_str()); + sLog.outDebug("AreaInfoCallback: trying to intersect '%s'", prims[entry].name.c_str()); #endif prims[entry].intersectPoint(point, aInfo); } @@ -73,7 +73,7 @@ namespace VMAP void operator()(const Vector3& point, uint32 entry) { #ifdef VMAP_DEBUG - sLog.outDebug("trying to intersect '%s'", prims[entry].name.c_str()); + sLog.outDebug("LocationInfoCallback: trying to intersect '%s'", prims[entry].name.c_str()); #endif if (prims[entry].GetLocationInfo(point, locInfo)) result = true; @@ -121,7 +121,7 @@ namespace VMAP } StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath): - iMapID(mapID), /* iTree(0), */ iTreeValues(0), iBasePath(basePath) + iMapID(mapID), iTreeValues(0), iBasePath(basePath) { if (iBasePath.length() > 0 && (iBasePath[iBasePath.length()-1] != '/' || iBasePath[iBasePath.length()-1] != '\\')) { @@ -260,7 +260,11 @@ namespace VMAP if (!tf) success = false; else + { + if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) + success = false; fclose(tf); + } } fclose(rf); return success; @@ -270,7 +274,7 @@ namespace VMAP bool StaticMapTree::InitMap(const std::string &fname, VMapManager2 *vm) { - sLog.outDebug("Initializing StaticMapTree '%s'", fname.c_str()); + sLog.outDebug("StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str()); bool success = true; std::string fullname = iBasePath + fname; FILE *rf = fopen(fullname.c_str(), "rb"); @@ -298,12 +302,12 @@ namespace VMAP // only non-tiled maps have them, and if so exactly one (so far at least...) ModelSpawn spawn; #ifdef VMAP_DEBUG - sLog.outDebug("Map isTiled: %u", static_cast(iIsTiled)); + sLog.outDebug("StaticMapTree::InitMap() : map isTiled: %u", static_cast(iIsTiled)); #endif if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn)) { WorldModel *model = vm->acquireModelInstance(iBasePath, spawn.name); - sLog.outDebug("StaticMapTree::InitMap(): loading %s", spawn.name.c_str()); + sLog.outDebug("StaticMapTree::InitMap() : loading %s", spawn.name.c_str()); if (model) { // assume that global model always is the first and only tree value (could be improved...) @@ -313,7 +317,7 @@ namespace VMAP else { success = false; - sLog.outError("Could not acquire WorldModel pointer!"); + sLog.outError("StaticMapTree::InitMap() : could not acquire WorldModel pointer for '%s'", spawn.name.c_str()); } } @@ -349,7 +353,7 @@ namespace VMAP } if (!iTreeValues) { - sLog.outError("Tree has not been initialized! [%u,%u]", tileX, tileY); + sLog.outError("StaticMapTree::LoadMapTile() : tree has not been initialized [%u,%u]", tileX, tileY); return false; } bool result = true; @@ -358,8 +362,12 @@ namespace VMAP FILE* tf = fopen(tilefile.c_str(), "rb"); if (tf) { + char chunk[8]; + + if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) + result = false; uint32 numSpawns; - if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1) + if (result && fread(&numSpawns, sizeof(uint32), 1, tf) != 1) result = false; for (uint32 i=0; iacquireModelInstance(iBasePath, spawn.name); if (!model) - sLog.outError("error: could not acquire WorldModel pointer! [%u,%u]", tileX, tileY); + sLog.outError("StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u,%u]", tileX, tileY); // update tree uint32 referencedVal; @@ -382,7 +390,7 @@ namespace VMAP #ifdef VMAP_DEBUG if (referencedVal > iNTreeValues) { - sLog.outDebug("invalid tree element! (%u/%u)", referencedVal, iNTreeValues); + sLog.outDebug("StaticMapTree::LoadMapTile() : invalid tree element (%u/%u)", referencedVal, iNTreeValues); continue; } #endif @@ -394,9 +402,9 @@ namespace VMAP ++iLoadedSpawns[referencedVal]; #ifdef VMAP_DEBUG if (iTreeValues[referencedVal].ID != spawn.ID) - sLog.outDebug("error: trying to load wrong spawn in node!"); + sLog.outDebug("StaticMapTree::LoadMapTile() : trying to load wrong spawn in node"); else if (iTreeValues[referencedVal].name != spawn.name) - sLog.outDebug("error: name collision on GUID=%u", spawn.ID); + sLog.outDebug("StaticMapTree::LoadMapTile() : name collision on GUID=%u", spawn.ID); #endif } } @@ -417,7 +425,7 @@ namespace VMAP loadedTileMap::iterator tile = iLoadedTiles.find(tileID); if (tile == iLoadedTiles.end()) { - sLog.outError("WARNING: trying to unload non-loaded tile. Map:%u X:%u Y:%u", iMapID, tileX, tileY); + sLog.outError("StaticMapTree::UnloadMapTile() : trying to unload non-loaded tile - Map:%u X:%u Y:%u", iMapID, tileX, tileY); return; } if (tile->second) // file associated with tile @@ -427,6 +435,9 @@ namespace VMAP if (tf) { bool result=true; + char chunk[8]; + if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) + result = false; uint32 numSpawns; if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1) result = false; @@ -446,11 +457,10 @@ namespace VMAP fread(&referencedNode, sizeof(uint32), 1, tf); if (!iLoadedSpawns.count(referencedNode)) { - sLog.outError("Trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID); + sLog.outError("StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID); } else if (--iLoadedSpawns[referencedNode] == 0) { - //std::cout << "MapTree: removing '" << spawn.name << "' from tree\n"; iTreeValues[referencedNode].setUnloaded(); iLoadedSpawns.erase(referencedNode); } diff --git a/src/server/collision/Maps/MapTree.h b/src/server/collision/Maps/MapTree.h index 7a7af43e949..f9c51d47b95 100644 --- a/src/server/collision/Maps/MapTree.h +++ b/src/server/collision/Maps/MapTree.h @@ -22,6 +22,7 @@ #include "Define.h" #include "Dynamic/UnorderedMap.h" #include "BoundingIntervalHierarchy.h" +#include "Log.h" namespace VMAP { diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp index 0b9780130ed..c6798e70cc4 100644 --- a/src/server/collision/Maps/TileAssembler.cpp +++ b/src/server/collision/Maps/TileAssembler.cpp @@ -1,19 +1,19 @@ /* + * Copyright (C) 2008-2010 TrinityCore * Copyright (C) 2005-2010 MaNGOS * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . */ #include "WorldModel.h" @@ -82,6 +82,7 @@ namespace VMAP // build global map tree std::vector mapSpawns; UniqueEntryMap::iterator entry; + printf("Calculating model bounds for map %u...\n", map_iter->first); for (entry = map_iter->second->UniqueEntries.begin(); entry != map_iter->second->UniqueEntries.end(); ++entry) { // M2 models don't have a bound set in WDT/ADT placement data, i still think they're not used for LoS at all on retail @@ -100,6 +101,7 @@ namespace VMAP spawnedModelFiles.insert(entry->second.name); } + printf("Creating map tree...\n", map_iter->first); BIH pTree; pTree.build(mapSpawns, BoundsTrait::getBounds); @@ -107,8 +109,6 @@ namespace VMAP std::map modelNodeIdx; for (uint32 i=0; i(mapSpawns[i]->ID, i)); - if (!modelNodeIdx.empty()) - printf("min GUID: %u, max GUID: %u\n", modelNodeIdx.begin()->first, modelNodeIdx.rbegin()->first); // write map tree file std::stringstream mapfilename; @@ -158,6 +158,8 @@ namespace VMAP StaticMapTree::unpackTileID(tile->first, x, y); tilefilename << std::setw(2) << x << "_" << std::setw(2) << y << ".vmtile"; FILE *tilefile = fopen(tilefilename.str().c_str(), "wb"); + // file header + if (success && fwrite(VMAP_MAGIC, 1, 8, tilefile) != 8) success = false; // write number of tile spawns if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false; // write tile spawns diff --git a/src/server/collision/Models/ModelInstance.cpp b/src/server/collision/Models/ModelInstance.cpp index 677a08e147a..af32d4026e7 100644 --- a/src/server/collision/Models/ModelInstance.cpp +++ b/src/server/collision/Models/ModelInstance.cpp @@ -1,24 +1,25 @@ /* + * Copyright (C) 2008-2010 TrinityCore * Copyright (C) 2005-2010 MaNGOS * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . */ #include "ModelInstance.h" #include "WorldModel.h" #include "MapTree.h" +#include "VMapDefinitions.h" using G3D::Vector3; using G3D::Ray; diff --git a/src/server/collision/Models/WorldModel.cpp b/src/server/collision/Models/WorldModel.cpp index 690c77577ae..0bd156fedc2 100644 --- a/src/server/collision/Models/WorldModel.cpp +++ b/src/server/collision/Models/WorldModel.cpp @@ -1,19 +1,19 @@ /* + * Copyright (C) 2008-2010 TrinityCore * Copyright (C) 2005-2010 MaNGOS * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . */ #include "WorldModel.h" @@ -148,15 +148,48 @@ namespace VMAP bool WmoLiquid::GetLiquidHeight(const Vector3 &pos, float &liqHeight) const { - uint32 tx = (pos.x - iCorner.x)/LIQUID_TILE_SIZE; + float tx_f = (pos.x - iCorner.x)/LIQUID_TILE_SIZE; + uint32 tx = uint32(tx_f); if (tx<0 || tx >= iTilesX) return false; - uint32 ty = (pos.y - iCorner.y)/LIQUID_TILE_SIZE; + float ty_f = (pos.y - iCorner.y)/LIQUID_TILE_SIZE; + uint32 ty = uint32(ty_f); if (ty<0 || ty >= iTilesY) return false; + + // check if tile shall be used for liquid level // checking for 0x08 *might* be enough, but disabled tiles always are 0x?F: if ((iFlags[tx + ty*iTilesX] & 0x0F) == 0x0F) return false; - //placeholder...use only lower left corner vertex - liqHeight = /* iCorner.z + */ iHeight[tx + ty*(iTilesX+1)]; + + // (dx, dy) coordinates inside tile, in [0,1]^2 + float dx = tx_f - (float)tx; + float dy = ty_f - (float)ty; + + /* Tesselate tile to two triangles (not sure if client does it exactly like this) + + ^ dy + | + 1 x---------x (1,1) + | (b) / | + | / | + | / | + | / (a) | + x---------x---> dx + 0 1 + */ + + const uint32 rowOffset = iTilesX + 1; + if (dx > dy) // case (a) + { + float sx = iHeight[tx+1 + ty * rowOffset] - iHeight[tx + ty * rowOffset]; + float sy = iHeight[tx+1 + (ty+1) * rowOffset] - iHeight[tx+1 + ty * rowOffset]; + liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy; + } + else // case (b) + { + float sx = iHeight[tx+1 + (ty+1) * rowOffset] - iHeight[tx + (ty+1) * rowOffset]; + float sy = iHeight[tx + (ty+1) * rowOffset] - iHeight[tx + ty * rowOffset]; + liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy; + } return true; } diff --git a/src/server/collision/VMapDefinitions.h b/src/server/collision/VMapDefinitions.h index e4a34cc1397..5f4a976ed2a 100644 --- a/src/server/collision/VMapDefinitions.h +++ b/src/server/collision/VMapDefinitions.h @@ -1,19 +1,19 @@ /* + * Copyright (C) 2008-YYYY TrinityCore * Copyright (C) 2005-2010 MaNGOS * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . */ #ifndef _VMAPDEFINITIONS_H diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 3b6d20e093d..b78d8b363cd 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -177,7 +177,7 @@ EAIErrorLevel = 2 # # vmap.enableIndoorCheck # Enable/Disable VMap based indoor check to remove outdoor-only auras (mounts etc.) -# Default: 0 (disabled) +# Default: 1 (enabled) # # DetectPosCollision # Check final move position, summon position, etc for visible collision @@ -244,10 +244,10 @@ PlayerSave.Stats.MinLevel = 0 PlayerSave.Stats.SaveOnlyOnLogout = 1 vmap.enableLOS = 0 vmap.enableHeight = 0 -vmap.ignoreMapIds = "369" +vmap.ignoreMapIds = "" vmap.ignoreSpellIds = "7720" vmap.petLOS = 0 -vmap.enableIndoorCheck = 0 +vmap.enableIndoorCheck = 1 DetectPosCollision = 1 TargetPosRecalculateRange = 1.5 UpdateUptimeInterval = 10 diff --git a/src/tools/vmap3_assembler/VMapAssembler.cpp b/src/tools/vmap3_assembler/VMapAssembler.cpp index 6666b54356c..d714db5ae45 100644 --- a/src/tools/vmap3_assembler/VMapAssembler.cpp +++ b/src/tools/vmap3_assembler/VMapAssembler.cpp @@ -76,11 +76,13 @@ A '#' at the beginning of a line defines a comment return(result); } */ //======================================================= + int main(int argc, char* argv[]) { if(argc != 3 && argc != 4) { - printf("\nusage: %s [config file name]\n", argv[0]); + //printf("\nusage: %s [config file name]\n", argv[0]); + printf("\nusage: %s \n", argv[0]); return 1; } diff --git a/src/tools/vmap3_extractor/dbcfile.h b/src/tools/vmap3_extractor/dbcfile.h index 7381ab9f668..d405d6ffd60 100644 --- a/src/tools/vmap3_extractor/dbcfile.h +++ b/src/tools/vmap3_extractor/dbcfile.h @@ -1,13 +1,27 @@ +/* + * Copyright (C) 2008-2010 TrinityCore + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + #ifndef DBCFILE_H #define DBCFILE_H -#define __STORMLIB_SELF__ #include #include -//#include "StormLib.h" -#undef min -#undef max class DBCFile { public: diff --git a/src/tools/vmap3_extractor/vmapexport.cpp b/src/tools/vmap3_extractor/vmapexport.cpp index 82e9bd7cc7b..b82f9249f07 100644 --- a/src/tools/vmap3_extractor/vmapexport.cpp +++ b/src/tools/vmap3_extractor/vmapexport.cpp @@ -435,7 +435,7 @@ bool processArgv(int argc, char ** argv, const char *versionString) int main(int argc, char ** argv) { bool success=true; - const char *versionString = "V2.90 2010_05"; + const char *versionString = "V3.00 2010_07"; // Use command line arguments, when some if(!processArgv(argc, argv, versionString)) -- cgit v1.2.3