diff --git a/externals/PackageList.txt b/externals/PackageList.txt
index 52341a01cd..168d042898 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/Discovery.h b/externals/g3dlite/G3D.lib/include/G3D/Discovery.h
deleted file mode 100644
index acd1c2c01d..0000000000
--- 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/source/AABox.cpp b/externals/g3dlite/G3D.lib/source/AABox.cpp
deleted file mode 100644
index 9e871aa8af..0000000000
--- 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 45fb41df53..0000000000
--- 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 a30ec0644e..0000000000
--- 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 65a9976fe0..0000000000
--- 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 8fcc30e548..0000000000
--- 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 4b6c56388e..0000000000
--- 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 fbcb56fe97..0000000000
--- 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 16650bc1a9..0000000000
--- 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 7e058a27d1..0000000000
--- 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 0fd00693d4..0000000000
--- 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 8183d8a0f6..0000000000
--- 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 837bf1b2c8..0000000000
--- 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 ed2e91291a..0000000000
--- 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 8c8636a742..0000000000
--- 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 99b29b5b0a..0000000000
--- 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 76dbe21a7c..0000000000
--- 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 b6e94fe585..0000000000
--- 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 09aee2c265..0000000000
--- 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 4aa24c39f9..0000000000
--- 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 bdc7d56be2..0000000000
--- 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 2c27c5bf2b..0000000000
--- 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 e70188377e..0000000000
--- 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 c7abf98255..0000000000
--- 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 16499af15f..0000000000
--- 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 598ba730d0..0000000000
--- 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 fe2812cf3b..0000000000
--- 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 9fd6a743e8..0000000000
--- 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 bfe5c8305e..0000000000
--- 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 d84feedecc..0000000000
--- 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 8acb066ef5..0000000000
--- 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 090370436c..0000000000
--- 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 25c757b70e..0000000000
--- 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 30841d01c6..0000000000
--- 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 c43e7194d7..0000000000
--- 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 aa2ac6098d..0000000000
--- 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 2de32b6009..0000000000
--- 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 84a1cd650b..0000000000
--- 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 dee1cba14b..0000000000
--- 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 3cbf6ad711..0000000000
--- 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 9cbc4edcb3..0000000000
--- 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