Merge branch 'master' of github.com:hrydgard/native

This commit is contained in:
Henrik Rydgard 2012-03-27 23:54:35 +02:00
commit 0a154b548e
14 changed files with 44208 additions and 393 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
Release
Debug
*.vcxproj.user

View File

@ -3,8 +3,23 @@ native
This is my library of stuff that I use when writing C++ programs, mostly for Android. It has some basic OpenGL utility code, JSON read/write (two libraries that should be made more similar), 2D texture atlases and drawing code, ETC1 texture loading support, basic logging, etc. The associated tools to create ZIM texture files and atlases do not yet live here but I might move them here eventually.
This project incorporates code from a variety of public domain or similarly-licensed code. This is the list:
etcpack by Ericsson, in a cleaned up form. public domain?
sha1, public domain implementation by Dominik Reichl
json_writer by me (Henrik Rydgård)
vjson in a heavily modified form, originally by ??? (TODO)
libzip with attribution "Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner"
stb_vorbis, public domain by Sean Barrett of RAD Tools
If you're not okay with the licenses above, don't use this code.
If you find this useful for your own projects, drop me a line at hrydgard@gmail.com .
I hereby release this code under the BSD license.
I hereby release all code here not under the licenses above to the public domain.
Henrik Rydgård

View File

@ -1,9 +0,0 @@
set(SRCS
collision.cpp
)
add_library(collision STATIC ${SRCS})
if(UNIX)
add_definitions(-fPIC)
endif(UNIX)

View File

@ -1,288 +0,0 @@
#include "base/logging.h"
#include "math/lin/vec3.h"
#include "ray_intersections.h"
#include "collision.h"
#include <string>
// #define COLLISION_ENABLE_SCALING
static std::string V(const Vec3 &v) {
char temp[100];
sprintf(temp, "(%f %f %f)", v.x, v.y, v.z);
return std::string(temp);
}
Collidable::Collidable() {
}
Collidable::~Collidable() {
}
void Collision::Init(const Vec3 &source, const Vec3 &dest, const Vec3 &size) {
this->size = size;
scale.Set(1.0f / size.x, 1.0f / size.y, 1.0f / size.z);
sourcePoint = source.scaledBy(scale);
velocity = (dest - source).scaledBy(scale);
velocityLength = velocity.length();
normalizedVelocity = velocity / velocityLength;
stuck = false;
foundCollision = false;
nearestDistance = velocityLength;
}
void Collision::BeginTransform(const Matrix4x4 &inverse, const Matrix4x4 &transform) {
this->transform = &transform;
untransformed_sourcePoint = sourcePoint;
untransformed_velocity = velocity;
sourcePoint = sourcePoint * inverse;
velocity = velocity.rotatedBy(inverse);
normalizedVelocity = untransformed_velocity.normalized();
}
void Collision::EndTransform() {
sourcePoint = untransformed_sourcePoint;
velocity = untransformed_velocity;
normalizedVelocity = untransformed_velocity.normalized();
this->transform = 0;
}
bool Collision::registerCollision(float t, const Vec3 &polyIPoint) {
// Special handling for multiple contact points
if (t < 0.0f) {
return false;
}
Vec3 ipoint;
if (transform) ipoint = polyIPoint * (*transform);
else ipoint = polyIPoint;
if (t >= -0.0001 && t <= 0.0001 && num_contact_points < MAX_CONTACT_POINTS) {
for (int i = 0; i < num_contact_points; i++) {
// Check if identical - can happen on dupe edges (which we'll later remove).
// TODO: Let's see if we can get rid of this fuzziness.
if (ipoint.distance2To(contact_points[i]) < 0.00001)
goto skip;
}
contact_points[num_contact_points++] = ipoint;
}
skip:
if ((t >= 0.0) && (t <= velocityLength) && (t <= this->nearestDistance)) {
// If we are hit we have a closest hit so far. We save the information
this->nearestDistance = t;
this->nearestPolygonIntersectionPoint = ipoint;
this->foundCollision = true;
//ILOG("Collision registered, t=%f", t);
return true;
} else {
// Already had a closer collision.
return false;
}
}
bool Collision::Triangle(Vec3 p1, Vec3 p2, Vec3 p3) {
Vec3 pNormal = (p2 - p1) % (p3 - p1);
pNormal.normalize();
return Triangle(p1, p2, p3, pNormal);
}
bool Collision::Triangle(Vec3 p1, Vec3 p2, Vec3 p3, const Vec3 &pNormal) {
#ifdef COLLISION_ENABLE_SCALING
p1.scaleBy(scale);
p2.scaleBy(scale);
p3.scaleBy(scale);
#endif
// Backface
// Early out optimization, lose a square root
if (dot(velocity, pNormal) >= 0.0f)
return false;
// ILOG("normal. %s", V(pNormal).c_str());
// find the plane intersection point
float t;
Vec3 polyIPoint, sIPoint = sourcePoint - pNormal;
if (pointPlaneDistance(sIPoint, p1, pNormal) > 0.0f) {
// Plane is embedded in ellipsoid.
// Find plane intersection point by shooting a ray from the sphere intersection
// point along the plane normal.
t = intersectRayPlanePerp(sIPoint, pNormal, p1);
polyIPoint = sIPoint + pNormal * t; // calculate plane intersection point
} else {
// shoot ray along the velocity vector
t = intersectRayPlane(sIPoint, normalizedVelocity, p1, pNormal);
if (t > velocityLength) {
// Did not hit plane. No point in doing triangle tests.
return false;
}
// calculate plane intersection point
polyIPoint = sIPoint + normalizedVelocity * t;
}
if (isPointInTriangle(polyIPoint, p1, p2, p3)) {
// ILOG("Hit triangle! %s %s %s %s", V(polyIPoint).c_str(), V(p1).c_str(), V(p2).c_str(), V(p3).c_str());
float depth2 = (polyIPoint - sourcePoint).length2();
if (depth2 < 0.9999f) {
// Here we do the error checking to see if we got ourself stuck last frame
ELOG("Stuck in triangle! depth2 = %f", depth2);
// ILOG("%s %s %s", V(p1).c_str(), V(p2).c_str(), V(p3).c_str());
stuck = true;
}
return registerCollision(t, polyIPoint);
} else {
// ILOG("Missed this triangle - returning");
return false;
}
}
bool Collision::EdgeLine(Vec3 p1, Vec3 p2) {
// This ellipsoid scaling stuff will result in the edge not being really cylindric.
// Should work for many purposes though.
#ifdef COLLISION_ENABLE_SCALING
p1.scaleBy(scale);
p2.scaleBy(scale);
#endif
float t = 1000000000.0;
Vec3 polyIPoint;
if (intersectCylinder(sourcePoint, normalizedVelocity,
p1, p2, &t, &polyIPoint)) {
polyIPoint = closestPointOnLine(p1, p2, polyIPoint);
return registerCollision(t, polyIPoint);
} else {
return false;
}
}
bool Collision::Corner(Vec3 p1) {
#ifdef COLLISION_ENABLE_SCALING
p1.scaleBy(scale);
#endif
float t = intersectRayUnitSphere(sourcePoint, normalizedVelocity, p1);
if (t != -1.0f) {
return registerCollision(t, p1);
} else {
return false;
}
}
bool Collision::Quad(const Vec3 &o, const Vec3 &dx, const Vec3 &dy) {
bool hit = Triangle(o, o + dx, o + dx + dy);
hit |= Triangle(o + dx + dy, o + dy, o);
return hit;
}
bool Collide(Collision *collision, Collidable *scene, Vec3 *out) {
bool hit_anything = false;
collision->num_contact_points = 0;
collision->lastSafePosition = collision->sourcePoint;
// Process max 8 slides to have a limit if we get into an impossible situation.
int i = 0;
for (i = 0; i < 4; i++) {
// ILOG("Try %i! %s", i, V(collision->sourcePoint).c_str());
scene->Collide(collision);
if (!collision->foundCollision) {
// Nothing left to do.
collision->sourcePoint += collision->velocity;
collision->velocity.setZero();
break;
}
hit_anything = true;
if (collision->nearestDistance < 0.0f) {
ILOG("NegHit! %f %f", collision->velocityLength, collision->nearestDistance);
} else {
// ILOG("Hit! %f %f ", collision->velocityLength, collision->nearestDistance);
}
Vec3 slidePlaneOrigin;
Vec3 slidePlaneNormal;
Vec3 newSourcePoint = collision->sourcePoint;
float adjusted_hit_distance = collision->nearestDistance - 0.0001f;
if (adjusted_hit_distance < 0) adjusted_hit_distance = 0;
// Two cases - one where we have multiple contact points, one where we don't.
if (collision->num_contact_points > 1) {
ILOG("Resolve %i-ary collision, velocityLength = %f",
collision->num_contact_points, collision->velocity.length());
Vec3 avg_contact(0,0,0);
for (int i = 0; i < collision->num_contact_points; i++) {
ILOG("Contact point %s", V(collision->contact_points[i]).c_str());
avg_contact += collision->contact_points[i];
}
avg_contact /= (float)collision->num_contact_points;
// The average of the contact points should be inside the sphere.
float dist = sqrt(avg_contact.distance2To(collision->sourcePoint));
if (dist > 1.0) {
ILOG("Bogus contact points, for sure: %s vs %s, dist=%f", V(avg_contact).c_str(), V(collision->sourcePoint).c_str(), dist);
}
Vec3 avg_contact_dir = avg_contact - collision->sourcePoint;
avg_contact_dir.normalize();
avg_contact = collision->sourcePoint + avg_contact_dir;
newSourcePoint += collision->normalizedVelocity * adjusted_hit_distance;
slidePlaneOrigin = avg_contact;
slidePlaneNormal = (newSourcePoint - slidePlaneOrigin).normalized();
// Push the ball out a bit along the normal to avoid re-collision.
newSourcePoint += slidePlaneNormal * 0.01f;
//collision->velocity += slidePlaneNormal * 0.01;
//slidePlaneNormal = avg_contact_dir;
} else {
// LOG(INFO) << "Adjusting newsourcepoint to end of collision";
newSourcePoint += collision->normalizedVelocity * adjusted_hit_distance;
// LOG(INFO) << "s: " << V(collision->sourcePoint);
// LOG(INFO) << "nsp: " << V(newSourcePoint);
// LOG(INFO) << "ip: " << V(collision->nearestPolygonIntersectionPoint);
// Now we must calculate the sliding plane
slidePlaneOrigin = collision->nearestPolygonIntersectionPoint;
slidePlaneNormal = (newSourcePoint - slidePlaneOrigin).normalized();
}
// We now project the destination point onto the sliding plane
Vec3 destinationPoint = collision->sourcePoint + collision->velocity;
float l = intersectRayPlane(destinationPoint, slidePlaneNormal,
slidePlaneOrigin, -slidePlaneNormal);
// We can now calculate a new destination point on the sliding plane
Vec3 newDestinationPoint = destinationPoint + slidePlaneNormal * l;
// now we start over with the new position and velocity
collision->sourcePoint = newSourcePoint;
// Generate the slide vector, which will become our new velocity vector
Vec3 slide = newDestinationPoint - slidePlaneOrigin;
slide += slidePlaneNormal * 0.0001f;
// LOG(INFO) << "NDP: " << V(newDestinationPoint);
// ILOG("Slide: %s", V(slide).c_str());
// Recompute to get ready!
collision->velocity = slide;
collision->velocityLength = collision->velocity.length();
if (collision->velocityLength <= 0.0002) {
//ILOG("Zero-length velocity vector. Break.");
collision->velocity.setZero();
break;
} else {
// ILOG("Velocity: %s", V(collision->velocity).c_str());
}
collision->nearestDistance = collision->velocityLength;
collision->normalizedVelocity = collision->velocity / collision->velocityLength;
}
//ILOG("%i tries", i);
*out = collision->sourcePoint.scaledBy(collision->size);
if (collision->stuck) {
//ILOG("Stuck - resetting");
// *out = collision->lastSafePosition.scaledBy(collision->size);
}
return hit_anything;
}

View File

@ -1,89 +0,0 @@
// Collision detection engine. You pass in a class representing a scene,
// and out comes a nice FPS-like "sliding physics" response.
// By hrydgard@gmail.com,
#ifndef _COLLISION_H
#define _COLLISION_H
#include "math/lin/vec3.h"
#include "math/lin/matrix4x4.h"
class Collision;
class Collidable {
public:
Collidable();
virtual ~Collidable();
// Apply the collision functions to collision as appropriate.
virtual void Collide(Collision *collision) = 0;
};
class Collision {
public:
void Init(const Vec3 &source, const Vec3 &dest, const Vec3 &size);
// Collision functions
// These should be called from Collidable::Collide and nowhere else
// except the unit test.
// To correctly collide with meshes, just apply these in sequence. You MUST
// collide against all external (convex) edges, otherwise you can get
// quite stuck. There's PLENTY of optimization to do here.
bool Triangle(Vec3 p1, Vec3 p2, Vec3 p3);
bool Triangle(Vec3 p1, Vec3 p2, Vec3 p3, const Vec3 &normal);
bool EdgeLine(Vec3 p1, Vec3 p2); // Cylinder
bool Quad(const Vec3 &origin, const Vec3 &dX, const Vec3 &dY);
bool UnitCube(const Vec3 &origin);
bool Corner(Vec3 p1); // Sphere
bool Corners(Vec3 *p, int count);
// There's an opportunity to provide hyper optimized versions of
// Edge for axis aligned edges. The cylinder intersection becomes trivial.
// These cannot be nested!
void BeginTransform(const Matrix4x4 &inverse, const Matrix4x4 &transform);
void EndTransform();
private:
bool registerCollision(float t, const Vec3 &polyIPoint);
public:
Vec3 sourcePoint;
float velocityLength;
Vec3 size;
Vec3 scale;
Vec3 velocity; // data about player movement
Vec3 normalizedVelocity;
Vec3 lastSafePosition; // for error handling
bool stuck;
// data for collision response
bool foundCollision;
float nearestDistance; // nearest distance to hit
Vec3 nearestPolygonIntersectionPoint; // on polygon
const Matrix4x4 *transform;
// Saved state during transformed operation
Vec3 untransformed_sourcePoint;
Vec3 untransformed_velocity;
enum {
MAX_CONTACT_POINTS = 10
};
Vec3 contact_points[MAX_CONTACT_POINTS];
int num_contact_points;
};
// Sliding physics.
bool Collide(Collision *collision, Collidable *scene, Vec3 *out);
// Bouncy physics
// void CollideBouncy( ... )
#endif // _COLLISION_H

15507
ext/glew/GL/glew.h Normal file

File diff suppressed because it is too large Load Diff

1568
ext/glew/GL/glxew.h Normal file

File diff suppressed because it is too large Load Diff

1361
ext/glew/GL/wglew.h Normal file

File diff suppressed because it is too large Load Diff

15485
ext/glew/glew.c Normal file

File diff suppressed because it is too large Load Diff

9081
ext/glew/glewinfo.c Normal file

File diff suppressed because it is too large Load Diff

1176
ext/glew/visualinfo.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2,8 +2,13 @@
// apart from the string being built-up, which could easily be replaced
// with a file stream (although I've chosen not to do that just yet).
//
// Writes nicely 2-spade indented output with correct comma-placement
// in arrays and dictionaries.
//
// Does not deal with encodings in any way.
//
// Zero dependencies apart from stdlib.
// Public domain.
// Public domain by Henrik Rydgård.
#include <string>
#include <vector>
@ -19,6 +24,7 @@ class JsonWriter {
void end();
void pushDict(const char *name);
void pushArray(const char *name);
void pop();
void writeBool(bool value);
void writeBool(const char *name, bool value);
void writeInt(int value);
@ -27,7 +33,6 @@ class JsonWriter {
void writeFloat(const char *name, double value);
void writeString(const char *value);
void writeString(const char *name, const char *value);
void pop();
std::string str() const {
return str_.str();

View File

@ -56,7 +56,7 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\zlib;..\native;..\RollerballGL;..\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -72,7 +72,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\zlib;..\native;..\RollerballGL;..\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -83,7 +83,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<None Include="file\CMakeLists.txt" />
<None Include="ReadMe.txt" />
<None Include="README.md" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="audio\mixer.h" />

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="ReadMe.txt" />
<None Include="file\CMakeLists.txt">
<Filter>file</Filter>
</None>
<None Include="README.md" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="base\logging.h" />