[12632] Revert previous commit (see Notes)

This commit is contained in:
billy1arm 2013-05-31 13:50:57 +01:00 committed by Antz
parent 1cd806c02e
commit ef445ea523
1462 changed files with 9689 additions and 7080 deletions

View file

@ -1,5 +1,5 @@
#
# This file is part of the CMaNGOS Project. See AUTHORS file for Copyright information
# This code is part of MaNGOS. Contributor & Copyright details are in AUTHORS/THANKS.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View file

@ -1,4 +1,4 @@
/**
/*
@file AABox.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@ -282,6 +282,10 @@ bool AABox::culledBy(
return false;
}
void AABox::getBounds(Sphere& s) const {
s.center = center();
s.radius = extent().length() / 2;
}
bool AABox::intersects(const class Sphere& sphere) const {
double d = 0;

View file

@ -1,13 +1,13 @@
/**
/*
@file Any.cpp
@author Morgan McGuire
@author Shawn Yarbrough
@created 2006-06-11
@edited 2009-11-15
@edited 2010-07-24
Copyright 2000-2009, Morgan McGuire.
Copyright 2000-2010, Morgan McGuire.
All rights reserved.
*/
@ -15,11 +15,73 @@
#include "G3D/TextOutput.h"
#include "G3D/TextInput.h"
#include "G3D/stringutils.h"
#include "G3D/fileutils.h"
#include "G3D/FileSystem.h"
#include <deque>
#include <iostream>
namespace G3D {
std::string Any::resolveStringAsFilename() const {
verifyType(STRING);
std::string f = FileSystem::resolve(string(), sourceDirectory());
if (FileSystem::exists(f)) {
return f;
} else {
const std::string& s = System::findDataFile(string(), false);
if (s.empty()) {
return string();
} else {
return s;
}
}
}
bool Any::nameBeginsWith(const std::string& s) const {
return nameBeginsWith(s.c_str());
}
bool Any::nameEquals(const std::string& s) const {
// If std::string has a fast hash compare, use it first
return (name() == s) || nameEquals(s.c_str());
}
inline static char toLower(char c) {
return ((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a') : c;
}
bool Any::nameBeginsWith(const char* s) const {
verifyType(Any::ARRAY, Any::TABLE);
const char* n = name().c_str();
// Walk through character-by-character
while ((*s != '\0') && (*n != '\0')) {
if (toLower(*s) != toLower(*n)) {
// Mismatch
return false;
}
++s; ++n;
}
// Make sure s ran out no later than n
return (*s == '\0');
}
bool Any::nameEquals(const char* s) const {
verifyType(Any::ARRAY, Any::TABLE);
#ifdef G3D_WIN32
return stricmp(name().c_str(), s) == 0;
#else
return strcasecmp(name().c_str(), s) == 0;
#endif
}
void Any::beforeRead() const {
if (isPlaceholder()) {
// Tried to read from a placeholder--throw an exception as if
@ -675,11 +737,10 @@ bool Any::operator!=(const Any& x) const {
static void getDeserializeSettings(TextInput::Settings& settings) {
settings.cppBlockComments = true;
settings.cppLineComments = true;
settings.otherLineComments = true;
settings.otherCommentCharacter = '#';
settings.otherLineComments = false;
settings.generateCommentTokens = true;
settings.singleQuotedStrings = false;
settings.msvcSpecials = false;
settings.msvcFloatSpecials = false;
settings.caseSensitive = false;
}
@ -708,7 +769,7 @@ void Any::load(const std::string& filename) {
TextInput::Settings settings;
getDeserializeSettings(settings);
TextInput ti(filename, settings);
TextInput ti(FileSystem::resolve(filename), settings);
deserialize(ti);
}
@ -870,12 +931,6 @@ static bool isClose(const char c) {
}
/** True if \a s is a C++ name operator */
static bool isNameOperator(const std::string& s) {
return s == "." || s == "::" || s == "->";
}
void Any::deserializeName(TextInput& ti, Token& token, std::string& name) {
debugAssert(token.type() == Token::SYMBOL);
std::string s = token.string();
@ -928,6 +983,9 @@ void Any::deserialize(TextInput& ti, Token& token) {
"File ended without a properly formed Any");
}
// Do we need to read one more token after the end?
bool needRead = true;
switch (token.type()) {
case Token::STRING:
m_type = STRING;
@ -951,8 +1009,41 @@ void Any::deserialize(TextInput& ti, Token& token) {
break;
case Token::SYMBOL:
// Named Array, Named Table, Array, Table, or NONE
if (toUpper(token.string()) == "NONE") {
// Pragma, Named Array, Named Table, Array, Table, or NONE
if (token.string() == "#") {
// Pragma
// Currently, "include" is the only pragma allowed
token = ti.read();
if (! ((token.type() == Token::SYMBOL) &&
(token.string() == "include"))) {
throw ParseError(ti.filename(), token.line(), token.character(),
"Expected 'include' pragma after '#'");
}
ti.readSymbol("(");
const std::string& includeName = ti.readString();
// Find the include file
const std::string& myPath = filenamePath(ti.filename());
std::string t = pathConcat(myPath, includeName);
if (! FileSystem::exists(t)) {
// Try and find it, starting with cwd
t = System::findDataFile(includeName);
}
// Read the included file
load(t);
// Update the source information
ensureData();
m_data->source.filename +=
format(" [included from %s:%d(%d)]", ti.filename().c_str(), token.line(), token.character());
ti.readSymbol(")");
} else if (toUpper(token.string()) == "NONE") {
// Nothing left to do; we initialized to NONE originally
ensureData();
m_data->source.set(ti, token);
@ -982,6 +1073,7 @@ void Any::deserialize(TextInput& ti, Token& token) {
ensureData();
m_data->name = name;
}
needRead = false;
} // if NONE
break;
@ -996,7 +1088,7 @@ void Any::deserialize(TextInput& ti, Token& token) {
m_data->comment = comment;
}
if (m_type != ARRAY && m_type != TABLE) {
if (needRead) {
// Array and table already consumed their last token
token = ti.read();
}
@ -1016,9 +1108,9 @@ static bool isSeparator(char c) {
void Any::readUntilCommaOrClose(TextInput& ti, Token& token) {
while (! ((token.type() == Token::SYMBOL) &&
(isClose(token.string()[0])) ||
isSeparator(token.string()[0]))) {
bool atClose = (token.type() == Token::SYMBOL) && isClose(token.string()[0]);
bool atComma = isSeparator(token.string()[0]);
while (! (atClose || atComma)) {
switch (token.type()) {
case Token::NEWLINE:
case Token::COMMENT:
@ -1030,6 +1122,10 @@ void Any::readUntilCommaOrClose(TextInput& ti, Token& token) {
throw ParseError(ti.filename(), token.line(), token.character(),
"Expected a comma or close paren");
}
// Update checks
atComma = isSeparator(token.string()[0]);
atClose = (token.type() == Token::SYMBOL) && isClose(token.string()[0]);
}
}
@ -1076,13 +1172,13 @@ void Any::deserializeBody(TextInput& ti, Token& token) {
}
key = token.string();
// Consume everything up to the = sign
// Consume everything up to the = sign, returning the "=" sign.
token = ti.readSignificant();
if ((token.type() != Token::SYMBOL) || (token.string() != "=")) {
throw ParseError(ti.filename(), token.line(), token.character(), "Expected =");
} else {
// Consume (don't consume comments--we want the value pointed to by a to get those).
// Read the next token, which is the value (don't consume comments--we want the value pointed to by a to get those).
token = ti.read();
}
}
@ -1154,6 +1250,15 @@ const Any::Source& Any::source() const {
}
std::string Any::sourceDirectory() const {
if (m_data) {
return FilePath::parent(m_data->source.filename);
} else {
return "";
}
}
void Any::verify(bool value, const std::string& message) const {
beforeRead();
if (! value) {
@ -1185,6 +1290,14 @@ void Any::verifyName(const std::string& n) const {
}
void Any::verifyName(const std::string& n, const std::string& m) const {
beforeRead();
const std::string& x = toUpper(name());
verify(beginsWith(x, toUpper(n)) ||
beginsWith(x, toUpper(m)), "Name must begin with " + n + " or " + m);
}
void Any::verifyType(Type t) const {
beforeRead();
if (type() != t) {

View file

@ -1,4 +1,4 @@
/**
/*
@file AreaMemoryManager.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file BinaryFormat.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,11 +1,11 @@
/**
/*
@file BinaryInput.cpp
@author Morgan McGuire, graphics3d.com
Copyright 2001-2007, Morgan McGuire. All rights reserved.
@created 2001-08-09
@edited 2005-02-24
@edited 2010-03-05
<PRE>
@ -37,8 +37,11 @@
#include "G3D/Array.h"
#include "G3D/fileutils.h"
#include "G3D/Log.h"
#include "G3D/FileSystem.h"
#include <zlib.h>
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
#include "zip.h"
#endif /* G3DFIX: Use ZIP-library only if defined */
#include <cstring>
namespace G3D {
@ -272,28 +275,42 @@ BinaryInput::BinaryInput(
_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<uint8*>(v);
m_bufferLength = m_length = s;
if (compressed) {
decompress();
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
std::string zipfile;
if (FileSystem::inZipfile(m_filename, zipfile)) {
// Load from zipfile
// zipRead(filename, v, s);
std::string internalFile = m_filename.substr(zipfile.length() + 1);
struct zip* z = zip_open(zipfile.c_str(), ZIP_CHECKCONS, NULL);
{
struct zip_stat info;
zip_stat_init( &info ); // TODO: Docs unclear if zip_stat_init is required.
zip_stat(z, internalFile.c_str(), ZIP_FL_NOCASE, &info);
m_bufferLength = m_length = info.size;
// sets machines up to use MMX, if they want
m_buffer = reinterpret_cast<uint8*>(System::alignedMalloc(m_length, 16));
struct zip_file* zf = zip_fopen( z, internalFile.c_str(), ZIP_FL_NOCASE );
{
int64 test = zip_fread( zf, m_buffer, m_length );
debugAssertM(test == m_length,
internalFile + " was corrupt because it unzipped to the wrong size.");
(void)test;
}
m_freeBuffer = true;
} else {
Log::common()->printf("Warning: File not found: %s\n", m_filename.c_str());
zip_fclose( zf );
}
zip_close( z );
if (compressed) {
decompress();
}
m_freeBuffer = true;
return;
}
#endif /* G3DFIX: Use ZIP-library only if defined */
// Figure out how big the file is and verify that it exists.
m_length = fileLength(m_filename);
m_length = FileSystem::size(m_filename);
// Read the file into memory
FILE* file = fopen(m_filename.c_str(), "rb");
@ -460,6 +477,42 @@ std::string BinaryInput::readString() {
return readString(n);
}
static bool isNewline(char c) {
return c == '\n' || c == '\r';
}
std::string BinaryInput::readStringNewline() {
int64 n = 0;
if ((m_pos + m_alreadyRead + n) < (m_length - 1)) {
prepareToRead(1);
}
if ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
! isNewline(m_buffer[m_pos + n])) {
++n;
while ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
! isNewline(m_buffer[m_pos + n])) {
prepareToRead(1);
++n;
}
}
const std::string s = readString(n);
// Consume the newline
char firstNLChar = readUInt8();
// Consume the 2nd newline
if (isNewline(m_buffer[m_pos + 1]) && (m_buffer[m_pos + 1] != firstNLChar)) {
readUInt8();
}
return s;
}
std::string BinaryInput::readStringEven() {
std::string x = readString();

View file

@ -1,22 +1,27 @@
/**
/*
@file BinaryOutput.cpp
@author Morgan McGuire, graphics3d.com
Copyright 2002-2007, Morgan McGuire, All rights reserved.
@author Morgan McGuire, http://graphics.cs.williams.edu
Copyright 2002-2010, Morgan McGuire, All rights reserved.
@created 2002-02-20
@edited 2008-01-07
@edited 2010-03-17
*/
#include "G3D/platform.h"
#include "G3D/BinaryOutput.h"
#include "G3D/fileutils.h"
#include "G3D/FileSystem.h"
#include "G3D/stringutils.h"
#include "G3D/Array.h"
#include <zlib.h>
#include "G3D/Log.h"
#include <cstring>
#ifdef G3D_LINUX
# include <errno.h>
#endif
// 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.
@ -155,7 +160,7 @@ void BinaryOutput::reserveBytesWhenOutOfMemory(size_t bytes) {
//debugPrintf("Writing %d bytes to disk\n", writeBytes);
const char* mode = (m_alreadyWritten > 0) ? "ab" : "wb";
FILE* file = fopen(m_filename.c_str(), mode);
FILE* file = FileSystem::fopen(m_filename.c_str(), mode);
debugAssert(file);
size_t count = fwrite(m_buffer, 1, writeBytes, file);
@ -317,14 +322,17 @@ void BinaryOutput::commit(bool flush) {
parseFilename(m_filename, root, pathArray, base, ext);
path = root + stringJoin(pathArray, '/');
if (! fileExists(path, false)) {
createDirectory(path);
if (! FileSystem::exists(path, false)) {
FileSystem::createDirectory(path);
}
const char* mode = (m_alreadyWritten > 0) ? "ab" : "wb";
FILE* file = fopen(m_filename.c_str(), mode);
FILE* file = FileSystem::fopen(m_filename.c_str(), mode);
if (! file) {
logPrintf("Error %d while trying to open \"%s\"\n", errno, m_filename.c_str());
}
m_ok = (file != NULL) && m_ok;
if (m_ok) {
@ -340,7 +348,7 @@ void BinaryOutput::commit(bool flush) {
if (flush) {
fflush(file);
}
fclose(file);
FileSystem::fclose(file);
file = NULL;
}
}

View file

@ -1,4 +1,4 @@
/**
/*
@file Box.cpp
Box class
@ -16,7 +16,7 @@
namespace G3D {
/**
/*
Sets a field on four vertices. Used by the constructor.
*/
#define setMany(i0, i1, i2, i3, field, extreme) \

View file

@ -1,4 +1,4 @@
/**
/*
@file Box.cpp
Box class

View file

@ -1,4 +1,4 @@
/**
/*
\file BumpMapPreprocess.cpp
\maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,5 +1,5 @@
#
# This file is part of the CMaNGOS Project. See AUTHORS file for Copyright information
# This code is part of MaNGOS. Contributor & Copyright details are in AUTHORS/THANKS.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View file

@ -1,4 +1,4 @@
/**
/*
@file Capsule.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file CollisionDetection.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Color1.cpp
Color class.

View file

@ -1,4 +1,4 @@
/**
/*
@file Color1uint8.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Color3.cpp
Color class.

View file

@ -1,4 +1,4 @@
/**
/*
@file Color3uint8.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Color4.cpp
Color class.

View file

@ -1,4 +1,4 @@
/**
/*
@file Color4uint8.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Cone.cpp
Cone class
@ -26,7 +26,7 @@ Cone::Cone(const Vector3 &tip, const Vector3 &direction, float angle) {
debugAssert(angle <= pi());
}
/**
/*
Forms the smallest cone that contains the box. Undefined if
the tip is inside or on the box.
*/

View file

@ -1,4 +1,4 @@
/**
/*
@file ConvexPolyhedron.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file CoordinateFrame.cpp
Coordinate frame class
@ -6,7 +6,7 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2001-06-02
@edited 2009-11-13
@edited 2010-03-13
Copyright 2000-2010, Morgan McGuire.
All rights reserved.
@ -26,23 +26,52 @@
#include "G3D/UprightFrame.h"
#include "G3D/Any.h"
#include "G3D/stringutils.h"
#include "G3D/PhysicsFrame.h"
#include "G3D/UprightFrame.h"
namespace G3D {
std::string CoordinateFrame::toXYZYPRDegreesString() const {
UprightFrame uframe(*this);
return format("CFrame::fromXYZYPRDegrees(% 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff)",
uframe.translation.x, uframe.translation.y, uframe.translation.z,
toDegrees(uframe.yaw), toDegrees(uframe.pitch), 0.0f);
}
CoordinateFrame::CoordinateFrame(const Any& any) {
any.verifyName("CFrame");
if (toUpper(any.name()) == "CFRAME") {
*this = CFrame();
const std::string& n = toUpper(any.name());
if (beginsWith(n, "VECTOR3")) {
translation = any;
} else if (beginsWith(n, "MATRIX3")) {
rotation = any;
} else if ((n == "CFRAME") || (n == "COORDINATEFRAME")) {
any.verifyType(Any::TABLE, Any::ARRAY);
if (any.type() == Any::TABLE) {
rotation = any["rotation"];
translation = any["translation"];
} else {
if (any.type() == Any::ARRAY) {
any.verifySize(2);
rotation = any[0];
translation = any[1];
} else {
for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
const std::string& n = toLower(it->key);
if (n == "translation") {
translation = Vector3(it->value);
} else if (n == "rotation") {
rotation = Matrix3(it->value);
} else {
any.verify(false, "Illegal table key: " + it->key);
}
}
}
} else if (beginsWith(n, "PHYSICSFRAME") || beginsWith(n, "PFRAME")) {
*this = PhysicsFrame(any);
} else {
any.verifyName("CFrame::fromXYZYPRDegrees");
any.verifyName("CFrame::fromXYZYPRDegrees", "CoordinateFrame::fromXYZYPRDegrees");
any.verifyType(Any::ARRAY);
any.verifySize(3, 6);
@ -370,12 +399,12 @@ CoordinateFrame CoordinateFrame::lerp(
} else if (alpha == 0.0f) {
return *this;
} else {
Quat q1 = Quat(this->rotation);
Quat q2 = Quat(other.rotation);
const Quat q1(this->rotation);
const Quat q2(other.rotation);
return CoordinateFrame(
q1.slerp(q2, alpha).toRotationMatrix(),
this->translation * (1 - alpha) + other.translation * alpha);
translation * (1 - alpha) + other.translation * alpha);
}
}
@ -383,7 +412,7 @@ CoordinateFrame CoordinateFrame::lerp(
void CoordinateFrame::pointToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
vout.resize(v.size());
for (int i = v.size() - 1; i >= 0; --i) {
for (int i = 0; i < v.size(); ++i) {
vout[i] = pointToWorldSpace(v[i]);
}
}
@ -392,7 +421,7 @@ void CoordinateFrame::pointToWorldSpace(const Array<Vector3>& v, Array<Vector3>&
void CoordinateFrame::normalToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
vout.resize(v.size());
for (int i = v.size() - 1; i >= 0; --i) {
for (int i = 0; i < v.size(); ++i) {
vout[i] = normalToWorldSpace(v[i]);
}
}

View file

@ -1,4 +1,4 @@
/**
/*
@file Crypto.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Crypto_md5.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Cylinder.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -0,0 +1,867 @@
/*
@file FileSystem.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu
@author 2002-06-06
@edited 2010-04-10
*/
#include "G3D/FileSystem.h"
#include "G3D/System.h"
#include "G3D/stringutils.h"
#include "G3D/fileutils.h"
#include <sys/stat.h>
#include <sys/types.h>
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
#include "zip.h"
#endif /* G3DFIX: Use ZIP-library only if defined */
#include "G3D/g3dfnmatch.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
#ifdef G3D_WIN32
// Needed for _getcwd
# include <direct.h>
// Needed for _findfirst
# include <io.h>
#define stat64 _stat64
#else
# include <dirent.h>
# include <fnmatch.h>
# include <unistd.h>
# define _getcwd getcwd
# define _stat stat
#endif
namespace G3D {
static FileSystem* common = NULL;
FileSystem& FileSystem::instance() {
init();
return *common;
}
void FileSystem::init() {
if (common == NULL) {
common = new FileSystem();
}
}
void FileSystem::cleanup() {
if (common != NULL) {
delete common;
common = NULL;
}
}
FileSystem::FileSystem() : m_cacheLifetime(10) {}
/////////////////////////////////////////////////////////////
bool FileSystem::Dir::contains(const std::string& f) const {
for (int i = 0; i < nodeArray.size(); ++i) {
# ifdef G3D_WIN32
if (stricmp(f.c_str(), nodeArray[i].name.c_str()) == 0) {
return true;
}
# else
if (f == nodeArray[i].name) {
return true;
}
# endif
}
return false;
}
void FileSystem::Dir::computeZipListing(const std::string& zipfile, const std::string& pathInsideZipfile) {
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
struct zip* z = zip_open( FilePath::removeTrailingSlash(zipfile).c_str(), ZIP_CHECKCONS, NULL );
debugAssert(z);
int count = zip_get_num_files( z );
Set<std::string> alreadyAdded;
for (int i = 0; i < count; ++i) {
struct zip_stat info;
zip_stat_init( &info ); // TODO: Docs unclear if zip_stat_init is required.
zip_stat_index( z, i, ZIP_FL_NOCASE, &info );
// Fully-qualified name of a file inside zipfile
std::string name = info.name;
if (beginsWith(name, pathInsideZipfile)) {
// We found something inside the directory we were looking for,
// so the directory itself must exist
exists = true;
// For building the cached directory listing, extract only elements that do not contain
// additional subdirectories.
int start = pathInsideZipfile.size();
if ((int(name.length()) > start) && isSlash(name[start])) {
++start;
}
int end = findSlash(name, start);
if (end == -1) {
// There are no more slashes; add this name
name = name.substr(start);
if (alreadyAdded.insert(name)) {
Entry& e = nodeArray.next();
e.name = name;
e.type = FILE_TYPE;
}
} else {
// There are more slashes, indicating that this is a directory
name = name.substr(start, end);
if (alreadyAdded.insert(name)) {
Entry& e = nodeArray.next();
e.name = name;
e.type = DIR_TYPE;
}
}
}
}
zip_close(z);
z = NULL;
#endif /* G3DFIX: Use ZIP-library only if defined */
}
FileSystem::Dir& FileSystem::getContents(const std::string& path, bool forceUpdate) {
const std::string& key =
# if defined(G3D_WIN32)
FilePath::canonicalize(FilePath::removeTrailingSlash(toLower(FilePath::canonicalize(resolve(path)))));
# else
FilePath::canonicalize(FilePath::removeTrailingSlash(FilePath::canonicalize(resolve(path))));
# endif
RealTime now = System::time();
Dir& dir = m_cache.getCreate(key);
if ((now > dir.lastChecked + cacheLifetime()) || forceUpdate) {
dir = Dir();
// Out of date: update
dir.lastChecked = now;
struct _stat st;
const bool exists = _stat(key.c_str(), &st) != -1;
const bool isDirectory = (st.st_mode & S_IFDIR) != 0;
// Does this path exist on the real filesystem?
if (exists && isDirectory) {
// Is this path actually a directory?
if (isDirectory) {
dir.exists = true;
// Update contents
# ifdef G3D_WIN32
const std::string& filespec = FilePath::concat(key, "*");
struct _finddata_t fileinfo;
intptr_t handle = _findfirst(filespec.c_str(), &fileinfo);
debugAssert(handle != -1);
int result = 0;
do {
if ((strcmp(fileinfo.name, ".") != 0) && (strcmp(fileinfo.name, "..") != 0)) {
Entry& e = dir.nodeArray.next();
e.name = fileinfo.name;
if ((fileinfo.attrib & _A_SUBDIR) != 0) {
e.type = DIR_TYPE;
} else {
e.type = FILE_TYPE;
}
}
result = _findnext(handle, &fileinfo);
} while (result == 0);
_findclose(handle);
# else
DIR* listing = opendir(key.c_str());
debugAssertM(listing, "opendir failed on '" + key + "'");
struct dirent* entry = readdir(listing);
while (entry != NULL) {
if ((strcmp(entry->d_name, "..") != 0) && (strcmp(entry->d_name, ".") != 0)) {
Entry& e = dir.nodeArray.next();
e.name = entry->d_name;
# ifdef _DIRENT_HAVE_D_TYPE
// Not all POSIX systems support this field
// http://www.delorie.com/gnu/docs/glibc/libc_270.html
switch (entry->d_type) {
case DT_DIR:
e.type = DIR_TYPE;
break;
case DT_REG:
e.type = FILE_TYPE;
break;
case DT_UNKNOWN:
default:
e.type = UNKNOWN;
break;
}
# endif
}
entry = readdir(listing);
}
closedir(listing);
listing = NULL;
entry = NULL;
# endif
}
} else {
std::string zip;
if (exists && isZipfile(path)) {
// This is a zipfile; get its root
dir.isZipfile = true;
dir.computeZipListing(path, "");
} else if (inZipfile(path, zip)) {
// There is a zipfile somewhere in the path. Does
// the rest of the path exist inside the zipfile?
dir.inZipfile = true;
dir.computeZipListing(zip, path.substr(zip.length() + 1));
}
}
}
return dir;
}
bool FileSystem::_inZipfile(const std::string& path, std::string& z) {
// Reject trivial cases before parsing
if (path.find('.') == std::string::npos) {
// There is no zipfile possible, since G3D requires
// an extension on zipfiles.
return false;
}
// Look at all sub-paths containing periods.
// For each, ask if it is a zipfile.
int current = 0;
current = path.find('.', current);
while (current != -1) {
// xxxxx/foo.zip/yyyyy
current = path.find('.', current);
// Look forward for the next slash
int s = findSlash(path, current);
if (s == -1) {
// No more slashes
return false;
}
z = path.substr(0, s);
if (_isZipfile(z)) {
return true;
}
current = s + 1;
}
z = "";
return false;
}
bool FileSystem::_isZipfile(const std::string& filename) {
if (FilePath::ext(filename).empty()) {
return false;
}
FILE* f = fopen(FilePath::removeTrailingSlash(filename).c_str(), "r");
if (f == NULL) {
return false;
}
uint8 header[4];
fread(header, 4, 1, f);
const uint8 zipHeader[4] = {0x50, 0x4b, 0x03, 0x04};
for (int i = 0; i < 4; ++i) {
if (header[i] != zipHeader[i]) {
fclose(f);
return false;
}
}
fclose(f);
return true;
}
FILE* FileSystem::_fopen(const char* filename, const char* mode) {
for (const char* m = mode; *m != '\0'; ++m) {
if (*m == 'w') {
// Purge the cache entry for the parent of this directory
_clearCache(FilePath::parent(_resolve(filename)));
break;
}
}
return ::fopen(filename, mode);
}
void FileSystem::_clearCache(const std::string& path) {
if ((path == "") || FilePath::isRoot(path)) {
m_cache.clear();
} else {
Array<std::string> keys;
m_cache.getKeys(keys);
const std::string& prefix =
# ifdef G3D_WIN32
toLower(FilePath::canonicalize(FilePath::removeTrailingSlash(_resolve(path))));
# else
FilePath::canonicalize(FilePath::removeTrailingSlash(_resolve(path)));
# endif
const std::string& prefixSlash = prefix + "/";
for (int k = 0; k < keys.size(); ++k) {
const std::string& key = keys[k];
if ((key == prefix) || beginsWith(key, prefixSlash)) {
m_cache.remove(keys[k]);
}
}
}
}
void FileSystem::_setCacheLifetime(float t) {
m_cacheLifetime = t;
}
void FileSystem::_createDirectory(const std::string& dir) {
if (dir == "") {
return;
}
std::string d = _resolve(dir);
// Add a trailing / if there isn't one.
switch (d[d.size() - 1]) {
case '/':
case '\\':
break;
default:
d += "/";
}
// If it already exists, do nothing
if (_exists(FilePath::removeTrailingSlash(d))) {
return;
}
// Parse the name apart
std::string root, base, ext;
Array<std::string> path;
std::string lead;
FilePath::parse(d, root, path, base, ext);
debugAssert(base == "");
debugAssert(ext == "");
// Begin with an extra period so "c:\" becomes "c:\.\" after
// appending a path and "c:" becomes "c:.\", not root: "c:\"
std::string p = root + ".";
// Create any intermediate that doesn't exist
for (int i = 0; i < path.size(); ++i) {
p += "/" + path[i];
if (! _exists(p)) {
// Windows only requires one argument to mkdir,
// where as unix also requires the permissions.
# ifndef G3D_WIN32
mkdir(p.c_str(), 0777);
# else
_mkdir(p.c_str());
# endif
}
}
_clearCache(FilePath::parent(FilePath::removeTrailingSlash(d)));
}
void FileSystem::_copyFile(const std::string& source, const std::string& dest) {
# ifdef G3D_WIN32
// TODO: handle case where srcPath is in a zipfile
CopyFileA(source.c_str(), dest.c_str(), FALSE);
_clearCache(FilePath::parent(_resolve(dest)));
# else
// Read it all in, then dump it out
BinaryInput in(source, G3D_LITTLE_ENDIAN);
BinaryOutput out(dest, G3D_LITTLE_ENDIAN);
out.writeBytes(in.getCArray(), in.size());
out.commit(false);
# endif
}
bool FileSystem::_exists(const std::string& f, bool trustCache) {
if (FilePath::isRoot(f)) {
# ifdef G3D_WIN32
const std::string& winname = toLower(f.substr(0, 1)) + ":\\";
return _drives().contains(winname);
# else
return true;
# endif
}
std::string path = FilePath::removeTrailingSlash(f);
std::string parentPath = FilePath::parent(path);
const Dir& entry = getContents(parentPath, ! trustCache);
if (FilePath::containsWildcards(f)) {
if (! entry.exists) {
// The directory didn't exist, so neither do its contents
return false;
}
const std::string& pattern = FilePath::baseExt(path);
# ifdef G3D_WIN32
static const int flags = FNM_CASEFOLD;
# else
static const int flags = 0;
# endif
// See if any element of entry matches the wild card
for (int i = 0; i < entry.nodeArray.size(); ++i) {
if (FilePath::matches(entry.nodeArray[i].name, pattern, flags)) {
return true;
}
}
// Could not find a match
return false;
} else {
return entry.exists && entry.contains(FilePath::baseExt(path));
}
}
bool FileSystem::_isDirectory(const std::string& filename) {
// TODO: work with zipfiles and cache
struct _stat st;
const bool exists = _stat(FilePath::removeTrailingSlash(filename).c_str(), &st) != -1;
return exists && ((st.st_mode & S_IFDIR) != 0);
}
std::string FileSystem::_resolve(const std::string& filename, const std::string& cwd) {
if (filename.size() >= 1) {
if (isSlash(filename[0])) {
// Already resolved
return filename;
} else {
#ifdef G3D_WIN32
if ((filename.size() >= 2) && (filename[1] == ':')) {
// There is a drive spec on the front.
if ((filename.size() >= 3) && isSlash(filename[2])) {
// Already fully qualified
return filename;
} else {
// The drive spec is relative to the
// working directory on that drive.
debugAssertM(false, "Files of the form d:path are"
" not supported (use a fully qualified"
" name).");
return filename;
}
}
#endif
}
}
// Prepend the working directory.
return FilePath::concat(cwd, filename);
}
std::string FileSystem::_currentDirectory() {
static const int N = 2048;
char buffer[N];
_getcwd(buffer, N);
return std::string(buffer);
}
bool FileSystem::_isNewer(const std::string& src, const std::string& dst) {
// TODO: work with cache and zipfiles
struct _stat sts;
bool sexists = _stat(src.c_str(), &sts) != -1;
struct _stat dts;
bool dexists = _stat(dst.c_str(), &dts) != -1;
return sexists && ((! dexists) || (sts.st_mtime > dts.st_mtime));
}
int64 FileSystem::_size(const std::string& filename) {
struct stat64 st;
int result = stat64(filename.c_str(), &st);
if (result == -1) {
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
std::string zip, contents;
if (zipfileExists(filename, zip, contents)) {
int64 requiredMem;
struct zip *z = zip_open( zip.c_str(), ZIP_CHECKCONS, NULL );
debugAssertM(z != NULL, zip + ": zip open failed.");
{
struct zip_stat info;
zip_stat_init( &info ); // Docs unclear if zip_stat_init is required.
int success = zip_stat( z, contents.c_str(), ZIP_FL_NOCASE, &info );
debugAssertM(success == 0, zip + ": " + contents + ": zip stat failed.");
requiredMem = info.size;
}
zip_close(z);
return requiredMem;
} else {
#endif /* G3DFIX: Use ZIP-library only if defined */
return -1;
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
}
#endif /* G3DFIX: Use ZIP-library only if defined */
}
return st.st_size;
}
void FileSystem::listHelper(const std::string& shortSpec, const std::string& parentPath, Array<std::string>& result, const ListSettings& settings) {
Dir& dir = getContents(parentPath, false);
if (! dir.exists) {
return;
}
for (int i = 0; i < dir.nodeArray.size(); ++i) {
Entry& entry = dir.nodeArray[i];
// See if it matches the spec
if (FilePath::matches(entry.name, shortSpec, settings.caseSensitive)) {
if ((entry.type == UNKNOWN) && ! (settings.files && settings.directories)) {
// Update the type
entry.type = isDirectory(FilePath::concat(parentPath, entry.name)) ? DIR_TYPE : FILE_TYPE;
}
if ((settings.files && settings.directories) ||
(settings.files && (entry.type == FILE_TYPE)) ||
(settings.directories && (entry.type == DIR_TYPE))) {
if (settings.includeParentPath) {
result.append(FilePath::concat(parentPath, entry.name));
} else {
result.append(entry.name);
}
}
} // match
if (settings.recursive && (entry.type == DIR_TYPE)) {
listHelper(shortSpec, FilePath::concat(parentPath, entry.name), result, settings);
}
} // for
}
void FileSystem::_list(const std::string& spec, Array<std::string>& result, const ListSettings& settings) {
const std::string& shortSpec = FilePath::baseExt(spec);
const std::string& parentPath = FilePath::parent(spec);
listHelper(shortSpec, parentPath, result, settings);
}
#ifdef G3D_WIN32
const Array<std::string>& FileSystem::_drives() {
if (m_winDrive.length() == 0) {
// See http://msdn.microsoft.com/en-us/library/aa364975(VS.85).aspx
static const size_t bufSize = 5000;
char bufData[bufSize];
GetLogicalDriveStringsA(bufSize, bufData);
// Drive list is a series of NULL-terminated strings, itself terminated with a NULL.
for (int i = 0; bufData[i] != '\0'; ++i) {
const char* thisString = bufData + i;
m_winDrive.append(toLower(thisString));
i += strlen(thisString) + 1;
}
}
return m_winDrive;
}
#endif
/////////////////////////////////////////////////////////////////////
bool FilePath::isRoot(const std::string& f) {
# ifdef G3D_WIN32
if (f.length() < 2) {
return false;
}
if (f[1] == ':') {
if (f.length() == 2) {
// e.g., "x:"
return true;
} else if ((f.length() == 3) && isSlash(f[2])) {
// e.g., "x:\"
return true;
}
}
if (isSlash(f[0]) && isSlash(f[1])) {
// e.g., "\\foo\"
return true;
}
# else
if (f == "/") {
return true;
}
# endif
return false;
}
std::string FilePath::removeTrailingSlash(const std::string& f) {
bool removeSlash = ((endsWith(f, "/") || endsWith(f, "\\"))) && ! isRoot(f);
return removeSlash ? f.substr(0, f.length() - 1) : f;
}
std::string FilePath::concat(const std::string& dirname, const std::string& file) {
// Ensure that the directory ends in a slash
if (! dirname.empty() &&
! isSlash(dirname[dirname.size() - 1]) &&
(dirname[dirname.size() - 1] != ':')) {
return dirname + '/' + file;
} else {
return dirname + file;
}
}
std::string FilePath::ext(const std::string& filename) {
int i = filename.rfind(".");
if (i >= 0) {
return filename.substr(i + 1, filename.length() - i);
} else {
return "";
}
}
std::string FilePath::baseExt(const std::string& filename) {
int i = findLastSlash(filename);
# ifdef G3D_WIN32
int j = filename.rfind(":");
if ((i == -1) && (j >= 0)) {
i = j;
}
# endif
if (i == -1) {
return filename;
} else {
return filename.substr(i + 1, filename.length() - i);
}
}
std::string FilePath::base(const std::string& path) {
std::string filename = baseExt(path);
int i = filename.rfind(".");
if (i == -1) {
// No extension
return filename;
} else {
return filename.substr(0, i);
}
}
std::string FilePath::parent(const std::string& path) {
int i = findLastSlash(removeTrailingSlash(path));
# ifdef G3D_WIN32
int j = path.rfind(":");
if ((i == -1) && (j >= 0)) {
i = j;
}
# endif
if (i == -1) {
return "";
} else {
return path.substr(0, i + 1);
}
}
bool FilePath::containsWildcards(const std::string& filename) {
return (filename.find('*') != std::string::npos) || (filename.find('?') != std::string::npos);
}
bool FilePath::matches(const std::string& path, const std::string& pattern, bool caseSensitive) {
int flags = FNM_PERIOD | FNM_NOESCAPE | FNM_PATHNAME;
if (! caseSensitive) {
flags |= FNM_CASEFOLD;
}
return g3dfnmatch(pattern.c_str(), path.c_str(), flags) == 0;
}
static int fixslash(int c) {
return (c == '\\') ? '/' : c;
}
std::string FilePath::canonicalize(std::string x) {
std::transform(x.begin(), x.end(), x.begin(), fixslash);
return x;
}
void FilePath::parse
(const std::string& filename,
std::string& root,
Array<std::string>& path,
std::string& base,
std::string& ext) {
std::string f = filename;
root = "";
path.clear();
base = "";
ext = "";
if (f == "") {
// Empty filename
return;
}
// See if there is a root/drive spec.
if ((f.size() >= 2) && (f[1] == ':')) {
if ((f.size() > 2) && isSlash(f[2])) {
// e.g. c:\foo
root = f.substr(0, 3);
f = f.substr(3, f.size() - 3);
} else {
// e.g. c:foo
root = f.substr(2);
f = f.substr(2, f.size() - 2);
}
} else if ((f.size() >= 2) & isSlash(f[0]) && isSlash(f[1])) {
// e.g. //foo
root = f.substr(0, 2);
f = f.substr(2, f.size() - 2);
} else if (isSlash(f[0])) {
root = f.substr(0, 1);
f = f.substr(1, f.size() - 1);
}
// Pull the extension off
{
// Find the period
size_t i = f.rfind('.');
if (i != std::string::npos) {
// Make sure it is after the last slash!
size_t j = iMax(f.rfind('/'), f.rfind('\\'));
if ((j == std::string::npos) || (i > j)) {
ext = f.substr(i + 1, f.size() - i - 1);
f = f.substr(0, i);
}
}
}
// Pull the basename off
{
// Find the last slash
size_t i = iMax(f.rfind('/'), f.rfind('\\'));
if (i == std::string::npos) {
// There is no slash; the basename is the whole thing
base = f;
f = "";
} else if ((i != std::string::npos) && (i < f.size() - 1)) {
base = f.substr(i + 1, f.size() - i - 1);
f = f.substr(0, i);
}
}
// Parse what remains into path.
size_t prev, cur = 0;
while (cur < f.size()) {
prev = cur;
// Allow either slash
size_t i = f.find('/', prev + 1);
size_t j = f.find('\\', prev + 1);
if (i == std::string::npos) {
i = f.size();
}
if (j == std::string::npos) {
j = f.size();
}
cur = iMin(i, j);
if (cur == std::string::npos) {
cur = f.size();
}
path.append(f.substr(prev, cur - prev));
++cur;
}
}
}

View file

@ -1,11 +1,11 @@
/**
/*
@file GCamera.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu
@author Jeff Marsceill, 08jcm@williams.edu
@created 2005-07-20
@edited 2009-11-24
@edited 2010-02-22
*/
#include "G3D/GCamera.h"
#include "G3D/platform.h"
@ -45,6 +45,8 @@ GCamera::GCamera(const Any& any) {
m_nearPlaneZ = it->value;
} else if (k == "FARPLANEZ") {
m_farPlaneZ = it->value;
} else if (k == "PIXELOFFSET") {
m_pixelOffset = it->value;
} else {
any.verify(false, std::string("Illegal key in table: ") + it->key);
}
@ -61,6 +63,7 @@ GCamera::operator Any() const {
any.set("nearPlaneZ", nearPlaneZ());
any.set("farPlaneZ", farPlaneZ());
any.set("coordinateFrame", coordinateFrame());
any.set("pixelOffset", pixelOffset());
return any;
}
@ -68,7 +71,7 @@ GCamera::operator Any() const {
GCamera::GCamera() {
setNearPlaneZ(-0.2f);
setFarPlaneZ(-100.0f);
setFarPlaneZ(-150.0f);
setFieldOfView((float)toRadians(90.0f), HORIZONTAL);
}
@ -171,8 +174,8 @@ void GCamera::getProjectPixelMatrix(const Rect2D& viewport, Matrix4& P) const {
float sx = screenWidth / 2.0;
float sy = screenHeight / 2.0;
P = Matrix4(sx, 0, 0, sx + viewport.x0(),
0, -sy, 0, sy + viewport.y0(),
P = Matrix4(sx, 0, 0, sx + viewport.x0() - m_pixelOffset.x,
0, -sy, 0, sy + viewport.y0() + m_pixelOffset.y,
0, 0, 1, 0,
0, 0, 0, 1) * P;
}
@ -185,24 +188,28 @@ void GCamera::getProjectUnitMatrix(const Rect2D& viewport, Matrix4& P) const {
float r, l, t, b, n, f, x, y;
float s = 1.0f;
if (m_direction == VERTICAL) {
y = -m_nearPlaneZ * tan(m_fieldOfView / 2);
x = y * (screenWidth / screenHeight);
s = screenHeight;
} else { //m_direction == HORIZONTAL
x = -m_nearPlaneZ * tan(m_fieldOfView / 2);
y = x * (screenHeight / screenWidth);
s = screenWidth;
}
n = -m_nearPlaneZ;
f = -m_farPlaneZ;
r = x;
l = -x;
t = y;
b = -y;
r = x - m_pixelOffset.x/s;
l = -x - m_pixelOffset.x/s;
t = y + m_pixelOffset.y/s;
b = -y + m_pixelOffset.y/s;
P = Matrix4::perspectiveProjection(l, r, b, t, n, f);
}
Vector3 GCamera::projectUnit(const Vector3& point, const Rect2D& viewport) const {
Matrix4 M;
getProjectUnitMatrix(viewport, M);
@ -244,7 +251,7 @@ Vector3 GCamera::unproject(const Vector3& v, const Rect2D& viewport) const {
z = 1.0f / ((((1.0f / f) - (1.0f / n)) * v.z) + 1.0f / n);
}
const Ray& ray = worldRay(v.x, v.y, viewport);
const Ray& ray = worldRay(v.x - m_pixelOffset.x, v.y - m_pixelOffset.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()));
@ -481,6 +488,7 @@ void GCamera::serialize(BinaryOutput& bo) const {
bo.writeFloat32(farPlaneZ());
m_cframe.serialize(bo);
bo.writeInt8(m_direction);
m_pixelOffset.serialize(bo);
}
@ -492,6 +500,7 @@ void GCamera::deserialize(BinaryInput& bi) {
debugAssert(m_farPlaneZ < 0.0f);
m_cframe.deserialize(bi);
m_direction = (FOVDirection)bi.readInt8();
m_pixelOffset.deserialize(bi);
}

View file

@ -1,4 +1,4 @@
/**
/*
\file GImage.cpp
\author Morgan McGuire, http://graphics.cs.williams.edu
Copyright 2002-2010, Morgan McGuire
@ -639,7 +639,7 @@ void GImage::rotate90CW(int numTimes) {
for (int j = 0; j < numTimes; ++j) {
{
uint8* temp = old;
uint8* old = m_byte;
old = m_byte;
m_byte = temp;
}

View file

@ -1,4 +1,4 @@
/**
/*
@file GImage_bayer.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu
@created 2002-05-27

View file

@ -1,4 +1,4 @@
/**
/*
@file GImage_bmp.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu
@created 2002-05-27
@ -13,7 +13,7 @@
namespace G3D {
#ifndef G3D_WIN32
/**
/*
This is used by the Windows bitmap I/O.
*/
static const int BI_RGB = 0;

View file

@ -1,4 +1,4 @@
/**
/*
@file GImage_jpeg.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu
@created 2002-05-27
@ -26,7 +26,7 @@ namespace G3D {
const int jpegQuality = 96;
/**
/*
The IJG library needs special setup for compress/decompressing
from memory. These classes provide them.
@ -43,7 +43,7 @@ public:
typedef memory_destination_mgr* mem_dest_ptr;
/**
/*
Signature dictated by IJG.
*/
static void init_destination (
@ -56,7 +56,7 @@ static void init_destination (
dest->count=0;
}
/**
/*
Signature dictated by IJG.
*/
static boolean empty_output_buffer (
@ -70,7 +70,7 @@ static boolean empty_output_buffer (
return TRUE;
}
/**
/*
Signature dictated by IJG.
*/
static void term_destination (
@ -80,7 +80,7 @@ static void term_destination (
dest->count = dest->size - dest->pub.free_in_buffer;
}
/**
/*
Signature dictated by IJG.
*/
static void jpeg_memory_dest (
@ -111,7 +111,7 @@ static void jpeg_memory_dest (
#define INPUT_BUF_SIZE 4096
/**
/*
Structure dictated by IJG.
*/
class memory_source_mgr {
@ -127,7 +127,7 @@ public:
typedef memory_source_mgr* mem_src_ptr;
/**
/*
Signature dictated by IJG.
*/
static void init_source(
@ -139,7 +139,7 @@ static void init_source(
}
/**
/*
Signature dictated by IJG.
*/
static boolean fill_input_buffer(
@ -168,7 +168,7 @@ static boolean fill_input_buffer(
}
/**
/*
Signature dictated by IJG.
*/
static void skip_input_data(
@ -190,7 +190,7 @@ static void skip_input_data(
}
/**
/*
Signature dictated by IJG.
*/
static void term_source (
@ -200,7 +200,7 @@ static void term_source (
}
/**
/*
Signature dictated by IJG.
*/
static void jpeg_memory_src (

View file

@ -1,4 +1,4 @@
/**
/*
@file GImage_png.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu
@created 2002-05-27
@ -71,10 +71,20 @@ void png_warning(
void GImage::encodePNG(
BinaryOutput& out) const {
debugAssert( m_channels == 1 || m_channels == 3 || m_channels == 4 );
if (! (m_channels == 1 || m_channels == 3 || m_channels == 4)) {
throw GImage::Error(format("Illegal channels for PNG: %d", m_channels), out.getFilename());
}
if (m_width <= 0) {
throw GImage::Error(format("Illegal width for PNG: %d", m_width), out.getFilename());
}
if (m_height <= 0) {
throw GImage::Error(format("Illegal height for PNG: %d", m_height), out.getFilename());
}
if (m_height > (int)(PNG_UINT_32_MAX / png_sizeof(png_bytep)))
// PNG library requires that the height * pointer size fit within an int
if (png_uint_32(m_height) * png_sizeof(png_bytep) > PNG_UINT_32_MAX) {
throw GImage::Error("Unsupported PNG height.", out.getFilename());
}
out.setEndian(G3D_LITTLE_ENDIAN);
@ -184,7 +194,7 @@ void GImage::decodePNG(
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);
&interlace_type, NULL, NULL);
if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
@ -206,7 +216,7 @@ void GImage::decodePNG(
//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);
png_set_expand(png_ptr);
}
//Expand paletted or RGB images with transparency to full alpha channels
@ -253,7 +263,7 @@ void GImage::decodePNG(
for (uint32 pass = 0; pass < number_passes; ++pass) {
for (uint32 y = 0; y < (uint32)m_height; ++y) {
png_bytep rowPointer = &m_byte[m_width * m_channels * y];
png_read_rows(png_ptr, &rowPointer, png_bytepp_NULL, 1);
png_read_rows(png_ptr, &rowPointer, NULL, 1);
}
}

View file

@ -1,4 +1,4 @@
/**
/*
@file GImage_ppm.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu
@created 2002-05-27
@ -183,7 +183,7 @@ void GImage::decodePPM(
int w, h;
input.readBytes(head, 2);
if (head[0] != 'P' || (head[1] != '6') && (head[1] != '5')) {
if (head[0] != 'P' || ((head[1] != '6') && (head[1] != '5'))) {
throw GImage::Error("Invalid PPM Header.", input.getFilename());
}

View file

@ -1,4 +1,4 @@
/**
/*
@file GImage_tga.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu
@created 2002-05-27
@ -94,6 +94,20 @@ void GImage::encodeTGA(
out.writeString("TRUEVISION-XFILE ");
}
inline static void readBGR(uint8* byte, BinaryInput& bi) {
int b = bi.readUInt8();
int g = bi.readUInt8();
int r = bi.readUInt8();
byte[0] = r;
byte[1] = g;
byte[2] = b;
}
inline static void readBGRA(uint8* byte, BinaryInput& bi) {
readBGR(byte, bi);
byte[3] = bi.readUInt8();
}
void GImage::decodeTGA(
BinaryInput& input) {
@ -117,8 +131,8 @@ void GImage::decodeTGA(
(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());
if (imageType != 2 && imageType != 10) {
throw Error("TGA images must be type 2 (Uncompressed truecolor) or 10 (Run-length truecolor)", input.getFilename());
}
// Color map specification
@ -159,34 +173,63 @@ void GImage::decodeTGA(
int x;
int y;
if (m_channels == 3) {
if (imageType == 2) {
// Uncompressed
if (m_channels == 3) {
for (y = m_height - 1; y >= 0; --y) {
for (x = 0; x < m_width; ++x) {
int i = (x + y * m_width) * 3;
readBGR(m_byte + i, input);
}
}
} else {
for (y = m_height - 1; y >= 0; --y) {
for (x = 0; x < m_width; ++x) {
int i = (x + y * m_width) * 4;
readBGRA(m_byte + i, input);
}
}
}
} else if (imageType == 10) {
// Run-length encoded
for (y = m_height - 1; y >= 0; --y) {
for (x = 0; x < m_width; ++x) {
int b = input.readUInt8();
int g = input.readUInt8();
int r = input.readUInt8();
int i = (x + y * m_width) * 3;
m_byte[i + 0] = r;
m_byte[i + 1] = g;
m_byte[i + 2] = b;
}
for (int x = 0; x < m_width; /* intentionally no x increment */) {
// The specification guarantees that no packet will wrap past the end of a row
const uint8 repetitionCount = input.readUInt8();
const uint8 numValues = (repetitionCount & (~128)) + 1;
int byteOffset = (x + y * m_width) * 3;
if (repetitionCount & 128) {
// When the high bit is 1, this is a run-length packet
if (m_channels == 3) {
Color3uint8 value;
readBGR((uint8*)(&value), input);
for (int i = 0; i < numValues; ++i, ++x) {
for (int b = 0; b < 3; ++b, ++byteOffset) {
m_byte[byteOffset] = value[b];
}
}
} else {
Color4uint8 value;
readBGRA((uint8*)(&value), input);
for (int i = 0; i < numValues; ++i, ++x) {
for (int b = 0; b < 3; ++b, ++byteOffset) {
m_byte[byteOffset] = value[b];
}
}
}
} else {
// When the high bit is 0, this is a raw packet
for (int i = 0; i < numValues; ++i, ++x, byteOffset += m_channels) {
readBGR(m_byte + byteOffset, input);
}
}
}
}
} else {
for (y = m_height - 1; y >= 0; --y) {
for (x = 0; x < m_width; ++x) {
int b = input.readUInt8();
int g = input.readUInt8();
int r = input.readUInt8();
int a = input.readUInt8();
int i = (x + y * m_width) * 4;
m_byte[i + 0] = r;
m_byte[i + 1] = g;
m_byte[i + 2] = b;
m_byte[i + 3] = a;
}
}
alwaysAssertM(false, "Unsupported type");
}
}

View file

@ -1,4 +1,4 @@
/**
/*
@file GLight.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@ -19,6 +19,8 @@ GLight::GLight(const Any& any) {
if (any.type() == Any::TABLE) {
*this = GLight();
Vector3 spotTarget;
bool hasSpotTarget = false;
for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
const std::string& key = toLower(it->key);
if (key == "position") {
@ -26,7 +28,10 @@ GLight::GLight(const Any& any) {
} else if (key == "rightdirection") {
rightDirection = it->value;
} else if (key == "spotdirection") {
spotDirection = it->value;
spotDirection = Vector3(it->value).directionOrZero();
} else if (key == "spottarget") {
spotTarget = it->value;
hasSpotTarget = true;
} else if (key == "spotcutoff") {
spotCutoff = it->value.number();
} else if (key == "spotsquare") {
@ -47,6 +52,9 @@ GLight::GLight(const Any& any) {
any.verify(false, "Illegal key: " + it->key);
}
}
if (hasSpotTarget) {
spotDirection = (spotTarget - position.xyz()).direction();
}
} else if (toLower(any.name()) == "glight::directional") {
*this = directional(any[0], any[1],
@ -67,9 +75,9 @@ GLight::GLight(const Any& any) {
*this = spot(any[0], any[1], any[2], any[3],
(any.size() > 4) ? any[4] : Any(1),
(any.size() > 5) ? any[5] : Any(0),
(any.size() > 6) ? any[6] : Any(0.5f),
(any.size() > 7) ? any[5] : Any(true),
(any.size() > 8) ? any[6] : Any(true));
(any.size() > 6) ? any[6] : Any(0),
(any.size() > 7) ? any[7] : Any(true),
(any.size() > 8) ? any[8] : Any(true));
} else {
any.verify(false, "Unrecognized name");
}

View file

@ -1,4 +1,4 @@
/**
/*
@file GThread.cpp
GThread class.

View file

@ -1,4 +1,4 @@
/**
/*
@file GUniqueID.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu
*/

View file

@ -1,4 +1,4 @@
/**
/*
@file Image1.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Image1uint8.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Image3.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Image3uint8.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Image4.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Image4uint8.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,10 +1,10 @@
/**
/*
@file ImageFormat.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2003-05-23
@edited 2009-12-10
@edited 2010-03-30
*/
#include "GLG3D/glheaders.h"
@ -130,13 +130,19 @@ const ImageFormat* ImageFormat::stencil(int bits) {
"RGB8I",
"RGB8UI",
"RGBA8UI",
"ARGB8",
"BGR8",
"R8",
"RG8",
"RG8I",
"RG8UI",
"RG16F",
"RGBA8",
"RGBA16",
"RGBA16F",
@ -287,6 +293,9 @@ const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
case ImageFormat::CODE_BGR8:
return ImageFormat::BGR8();
case ImageFormat::CODE_R8:
return ImageFormat::R8();
case ImageFormat::CODE_RG8:
return ImageFormat::RG8();
@ -296,6 +305,9 @@ const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
case ImageFormat::CODE_RG8UI:
return ImageFormat::RG8UI();
case ImageFormat::CODE_RG16F:
return ImageFormat::RG16F();
case ImageFormat::CODE_RGBA8:
return ImageFormat::RGBA8();
@ -474,11 +486,16 @@ DEFINE_TEXTUREFORMAT_METHOD(LA32F, 2, UNCOMP_FORMAT, GL_LUMINANCE_ALPHA32
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(R8, 1, UNCOMP_FORMAT, GL_R8, GL_RED, 0, 0, 8, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_R8, ImageFormat::COLOR_SPACE_RGB);
DEFINE_TEXTUREFORMAT_METHOD(RG8, 2, UNCOMP_FORMAT, GL_RG8, GL_RG, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8, ImageFormat::COLOR_SPACE_RGB);
DEFINE_TEXTUREFORMAT_METHOD(RG8I, 2, UNCOMP_FORMAT, GL_RG8I, GL_RG, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8I, ImageFormat::COLOR_SPACE_RGB);
// The base format for integer formats must be *_INTEGER even though the spec doesn't state this
DEFINE_TEXTUREFORMAT_METHOD(RG8I, 2, UNCOMP_FORMAT, GL_RG8I, GL_RG_INTEGER, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8I, ImageFormat::COLOR_SPACE_RGB);
DEFINE_TEXTUREFORMAT_METHOD(RG8UI, 2, UNCOMP_FORMAT, GL_RG8UI, GL_RG, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8UI, ImageFormat::COLOR_SPACE_RGB);
DEFINE_TEXTUREFORMAT_METHOD(RG8UI, 2, UNCOMP_FORMAT, GL_RG8UI, GL_RG_INTEGER, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8UI, ImageFormat::COLOR_SPACE_RGB);
DEFINE_TEXTUREFORMAT_METHOD(RG16F, 2, UNCOMP_FORMAT, GL_RG16F, GL_RG, 0, 0, 16, 16, 0, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RG16F, 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);
@ -504,7 +521,8 @@ DEFINE_TEXTUREFORMAT_METHOD(RGBA16F, 4, UNCOMP_FORMAT, GL_RGBA16F_ARB,
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(RGBA32UI, 4, UNCOMP_FORMAT, GL_RGBA32UI, GL_RGBA, 0, 32, 32, 32, 32, 0, 0, 32*4, 32*4, GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA32UI, ImageFormat::COLOR_SPACE_RGB);
// The base format for integer formats must be *_INTEGER even though the spec doesn't state this
DEFINE_TEXTUREFORMAT_METHOD(RGBA32UI, 4, UNCOMP_FORMAT, GL_RGBA32UI, GL_RGBA_INTEGER, 0, 32, 32, 32, 32, 0, 0, 32*4, 32*4, GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA32UI, ImageFormat::COLOR_SPACE_RGB);
// Unsigned
DEFINE_TEXTUREFORMAT_METHOD(R11G11B10F, 3, UNCOMP_FORMAT, GL_R11F_G11F_B10F_EXT, GL_RGB, 0, 0, 11, 11, 10, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_R11G11B10F, ImageFormat::COLOR_SPACE_RGB);
@ -512,9 +530,12 @@ DEFINE_TEXTUREFORMAT_METHOD(R11G11B10F, 3, UNCOMP_FORMAT, GL_R11F_G11F_B10F_EX
// Unsigned
DEFINE_TEXTUREFORMAT_METHOD(RGB9E5F, 3, UNCOMP_FORMAT, GL_RGB9_E5_EXT, GL_RGB, 0, 0, 14, 14, 14, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGB9E5F, ImageFormat::COLOR_SPACE_RGB);
DEFINE_TEXTUREFORMAT_METHOD(RGB8I, 3, UNCOMP_FORMAT, GL_RGB8I_EXT, GL_RGB, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8I, ImageFormat::COLOR_SPACE_RGB);
// The base format for integer formats must be *_INTEGER even though the spec doesn't state this
DEFINE_TEXTUREFORMAT_METHOD(RGB8I, 3, UNCOMP_FORMAT, GL_RGB8I_EXT, GL_RGB_INTEGER, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8I, ImageFormat::COLOR_SPACE_RGB);
DEFINE_TEXTUREFORMAT_METHOD(RGB8UI, 3, UNCOMP_FORMAT, GL_RGB8UI_EXT, GL_RGB, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8UI, ImageFormat::COLOR_SPACE_RGB);
DEFINE_TEXTUREFORMAT_METHOD(RGB8UI, 3, UNCOMP_FORMAT, GL_RGB8UI_EXT, GL_RGB_INTEGER, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8UI, ImageFormat::COLOR_SPACE_RGB);
DEFINE_TEXTUREFORMAT_METHOD(RGBA8UI, 4, UNCOMP_FORMAT, GL_RGBA8UI_EXT, GL_RGBA_INTEGER, 0, 0, 8, 8, 8, 8, 0, 32, 32, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA8UI, 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);

View file

@ -1,4 +1,4 @@
/**
/*
@file Intersect.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Line.cpp
Line class

View file

@ -1,4 +1,4 @@
/**
/*
@file LineSegment.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,9 +1,9 @@
/**
/*
@file Log.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2001-08-04
@edited 2009-01-15
@edited 2010-01-15
*/
#include "G3D/platform.h"
@ -11,6 +11,7 @@
#include "G3D/format.h"
#include "G3D/Array.h"
#include "G3D/fileutils.h"
#include "G3D/FileSystem.h"
#include <time.h>
#ifdef G3D_WIN32
@ -43,7 +44,7 @@ Log::Log(const std::string& filename, int stripFromStackBottom) :
this->filename = filename;
logFile = fopen(filename.c_str(), "w");
logFile = FileSystem::fopen(filename.c_str(), "w");
if (logFile == NULL) {
std::string drive, base, ext;
@ -58,7 +59,7 @@ Log::Log(const std::string& filename, int stripFromStackBottom) :
logName = std::string("/tmp/") + logName;
#endif
logFile = fopen(logName.c_str(), "w");
logFile = FileSystem::fopen(logName.c_str(), "w");
}
// Use a large buffer (although we flush in logPrintf)

View file

@ -1,4 +1,4 @@
/**
/*
@file Matrix.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu
*/

View file

@ -1,4 +1,4 @@
/**
/*
@file Matrix3.cpp
3x3 matrix class
@ -29,11 +29,17 @@ const float Matrix3::EPSILON = 1e-06f;
Matrix3::Matrix3(const Any& any) {
any.verifyName("Matrix3");
any.verifyType(Any::ARRAY);
any.verifySize(9);
for (int r = 0; r < 3; ++r) {
for (int c = 0; c < 3; ++c) {
elt[r][c] = any[r * 3 + c];
if (any.nameEquals("Matrix3::fromAxisAngle")) {
any.verifySize(2);
*this = Matrix3::fromAxisAngle(any[0], any[1].number());
} else {
any.verifySize(9);
for (int r = 0; r < 3; ++r) {
for (int c = 0; c < 3; ++c) {
elt[r][c] = any[r * 3 + c];
}
}
}
}

View file

@ -1,4 +1,4 @@
/**
/*
@file Matrix4.cpp
@ -44,7 +44,12 @@ Matrix4::Matrix4(const Any& any) {
} else {
any.verify(false, "Matrix4::scale() takes either 1 or 3 arguments");
}
} else {
} else if (name == "matrix4::translation") {
if (any.size() == 3) {
*this = translation(any[0], any[1], any[2]);
} else {
any.verify(false, "Matrix4::translation() takes either 1 or 3 arguments");
} } else {
any.verify(false, "Expected Matrix4 constructor");
}
}
@ -253,7 +258,7 @@ Matrix4::Matrix4(
elt[3][0] = r4c1; elt[3][1] = r4c2; elt[3][2] = r4c3; elt[3][3] = r4c4;
}
/**
/*
init should be <B>row major</B>.
*/
Matrix4::Matrix4(const float* init) {

View file

@ -1,4 +1,4 @@
/**
/*
@file MemoryManager.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file MeshAlg.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,11 +1,11 @@
/**
/*
@file MeshAlgAdjacency.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2003-09-14
@edited 2009-04-26
@edited 2010-04-26
Copyright 2000-2009, Morgan McGuire.
Copyright 2000-2010, Morgan McGuire.
All rights reserved.
*/
@ -15,6 +15,7 @@
#include "G3D/Set.h"
#include "G3D/Stopwatch.h"
#include "G3D/SmallArray.h"
#include "G3D/AreaMemoryManager.h"
namespace G3D {
@ -43,6 +44,11 @@ private:
public:
MeshEdgeTable() {
AreaMemoryManager::Ref mm = AreaMemoryManager::create();
table.clearAndSetMemoryManager(mm);
}
void clear() {
table.clear();
}
@ -51,7 +57,7 @@ public:
table.resize(maxV);
}
/**
/*
Inserts the faceIndex into the edge's face list.
The index may be a negative number indicating a backface.
@ -137,7 +143,7 @@ public:
};
/**
/*
Assigns the edge index into the next unassigned edge
index. The edge index may be negative, indicating
a reverse edge.

View file

@ -1,4 +1,4 @@
/**
/*
@file MeshAlgWeld.cpp
The MeshAlg::computeWeld method.
@ -53,7 +53,7 @@ public:
Array<int>& _toOld,
double _radius);
/**
/*
Computes the grid index from an ordinate.
*/
void toGridCoords(Vector3 v, int& x, int& y, int& z) const;

View file

@ -1,4 +1,4 @@
/**
/*
@file MeshBuilder.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file NetMessage.cpp
@maintainer Morgan McGuire, morgan@cs.brown.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file NetworkDevice.cpp
@maintainer Morgan McGuire, morgan@cs.brown.edu
@ -6,8 +6,6 @@
@edited 2006-02-24
*/
#include <stdlib.h>
#include <time.h>
#include "G3D/platform.h"
#include "G3D/TextOutput.h"
#include "G3D/NetworkDevice.h"
@ -18,94 +16,8 @@
#include "G3D/G3DGameUnits.h"
#include "G3D/stringutils.h"
#include "G3D/debug.h"
#include "G3D/networkHelpers.h"
#include <cstring>
#if defined(G3D_LINUX) || defined(G3D_OSX) || defined(G3D_FREEBSD)
# include <sys/types.h>
# include <sys/socket.h>
# include <ifaddrs.h>
# include <netinet/in.h>
# include <net/if.h>
# ifdef __linux__
# include <sys/ioctl.h>
# include <netinet/in.h>
# include <unistd.h>
# include <string.h>
// Match Linux to FreeBSD
# define AF_LINK AF_PACKET
# else
# include <net/if_dl.h>
# include <sys/sockio.h>
# endif
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <sys/ioctl.h>
#include <netinet/if_ether.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <sys/types.h>
#define _alloca alloca
/** Define an error code for non-windows platforms. */
int WSAGetLastError() {
return -1;
}
#define SOCKET_ERROR -1
static std::string socketErrorCode(int code) {
return G3D::format("CODE %d: %s\n", code, strerror(code));
}
static std::string socketErrorCode() {
return socketErrorCode(errno);
}
static const int WSAEWOULDBLOCK = -100;
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
#else
// Windows
static std::string socketErrorCode(int code) {
LPTSTR formatMsg = NULL;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
code,
0,
(LPTSTR)&formatMsg,
0,
NULL);
return G3D::format("CODE %d: %s\n", code, formatMsg);
}
static std::string socketErrorCode() {
return socketErrorCode(GetLastError());
}
#endif
#ifndef _SOCKLEN_T
# if defined(G3D_WIN32) || defined(G3D_OSX)
typedef int socklen_t;
# endif
#endif
namespace G3D {
@ -666,7 +578,7 @@ bool Conduit::messageWaiting() {
}
/**
/*
Increases the send and receive sizes of a socket to 2 MB from 8k
*/
static void increaseBufferSize(SOCKET sock) {

View file

@ -1,13 +1,15 @@
/**
/*
@file PhysicsFrame.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2002-07-09
@edited 2006-01-25
@edited 2010-03-25
*/
#include "G3D/platform.h"
#include "G3D/Any.h"
#include "G3D/stringutils.h"
#include "G3D/PhysicsFrame.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
@ -28,6 +30,37 @@ PhysicsFrame::PhysicsFrame(
}
PhysicsFrame::PhysicsFrame(const Any& a) {
const std::string& n = toLower(a.name());
*this = PhysicsFrame();
if (beginsWith(n, "vector3")) {
*this = PhysicsFrame(Vector3(a));
} else if (beginsWith(n, "matrix3")) {
*this = PhysicsFrame(Matrix3(a));
} else if (beginsWith(n, "cframe") || beginsWith(n, "coordinateframe")) {
*this = PhysicsFrame(CoordinateFrame(a));
} else if (beginsWith(n, "pframe") || beginsWith(n, "physicsframe")) {
if (a.type() == Any::ARRAY) {
a.verifySize(2);
rotation = a[0];
translation = a[1];
} else {
for (Any::AnyTable::Iterator it = a.table().begin(); it.hasMore(); ++it) {
const std::string& n = toLower(it->key);
if (n == "translation") {
translation = it->value;
} else if (n == "rotation") {
rotation = it->value;
} else {
a.verify(false, "Illegal table key: " + it->key);
}
}
}
}
}
PhysicsFrame PhysicsFrame::operator*(const PhysicsFrame& other) const {
PhysicsFrame result;
@ -38,7 +71,7 @@ PhysicsFrame PhysicsFrame::operator*(const PhysicsFrame& other) const {
}
CoordinateFrame PhysicsFrame::toCoordinateFrame() const {
PhysicsFrame::operator CoordinateFrame() const {
CoordinateFrame f;
f.translation = translation;

View file

@ -0,0 +1,80 @@
/*
\file PhysicsFrameSpline.cpp
\author Morgan McGuire, http://graphics.cs.williams.edu
*/
#include "G3D/PhysicsFrameSpline.h"
#include "G3D/Any.h"
#include "G3D/stringutils.h"
namespace G3D {
PhysicsFrameSpline::PhysicsFrameSpline() {}
PhysicsFrameSpline::PhysicsFrameSpline(const Any& any) {
*this = any;
}
PhysicsFrameSpline& PhysicsFrameSpline::operator=(const Any& any) {
const std::string& n = toLower(any.name());
*this = PhysicsFrameSpline();
if (n == "physicsframespline" || n == "pframespline") {
any.verifyName("PhysicsFrameSpline", "PFrameSpline");
for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
const std::string& k = toLower(it->key);
if (k == "cyclic") {
cyclic = it->value;
} else if (k == "control") {
const Any& v = it->value;
v.verifyType(Any::ARRAY);
control.resize(v.size());
for (int i = 0; i < control.size(); ++i) {
control[i] = v[i];
}
if (! any.containsKey("time")) {
time.resize(control.size());
for (int i = 0; i < time.size(); ++i) {
time[i] = i;
}
}
} else if (k == "finalinterval") {
finalInterval = it->value;
} else if (k == "time") {
const Any& v = it->value;
v.verifyType(Any::ARRAY);
time.resize(v.size());
for (int i = 0; i < time.size(); ++i) {
time[i] = v[i];
}
}
}
} else {
// Must be a PhysicsFrame constructor of some kind
append(any);
}
return *this;
}
void PhysicsFrameSpline::correct(PhysicsFrame& frame) const {
frame.rotation.unitize();
}
void PhysicsFrameSpline::ensureShortestPath(PhysicsFrame* A, int N) const {
for (int i = 1; i < N; ++i) {
const Quat& p = A[i - 1].rotation;
Quat& q = A[i].rotation;
float cosphi = p.dot(q);
if (cosphi < 0) {
// Going the long way, so change the order
q = -q;
}
}
}
}

View file

@ -1,4 +1,4 @@
/**
/*
@file Plane.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file PrecomputedRandom.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Quat.cpp
Quaternion implementation based on Watt & Watt page 363
@ -6,10 +6,12 @@
@author Morgan McGuire, graphics3d.com
@created 2002-01-23
@edited 2006-01-31
@edited 2010-03-31
*/
#include "G3D/Quat.h"
#include "G3D/Any.h"
#include "G3D/stringutils.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
@ -28,8 +30,22 @@ Quat Quat::fromAxisAngleRotation(
}
Quat::Quat(
const Matrix3& rot) {
Quat::Quat(const class Any& a) {
*this = Quat();
if (beginsWith(toLower(a.name()), "matrix3")) {
*this = a;
} else {
a.verifyName("Quat");
a.verifyType(Any::ARRAY);
x = a[0];
y = a[1];
z = a[2];
w = a[3];
}
}
Quat::Quat(const Matrix3& rot) {
static const int plus1mod3[] = {1, 2, 0};

View file

@ -1,4 +1,4 @@
/**
/*
@file Random.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Ray.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Rect2D.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file ReferenceCount.cpp
Reference Counting Garbage Collector for C++

View file

@ -1,4 +1,4 @@
/**
/*
@file RegistryUtil.cpp
@created 2006-04-06

View file

@ -1,4 +1,4 @@
/**
/*
@file Sphere.cpp
Sphere class

View file

@ -1,4 +1,4 @@
/**
/*
@file Stopwatch.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -27,6 +27,7 @@
#include "G3D/Table.h"
#include "G3D/GMutex.h"
#include "G3D/units.h"
#include "G3D/FileSystem.h"
#include <time.h>
#include <cstring>
@ -80,9 +81,9 @@
#endif
// SIMM include
#ifdef __SSE__
#ifdef __SSE__ /* G3DFIX: Only Intel Vector Extension enabled */
#include <xmmintrin.h>
#endif
#endif /* G3DFIX: Only Intel Vector Extension enabled */
namespace G3D {
@ -340,40 +341,6 @@ void getG3DVersion(std::string& s) {
s = cstr;
}
#if 0 // TODO: delete
struct Directory {
std::string path;
Array<std::string> contents;
};
static bool maybeAddDirectory(const std::string& newPath, Array<Directory>& directoryArray, bool recurse = true) {
if (fileExists(newPath)) {
Directory& d = directoryArray.next();
d.path = newPath;
getFiles(pathConcat(newPath, "*"), d.contents);
Array<std::string> dirs;
getDirs(pathConcat(newPath, "*"), dirs);
d.contents.append(dirs);
if (recurse) {
// Look for subdirectories
static const std::string subdirs[] =
{"font", "gui", "SuperShader", "cubemap", "icon", "material", "image", "md2", "md3", "ifs", "3ds", "sky", ""};
for (int j = 0; j < dirs.size(); ++j) {
for (int i = 0; ! subdirs[i].empty(); ++i) {
if (dirs[j] == subdirs[i]) {
maybeAddDirectory(pathConcat(newPath, dirs[j]), directoryArray, false);
}
}
}
}
return true;
} else {
return false;
}
}
#endif
std::string System::findDataFile
(const std::string& full,
@ -385,14 +352,14 @@ std::string System::findDataFile
// First check if the file exists as requested. This will go
// through the FileSystemCache, so most calls do not touch disk.
if (fileExists(full)) {
if (FileSystem::exists(full)) {
return full;
}
// Now check where we previously found this file.
std::string* last = lastFound.getPointer(full);
if (last != NULL) {
if (fileExists(*last)) {
if (FileSystem::exists(*last)) {
// Even if cwd has changed the file is still present.
// We won't notice if it has been deleted, however.
return *last;
@ -405,20 +372,33 @@ std::string System::findDataFile
// Places to look
static Array<std::string> directoryArray;
std::string initialAppDataDir(instance().m_appDataDir);
const char* g3dPath = getenv("G3DDATA");
if (directoryArray.size() == 0) {
// Initialize the directory array
RealTime t0 = System::time();
Array<std::string> baseDirArray;
std::string initialAppDataDir(instance().m_appDataDir);
baseDirArray.append("");
if (! initialAppDataDir.empty()) {
baseDirArray.append(initialAppDataDir);
}
const char* g3dPath = getenv("G3DDATA");
# ifdef G3D_WIN32
if (g3dPath == NULL) {
// If running the demos under visual studio from the G3D.sln file,
// this will locate the data directory.
const char* paths[] = {"../data-files/", "../../data-files/", "../../../data-files/", NULL};
for (int i = 0; paths[i]; ++i) {
if (FileSystem::exists(pathConcat(paths[i], "G3D-DATA-README.TXT"))) {
g3dPath = paths[i];
break;
}
}
}
# endif
if (g3dPath && (initialAppDataDir != g3dPath)) {
baseDirArray.append(g3dPath);
@ -428,11 +408,11 @@ std::string System::findDataFile
{"font", "gui", "SuperShader", "cubemap", "icon", "material", "image", "md2", "md3", "ifs", "3ds", "sky", ""};
for (int j = 0; j < baseDirArray.size(); ++j) {
std::string d = baseDirArray[j];
if (fileExists(d)) {
if ((d == "") || FileSystem::exists(d)) {
directoryArray.append(d);
for (int i = 0; ! subdirs[i].empty(); ++i) {
const std::string& p = pathConcat(d, subdirs[i]);
if (fileExists(p)) {
if (FileSystem::exists(p)) {
directoryArray.append(p);
}
}
@ -444,7 +424,7 @@ std::string System::findDataFile
for (int i = 0; i < directoryArray.size(); ++i) {
const std::string& p = pathConcat(directoryArray[i], full);
if (fileExists(p)) {
if (FileSystem::exists(p)) {
lastFound.set(full, p);
return p;
}
@ -454,9 +434,29 @@ std::string System::findDataFile
// Generate an error message
std::string locations;
for (int i = 0; i < directoryArray.size(); ++i) {
locations += pathConcat(directoryArray[i], full) + "\n";
locations += "\'" + pathConcat(directoryArray[i], full) + "'\n";
}
alwaysAssertM(false, "Could not find '" + full + "' in:\n" + locations);
std::string msg = "Could not find '" + full + "'.\n\n";
msg += "cwd = \'" + FileSystem::currentDirectory() + "\'\n";
if (g3dPath) {
msg += "G3DDATA = ";
if (! FileSystem::exists(g3dPath)) {
msg += "(illegal path!) ";
}
msg += std::string(g3dPath) + "\'\n";
} else {
msg += "(G3DDATA environment variable is undefined)\n";
}
msg += "GApp::Settings.dataDir = ";
if (! FileSystem::exists(initialAppDataDir)) {
msg += "(illegal path!) ";
}
msg += std::string(initialAppDataDir) + "\'\n";
msg += "\nLocations searched:\n" + locations;
alwaysAssertM(false, msg);
}
// Not found
@ -474,19 +474,23 @@ std::string demoFindData(bool errorIfNotFound) {
if (g3dPath) {
return g3dPath;
# ifdef G3D_WIN32
} else if (fileExists("../data")) {
} else if (FileSystem::exists("../data")) {
// G3D install on Windows
return "../data";
} else if (fileExists("../data-files")) {
} else if (FileSystem::exists("../data-files")) {
// G3D source on Windows
return "../data-files";
} else if (FileSystem::exists("c:/libraries/G3D/data")) {
return "c:/libraries/G3D/data";
# else
} else if (fileExists("../../../../data")) {
} else if (FileSystem::exists("../../../../data")) {
// G3D install on Unix
return "../../../../data";
} else if (fileExists("../../../../data-files")) {
} else if (FileSystem::exists("../../../../data-files")) {
// G3D source on Unix
return "../../../../data-files";
} else if (FileSystem::exists("/usr/local/G3D/data")) {
return "/usr/local/G3D/data";
# endif
} else {
return "";
@ -560,7 +564,7 @@ void System::getStandardProcessorExtensions() {
#endif
}
#if defined(G3D_WIN32) && !defined(G3D_64BIT)
#if defined(G3D_WIN32) && !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit Windows platforms */
#pragma message("Port System::memcpy SIMD to all platforms")
/** Michael Herf's fast memcpy */
void memcpyMMX(void* dst, const void* src, int nbytes) {
@ -611,7 +615,7 @@ void memcpyMMX(void* dst, const void* src, int nbytes) {
#endif
void System::memcpy(void* dst, const void* src, size_t numBytes) {
#if defined(G3D_WIN32) && !defined(G3D_64BIT)
#if defined(G3D_WIN32) && !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit Windows platforms */
memcpyMMX(dst, src, numBytes);
#else
::memcpy(dst, src, numBytes);
@ -621,7 +625,7 @@ void System::memcpy(void* dst, const void* src, size_t numBytes) {
/** Michael Herf's fastest memset. n32 must be filled with the same
character repeated. */
#if defined(G3D_WIN32) && !defined(G3D_64BIT)
#if defined(G3D_WIN32) && !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit Windows platforms */
#pragma message("Port System::memfill SIMD to all platforms")
// On x86 processors, use MMX
@ -660,7 +664,7 @@ void memfill(void *dst, int n32, unsigned long i) {
void System::memset(void* dst, uint8 value, size_t numBytes) {
#if defined(G3D_WIN32) && !defined(G3D_64BIT)
#if defined(G3D_WIN32) && !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit Windows platforms */
uint32 v = value;
v = v + (v << 8) + (v << 16) + (v << 24);
G3D::memfill(dst, v, numBytes);
@ -916,9 +920,12 @@ RealTime System::time() {
////////////////////////////////////////////////////////////////
#define REALPTR_TO_USERPTR(x) ((uint8*)(x) + sizeof (void *))
#define USERPTR_TO_REALPTR(x) ((uint8*)(x) - sizeof (void *))
#define REALBLOCK_SIZE(x) ((x) + sizeof (void *))
#define REALPTR_TO_USERPTR(x) ((uint8*)(x) + sizeof(uint32))
#define USERPTR_TO_REALPTR(x) ((uint8*)(x) - sizeof(uint32))
#define USERSIZE_TO_REALSIZE(x) ((x) + sizeof(uint32))
#define REALSIZE_FROM_USERPTR(u) (*(uint32*)USERPTR_TO_REALPTR(ptr) + sizeof(uint32))
#define USERSIZE_FROM_USERPTR(u) (*(uint32*)USERPTR_TO_REALPTR(ptr))
class BufferPool {
public:
@ -943,13 +950,19 @@ public:
private:
/** Pointer given to the program. Unless in the tiny heap, the user size of the block is stored right in front of the pointer as a uint32.*/
typedef void* UserPtr;
/** Actual block allocated on the heap */
typedef void* RealPtr;
class MemBlock {
public:
void* ptr;
size_t bytes;
UserPtr ptr;
size_t bytes;
inline MemBlock() : ptr(NULL), bytes(0) {}
inline MemBlock(void* p, size_t b) : ptr(p), bytes(b) {}
inline MemBlock(UserPtr p, size_t b) : ptr(p), bytes(b) {}
};
MemBlock smallPool[maxSmallBuffers];
@ -1006,13 +1019,13 @@ private:
/**
Malloc out of the tiny heap. Returns NULL if allocation failed.
*/
inline void* tinyMalloc(size_t bytes) {
inline UserPtr tinyMalloc(size_t bytes) {
// Note that we ignore the actual byte size
// and create a constant size block.
(void)bytes;
assert(tinyBufferSize >= bytes);
void* ptr = NULL;
UserPtr ptr = NULL;
if (tinyPoolSize > 0) {
--tinyPoolSize;
@ -1036,20 +1049,20 @@ private:
}
/** Returns true if this is a pointer into the tiny heap. */
bool inTinyHeap(void* ptr) {
bool inTinyHeap(UserPtr ptr) {
return
(ptr >= tinyHeap) &&
(ptr < (uint8*)tinyHeap + maxTinyBuffers * tinyBufferSize);
}
void tinyFree(void* ptr) {
void tinyFree(UserPtr ptr) {
assert(ptr);
assert(tinyPoolSize < maxTinyBuffers);
// "Tried to free a tiny pool buffer when the tiny pool freelist is full.");
# ifdef G3D_DEBUG
if (tinyPoolSize > 0) {
void* prevOnHeap = tinyPool[tinyPoolSize - 1];
UserPtr prevOnHeap = tinyPool[tinyPoolSize - 1];
assert(prevOnHeap != ptr);
// "System::malloc heap corruption detected: "
// "the last two pointers on the freelist are identical (during tinyFree).");
@ -1066,7 +1079,8 @@ private:
void flushPool(MemBlock* pool, int& poolSize) {
for (int i = 0; i < poolSize; ++i) {
::free(pool[i].ptr);
bytesAllocated -= USERSIZE_TO_REALSIZE(pool[i].bytes);
::free(USERPTR_TO_REALPTR(pool[i].ptr));
pool[i].ptr = NULL;
pool[i].bytes = 0;
}
@ -1074,24 +1088,23 @@ private:
}
/** Allocate out of a specific pool-> Return NULL if no suitable
memory was found.
*/
void* malloc(MemBlock* pool, int& poolSize, size_t bytes) {
/** Allocate out of a specific pool. Return NULL if no suitable
memory was found. */
UserPtr malloc(MemBlock* pool, int& poolSize, size_t bytes) {
// OPT: find the smallest block that satisfies the request.
// See if there's something we can use in the buffer pool->
// See if there's something we can use in the buffer pool.
// Search backwards since usually we'll re-use the last one.
for (int i = (int)poolSize - 1; i >= 0; --i) {
if (pool[i].bytes >= bytes) {
// We found a suitable entry in the pool->
// We found a suitable entry in the pool.
// No need to offset the pointer; it is already offset
void* ptr = pool[i].ptr;
UserPtr ptr = pool[i].ptr;
// Remove this element from the pool
// Remove this element from the pool, replacing it with
// the one from the end (same as Array::fastRemove)
--poolSize;
pool[i] = pool[poolSize];
@ -1155,6 +1168,8 @@ public:
~BufferPool() {
::free(tinyHeap);
flushPool(smallPool, smallPoolSize);
flushPool(medPool, medPoolSize);
#if 0 //-------------------------------- old mutex
# ifdef G3D_WIN32
DeleteCriticalSection(&mutex);
@ -1165,7 +1180,7 @@ public:
}
void* realloc(void* ptr, size_t bytes) {
UserPtr realloc(UserPtr ptr, size_t bytes) {
if (ptr == NULL) {
return malloc(bytes);
}
@ -1177,7 +1192,7 @@ public:
} else {
// Free the old pointer and malloc
void* newPtr = malloc(bytes);
UserPtr newPtr = malloc(bytes);
System::memcpy(newPtr, ptr, tinyBufferSize);
tinyFree(ptr);
return newPtr;
@ -1187,28 +1202,28 @@ public:
// In one of our heaps.
// See how big the block really was
size_t realSize = *(uint32*)USERPTR_TO_REALPTR(ptr);
if (bytes <= realSize) {
size_t userSize = USERSIZE_FROM_USERPTR(ptr);
if (bytes <= userSize) {
// The old block was big enough.
return ptr;
}
// Need to reallocate
void* newPtr = malloc(bytes);
System::memcpy(newPtr, ptr, realSize);
// Need to reallocate and move
UserPtr newPtr = malloc(bytes);
System::memcpy(newPtr, ptr, userSize);
free(ptr);
return newPtr;
}
}
void* malloc(size_t bytes) {
UserPtr malloc(size_t bytes) {
lock();
++totalMallocs;
if (bytes <= tinyBufferSize) {
void* ptr = tinyMalloc(bytes);
UserPtr ptr = tinyMalloc(bytes);
if (ptr) {
++mallocsFromTinyPool;
@ -1222,7 +1237,7 @@ public:
// through to a small buffer
if (bytes <= smallBufferSize) {
void* ptr = malloc(smallPool, smallPoolSize, bytes);
UserPtr ptr = malloc(smallPool, smallPoolSize, bytes);
if (ptr) {
++mallocsFromSmallPool;
@ -1235,7 +1250,7 @@ public:
// through into a medium allocation because that would
// waste the medium buffer's resources.
void* ptr = malloc(medPool, medPoolSize, bytes);
UserPtr ptr = malloc(medPool, medPoolSize, bytes);
if (ptr) {
++mallocsFromMedPool;
@ -1245,37 +1260,37 @@ public:
}
}
bytesAllocated += REALBLOCK_SIZE(bytes);
bytesAllocated += USERSIZE_TO_REALSIZE(bytes);
unlock();
// Heap allocate
// Allocate 4 extra bytes for our size header (unfortunate,
// since malloc already added its own header).
void* ptr = ::malloc(REALBLOCK_SIZE(bytes));
RealPtr ptr = ::malloc(USERSIZE_TO_REALSIZE(bytes));
if (ptr == NULL) {
// Flush memory pools to try and recover space
flushPool(smallPool, smallPoolSize);
flushPool(medPool, medPoolSize);
ptr = ::malloc(REALBLOCK_SIZE(bytes));
ptr = ::malloc(USERSIZE_TO_REALSIZE(bytes));
}
if (ptr == NULL) {
if ((System::outOfMemoryCallback() != NULL) &&
(System::outOfMemoryCallback()(REALBLOCK_SIZE(bytes), true) == true)) {
(System::outOfMemoryCallback()(USERSIZE_TO_REALSIZE(bytes), true) == true)) {
// Re-attempt the malloc
ptr = ::malloc(REALBLOCK_SIZE(bytes));
ptr = ::malloc(USERSIZE_TO_REALSIZE(bytes));
}
}
if (ptr == NULL) {
if (System::outOfMemoryCallback() != NULL) {
// Notify the application
System::outOfMemoryCallback()(REALBLOCK_SIZE(bytes), false);
System::outOfMemoryCallback()(USERSIZE_TO_REALSIZE(bytes), false);
}
# ifdef G3D_DEBUG
debugPrintf("::malloc(%d) returned NULL\n", (int)REALBLOCK_SIZE(bytes));
debugPrintf("::malloc(%d) returned NULL\n", (int)USERSIZE_TO_REALSIZE(bytes));
# endif
debugAssertM(ptr != NULL,
"::malloc returned NULL. Either the "
@ -1290,7 +1305,7 @@ public:
}
void free(void* ptr) {
void free(UserPtr ptr) {
if (ptr == NULL) {
// Free does nothing on null pointers
return;
@ -1305,7 +1320,7 @@ public:
return;
}
uint32 bytes = *(uint32*)USERPTR_TO_REALPTR(ptr);
uint32 bytes = USERSIZE_FROM_USERPTR(ptr);
lock();
if (bytes <= smallBufferSize) {
@ -1323,7 +1338,7 @@ public:
return;
}
}
bytesAllocated -= REALBLOCK_SIZE(bytes);
bytesAllocated -= USERSIZE_TO_REALSIZE(bytes);
unlock();
// Free; the buffer pools are full or this is too big to store.
@ -1677,7 +1692,7 @@ std::string System::currentDateString() {
// VC on Intel
void System::cpuid(CPUIDFunction func, uint32& areg, uint32& breg, uint32& creg, uint32& dreg) {
#if !defined(G3D_64BIT)
#if !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit platform */
// Can't copy from assembler direct to a function argument (which is on the stack) in VC.
uint32 a,b,c,d;
@ -1695,14 +1710,14 @@ void System::cpuid(CPUIDFunction func, uint32& areg, uint32& breg, uint32& creg,
breg = b;
creg = c;
dreg = d;
#else
int CPUInfo[4];
__cpuid(CPUInfo, func);
memcpy(&areg, &CPUInfo[0], 4);
memcpy(&breg, &CPUInfo[1], 4);
memcpy(&creg, &CPUInfo[2], 4);
memcpy(&dreg, &CPUInfo[3], 4);
#endif
#else /* G3DFIX: Don't check if on 64-bit platform */
int CPUInfo[4];
__cpuid(CPUInfo, func);
memcpy(&areg, &CPUInfo[0], 4);
memcpy(&breg, &CPUInfo[1], 4);
memcpy(&creg, &CPUInfo[2], 4);
memcpy(&dreg, &CPUInfo[3], 4);
#endif /* G3DFIX: Don't check if on 64-bit platform */
}
#elif defined(G3D_OSX) && ! defined(G3D_OSX_INTEL)

View file

@ -1,4 +1,4 @@
/**
/*
@file TextInput.cpp
@author Morgan McGuire, graphics3d.com
@ -6,7 +6,7 @@
@cite Based on a lexer written by Aaron Orenstein.
@created 2001-11-27
@edited 2008-07-14
@edited 2010-07-03
*/
#include "G3D/fileutils.h"
@ -33,37 +33,46 @@ Token TextInput::readSignificant() {
double Token::number() const {
if (_type == NUMBER) {
std::string s = toLower(_string);
if (s == "-1.#ind00") {
return nan();
}
if (s == "1.#inf00") {
return inf();
}
if (s == "-1.#inf00") {
return -inf();
}
double n;
if ((_string.length() > 2) &&
(_string[0] == '0') &&
(_string[1] == 'x')) {
// Hex
uint32 i;
sscanf(_string.c_str(), "%x", &i);
n = i;
} else {
sscanf(_string.c_str(), "%lg", &n);
}
return n;
return TextInput::parseNumber(_string);
} else {
return 0.0;
}
}
bool TextInput::parseBoolean(const std::string& _string) {
return toLower(_string) == "true";
}
double TextInput::parseNumber(const std::string& _string) {
std::string s = toLower(_string);
if (s == "-1.#ind00" || s == "nan") {
return nan();
}
if (s == "1.#inf00" || s == "inf" || s == "+inf") {
return inf();
}
if (s == "-1.#inf00" || s == "-inf") {
return -inf();
}
double n;
if ((_string.length() > 2) &&
(_string[0] == '0') &&
(_string[1] == 'x')) {
// Hex
uint32 i;
sscanf(_string.c_str(), "%x", &i);
n = i;
} else {
sscanf(_string.c_str(), "%lg", &n);
}
return n;
}
TextInput::Settings::Settings () :
cppBlockComments(true),
cppLineComments(true),
@ -78,7 +87,8 @@ TextInput::Settings::Settings () :
singleQuoteCharacter('\''),
sourceFileName(),
startingLineNumberOffset(0),
msvcSpecials(true),
msvcFloatSpecials(true),
simpleFloatSpecials(true),
proofSymbols(false),
caseSensitive(true)
{
@ -117,6 +127,41 @@ Token TextInput::read() {
}
}
std::string TextInput::readUntilNewlineAsString() {
/*
// Reset the read position back to the start of that token
currentCharOffset = t.bytePosition();
lineNumber = t.line();
charNumber = t.character();
stack.clear();
if (currentCharOffset == buffer.size()) {
// End of file
return "";
}
*/
std::string s;
// Read until newline or eof
char c = '\0';
do {
c = buffer[currentCharOffset];
if (c == '\r' || c == '\n') {
// Done
break;
} else {
s += c;
++currentCharOffset;
++charNumber;
}
} while (currentCharOffset < buffer.size());
return s;
}
static void toUpper(Set<std::string>& set) {
Array<std::string> symbols;
set.getMembers(symbols);
@ -198,6 +243,7 @@ int TextInput::peekInputChar(int distance) {
Token TextInput::nextToken() {
Token t;
t._bytePosition = currentCharOffset;
t._line = lineNumber;
t._character = charNumber;
t._type = Token::END;
@ -215,21 +261,24 @@ Token TextInput::nextToken() {
whitespaceDone = true;
// generate newlines tokens for '\n' and '\r' and '\r\n'
if (options.generateNewlineTokens && isNewline(c)) {
t._type = Token::NEWLINE;
t._extendedType = Token::NEWLINE_TYPE;
t._string = c;
while (isWhiteSpace(c)) {
if (options.generateNewlineTokens && isNewline(c)) {
t._type = Token::NEWLINE;
t._extendedType = Token::NEWLINE_TYPE;
t._bytePosition = currentCharOffset;
t._line = lineNumber;
t._character = charNumber;
t._string = c;
int c2 = peekInputChar(1);
if (c == '\r' && c2 == '\n') {
t._string += c2;
}
int c2 = peekInputChar(1);
if (c == '\r' && c2 == '\n') {
t._string += c2;
}
eatInputChar();
return t;
} else {
// Consume whitespace
while (isWhiteSpace(c)) {
eatInputChar();
return t;
} else {
// Consume the single whitespace
c = eatAndPeekInputChar();
}
}
@ -237,6 +286,7 @@ Token TextInput::nextToken() {
// update line and character number to include discarded whitespace
t._line = lineNumber;
t._character = charNumber;
t._bytePosition = currentCharOffset;
int c2 = peekInputChar(1);
@ -293,13 +343,16 @@ Token TextInput::nextToken() {
eatInputChar();
eatInputChar();
// c is the next character we'll read, c2 is the one after *that*
c = peekInputChar();
c2 = peekInputChar(1);
while (! ((c == '*') && (c2 == '/')) && (c != EOF)) {
commentString += c;
// Eat input char may consume more than one character if there is a newline
eatInputChar();
c = c2;
c = peekInputChar();
c2 = peekInputChar(1);
}
eatInputChar(); // eat closing '*'
@ -324,6 +377,7 @@ Token TextInput::nextToken() {
t._line = lineNumber;
t._character = charNumber;
t._bytePosition = currentCharOffset;
// handle EOF
if (c == EOF) {
@ -380,15 +434,29 @@ Token TextInput::nextToken() {
return t;
}
if (options.signedNumbers
&& (isDigit(c) || (c == '.' && isDigit(peekInputChar(1))))) {
if (options.signedNumbers) {
if (isDigit(c) || (c == '.' && isDigit(peekInputChar(1)))) {
// Negative number. 'c' is still the first digit, and is
// the next input char.
// Negative number. 'c' is still the first digit, and is
// the next input char.
goto numLabel;
goto numLabel;
} else {
char terminal = peekInputChar(3);
if (options.simpleFloatSpecials && (c == 'i') && (peekInputChar(1) == 'n') && (peekInputChar(2) == 'f') &&
! isLetter(terminal) && (terminal != '_')) {
// negative infinity
t._type = Token::NUMBER;
t._extendedType = Token::FLOATING_POINT_TYPE;
t._string = "-inf";
eatInputChar(); // i
eatInputChar(); // n
eatInputChar(); // f
return t;
}
}
}
// plain -
return t;
@ -403,13 +471,26 @@ Token TextInput::nextToken() {
return t;
}
if (options.signedNumbers
&& (isDigit(c) || (c == '.' && isDigit(peekInputChar(1))))) {
if (options.signedNumbers) {
if (isDigit(c) || (c == '.' && isDigit(peekInputChar(1)))) {
// Positive number. 'c' is still the first digit, and is
// the next input char.
// Positive number. 'c' is still the first digit, and is
// the next input char.
goto numLabel;
goto numLabel;
} else {
char terminal = peekInputChar(3);
if (options.simpleFloatSpecials && (c == 'i') && (peekInputChar(1) == 'n') && (peekInputChar(2) == 'f') &&
! isLetter(terminal) && (terminal != '_')) {
// positive infinity
t._type = Token::NUMBER;
t._extendedType = Token::FLOATING_POINT_TYPE;
t._string = "+inf";
eatInputChar(); // i
eatInputChar(); // n
eatInputChar(); // f
return t;
}
}
}
return t;
@ -596,7 +677,7 @@ numLabel:
c = eatAndPeekInputChar();
// Floating point specials (msvc format only)
if (options.msvcSpecials && (c == '#')) {
if (options.msvcFloatSpecials && (c == '#')) {
isSpecial = true;
// We are reading a floating point special value
// of the form -1.#IND00, -1.#INF00, or 1.#INF00
@ -607,8 +688,7 @@ numLabel:
}
if (test != 'I') {
throw BadMSVCSpecial
(
"Incorrect floating-point special (inf or nan) "
("Incorrect floating-point special (inf or nan) "
"format.",
t.line(), charNumber);
}
@ -714,6 +794,10 @@ numLabel:
}
}
if (options.simpleFloatSpecials && ((t._string == "nan") || (t._string == "inf"))) {
t._type = Token::NUMBER;
t._extendedType = Token::FLOATING_POINT_TYPE;
}
return t;
} else if (c == '\"') {
@ -1052,6 +1136,8 @@ static const char* tokenTypeToString(Token::Type t) {
return "Token::NUMBER";
case Token::END:
return "Token::END";
case Token::NEWLINE:
return "Token::NEWLINE";
default:
debugAssertM(false, "Fell through switch");
return "?";

View file

@ -1,17 +1,18 @@
/**
/*
@file TextOutput.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2004-06-21
@edited 2006-08-14
@edited 2010-03-14
Copyright 2000-2006, Morgan McGuire.
Copyright 2000-2010, Morgan McGuire.
All rights reserved.
*/
#include "G3D/TextOutput.h"
#include "G3D/Log.h"
#include "G3D/fileutils.h"
#include "G3D/FileSystem.h"
namespace G3D {
@ -392,17 +393,17 @@ void TextOutput::vprintf(const char* formatString, va_list argPtr) {
void TextOutput::commit(bool flush) {
std::string p = filenamePath(filename);
if (! fileExists(p, false)) {
createDirectory(p);
if (! FileSystem::exists(p, false)) {
FileSystem::createDirectory(p);
}
FILE* f = fopen(filename.c_str(), "wb");
FILE* f = FileSystem::fopen(filename.c_str(), "wb");
debugAssertM(f, "Could not open \"" + filename + "\"");
fwrite(data.getCArray(), 1, data.size(), f);
if (flush) {
fflush(f);
}
fclose(f);
FileSystem::fclose(f);
}

View file

@ -1,4 +1,4 @@
/**
/*
@file Triangle.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file UprightFrame.cpp
Box class

View file

@ -1,4 +1,4 @@
/**
/*
@file Vector2.cpp
2D vector class, used for texture coordinates primarily.

View file

@ -1,4 +1,4 @@
/**
/*
@file Vector2int16.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Vector3.cpp
3D vector class
@ -25,6 +25,7 @@
#include "G3D/Vector2.h"
#include "G3D/Color3.h"
#include "G3D/Vector4int8.h"
#include "G3D/Vector4.h"
#include "G3D/Vector3int32.h"
#include "G3D/Any.h"
@ -104,11 +105,7 @@ Vector3::Axis Vector3::primaryAxis() const {
size_t Vector3::hashCode() const {
unsigned int xhash = (*(int*)(void*)(&x));
unsigned int yhash = (*(int*)(void*)(&y));
unsigned int zhash = (*(int*)(void*)(&z));
return xhash + (yhash * 37) + (zhash * 101);
return Vector4(*this, 0.0f).hashCode();
}
std::ostream& operator<<(std::ostream& os, const Vector3& v) {

View file

@ -1,4 +1,4 @@
/**
/*
@file Vector3int16.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file Vector3int32.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,10 +1,10 @@
/**
/*
@file Vector4.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2001-07-09
@edited 2009-11-29
@edited 2010-07-05
*/
#include <stdlib.h>
@ -69,12 +69,7 @@ const Vector4& Vector4::nan() {
size_t Vector4::hashCode() const {
unsigned int xhash = (*(int*)(void*)(&x));
unsigned int yhash = (*(int*)(void*)(&y));
unsigned int zhash = (*(int*)(void*)(&z));
unsigned int whash = (*(int*)(void*)(&w));
return xhash + (yhash * 37) + (zhash * 101) + (whash * 241);
return HashTrait<uint128>::hashCode(*((uint128*)this));
}

View file

@ -1,4 +1,4 @@
/**
/*
@file Vector4int8.cpp
Homogeneous vector class.

View file

@ -1,4 +1,4 @@
/**
/*
@file Welder.cpp
@author Morgan McGuire, Kyle Whitson, Corey Taylor
@ -74,7 +74,7 @@ namespace G3D { namespace _internal {
class WeldHelper {
private:
/** Used by getIndex and updateTriLists */
/** Used by getIndex and updateTriLists. Deallocating this is slow. */
PointHashGrid<VNTi> weldGrid;
Array<Vector3>* outputVertexArray;
@ -88,7 +88,7 @@ private:
float normalSmoothingAngle;
/**
/*
Returns the index of the vertex in
outputVertexArray/outputNormalArray/outputTexCoordArray
that is within the global tolerances of v,n,t. If there
@ -136,7 +136,7 @@ private:
}
/**
/*
Updates each indexArray to refer to vertices in the
outputVertexArray.
@ -157,23 +157,25 @@ private:
int numTriLists = indexArrayArray.size();
int u = 0;
for (int t = 0; t < numTriLists; ++t) {
Array<int>& triList = *(indexArrayArray[t]);
if (indexArrayArray[t] != NULL) {
Array<int>& triList = *(indexArrayArray[t]);
// For all vertices in this list
for (int v = 0; v < triList.size(); ++v) {
// This vertex mapped to u in the flatVertexArray
triList[v] = getIndex(vertexArray[u], normalArray[u], texCoordArray[u]);
// For all vertices in this list
for (int v = 0; v < triList.size(); ++v) {
// This vertex mapped to u in the flatVertexArray
triList[v] = getIndex(vertexArray[u], normalArray[u], texCoordArray[u]);
/*
# ifdef G3D_DEBUG
{
int i = triList[v];
Vector3 N = normalArray[i];
debugAssertM(N.length() > 0.9f, "Produced non-unit normal");
}
# endif
*/
++u;
/*
# ifdef G3D_DEBUG
{
int i = triList[v];
Vector3 N = normalArray[i];
debugAssertM(N.length() > 0.9f, "Produced non-unit normal");
}
# endif
*/
++u;
}
}
}
}
@ -190,11 +192,13 @@ private:
int numTriLists = indexArrayArray.size();
for (int t = 0; t < numTriLists; ++t) {
const Array<int>& triList = *(indexArrayArray[t]);
for (int v = 0; v < triList.size(); ++v) {
int i = triList[v];
unrolledVertexArray.append(vertexArray[i]);
unrolledTexCoordArray.append(texCoordArray[i]);
if (indexArrayArray[t] != NULL) {
const Array<int>& triList = *(indexArrayArray[t]);
for (int v = 0; v < triList.size(); ++v) {
int i = triList[v];
unrolledVertexArray.append(vertexArray[i]);
unrolledTexCoordArray.append(texCoordArray[i]);
}
}
}
}
@ -214,15 +218,16 @@ private:
const Vector3& e1 = vertexArray[v + 2] - vertexArray[v];
// Note that the length may be zero in the case of sliver polygons, e.g.,
// those correcting a T-junction.
const Vector3& n = e0.cross(e1).directionOrZero();
// those correcting a T-junction. Scale up by 256 to avoid underflow when
// multiplying very small edges
const Vector3& n = (e0.cross(e1 * 256.0f)).directionOrZero();
// Append the normal once per vertex.
faceNormalArray.append(n, n, n);
}
}
/**
/*
Computes @a smoothNormalArray, whose elements are those of normalArray averaged
with neighbors within the angular cutoff.
*/
@ -230,15 +235,16 @@ private:
const Array<Vector3>& vertexArray,
const Array<Vector3>& normalArray,
Array<Vector3>& smoothNormalArray) {
// Create an area memory manager for fast deallocation
MemoryManager::Ref mm = AreaMemoryManager::create(iRound(sizeof(VN) * normalArray.size() * 1.5));
if (normalSmoothingAngle <= 0) {
smoothNormalArray = normalArray;
return;
}
// Create an area memory manager for fast deallocation
MemoryManager::Ref mm = AreaMemoryManager::create(iRound(sizeof(VN) * normalArray.size() * 1.5));
const float cosThresholdAngle = (float)cos(normalSmoothingAngle);
debugAssert(vertexArray.size() == normalArray.size());
@ -250,6 +256,7 @@ private:
grid.insert(VN(vertexArray[v], normalArray[v]));
}
// TODO: this step could be done on multiple threads
for (int v = 0; v < normalArray.size(); ++v) {
// Compute the sum of all nearby normals within the cutoff angle.
// Search within the vertexWeldRadius, since those are the vertices
@ -265,8 +272,8 @@ private:
const float cosAngle = N.dot(original);
if (cosAngle > cosThresholdAngle) {
// This normal is close enough to consider
sum += N;
// This normal is close enough to consider. Avoid underflow by scaling up
sum += (N * 256.0f);
}
++it;
}
@ -290,7 +297,7 @@ private:
public:
/**
/*
Algorithm:
1. Unroll the indexed triangle list into a triangle list, where
@ -366,8 +373,9 @@ public:
}
WeldHelper(float vertRadius) :
weldGrid(vertRadius),
vertexWeldRadius(vertRadius) {}
weldGrid(vertRadius, AreaMemoryManager::create()),
vertexWeldRadius(vertRadius) {
}
};
} // Internal
@ -382,6 +390,7 @@ void Welder::weld(
_internal::WeldHelper(settings.vertexWeldRadius).process(
vertexArray, texCoordArray, normalArray, indexArrayArray,
settings.normalSmoothingAngle, settings.textureWeldRadius, settings.normalWeldRadius);
}

216
dep/src/g3dlite/XML.cpp Normal file
View file

@ -0,0 +1,216 @@
/*
\file XML.h
\author Morgan McGuire
\maintainer Morgan McGuire
\created 2010-02-11
\edited 2010-02-24
Copyright 2000-2010, Morgan McGuire.
All rights reserved.
*/
#include "G3D/XML.h"
#include "G3D/fileutils.h"
#include "G3D/TextInput.h"
#include "G3D/TextOutput.h"
#include "G3D/stringutils.h"
namespace G3D {
XML::XML(TextInput& t) : m_type(VALUE) {
deserialize(t);
}
double XML::number() const {
return TextInput::parseNumber(m_value);
}
bool XML::boolean() const {
return TextInput::parseBoolean(m_value);
}
void XML::load(const std::string& filename) {
TextInput::Settings s;
s.cppBlockComments = false;
s.cppLineComments = false;
s.proofSymbols = false;
TextInput t(filename, s);
deserialize(t);
}
void XML::save(const std::string& filename) const {
std::string s;
unparse(s);
writeWholeFile(filename, s);
}
void XML::unparse(std::string &s) const {
TextOutput::Settings set;
set.wordWrap = TextOutput::Settings::WRAP_WITHOUT_BREAKING;
TextOutput t(set);
serialize(t);
t.commitString(s);
}
void XML::serialize(TextOutput& t) const {
if (m_type == VALUE) {
// Raw string; no quotes
t.writeSymbol(m_value);
} else {
t.printf("<%s", m_name.c_str());
for (AttributeTable::Iterator it = m_attribute.begin(); it.hasMore(); ++it) {
t.printf(" %s=\"%s\"", it->key.c_str(), it->value.m_value.c_str());
}
t.printf(">");
t.writeNewline();
t.pushIndent();
for (int i = 0; i < m_child.size(); ++i) {
m_child[i].serialize(t);
if (m_child[i].m_type == VALUE) {
// Only tags know to append a newline
t.writeNewline();
}
}
t.popIndent();
t.printf("</%s>", m_name.c_str());
t.writeNewline();
}
}
void XML::parse(const std::string& s) {
TextInput t(TextInput::FROM_STRING, s);
deserialize(t);
}
/** True if the next token begins the close tag */
static bool atClose(TextInput& t, const std::string name) {
if ((t.peek().type() == Token::SYMBOL) && (t.peek().string() == "<")) {
// Need to keep looking ahead
Token p0 = t.read();
if ((t.peek().type() == Token::SYMBOL) && (t.peek().string() == "/")) {
// Check the name on the close tag. It *must* match if
// this is a well-formed document, but there might be a
// tag error.
Token p1 = t.read();
Token p2 = t.peek();
std::string s = p2.string();
debugAssertM(beginsWith(name, s), "Mismatched close tag");
// Put the tokens back
t.push(p1);
t.push(p0);
return true;
} else {
// Put the read token back
t.push(p0);
return false;
}
} else {
return false;
}
}
void XML::deserialize(TextInput& t) {
begin:
Token n = t.read();
m_attribute.clear();
m_child.clear();
m_name = "";
m_value = "";
if ((n.type() == Token::SYMBOL) && (n.string() == "<")) {
// Beginning a tag
// Read name
n = t.read();
debugAssert(n.type() == Token::SYMBOL);
bool isComment =
(n.string() == "!") &&
(t.peek().type() == Token::SYMBOL) &&
(t.peek().string() == "--");
// ignored tag: <?xml> or <!xml>
// comment tag: <!-- ... -->
if ((n.string() == "?") || ((n.string() == "!") && ! isComment)) {
// Ignore this tag
while (t.hasMore() && ! ((n.type() == Token::SYMBOL) && (n.string() == ">"))) {
n = t.read();
}
goto begin;
} else if (isComment) {
// Ignore until "-->"
bool prevWasDash = false;
while (t.hasMore() && ! ((n.type() == Token::SYMBOL) && (n.string() == ">") && prevWasDash)) {
prevWasDash = (n.type() == Token::SYMBOL) && (n.string() == "--");
n = t.read();
}
goto begin;
}
// Keep reading until no colon
m_name += n.string();
n = t.read();
while ((n.type() == Token::SYMBOL) && (n.string() == ":")) {
// tag with namespace: <x:y>
m_name += ":" + t.readSymbol();
n = t.read();
}
// Read end of tag/close
bool done = false;
while (! done) {
debugAssert(n.type() == Token::SYMBOL);
if (n.string() == "/") {
// empty-element tag: <foo/>
// Consume the close tag
t.readSymbol(">");
done = true;
} else if (n.string() == ">") {
// End of open tag: read children until close tag
while (! atClose(t, m_name)) {
m_child.next().deserialize(t);
}
// Read close tag (we wouldn't be here unless it parses correctly)
while (t.hasMore() && ! (t.readSymbol() == ">")) {}
done = true;
} else {
// Attribute pair
std::string k = n.string();
t.readSymbol("=");
std::string v = t.read().string();
m_attribute.set(k, v);
// Advance to next
n = t.read();
}
}
} else {
// Beginning embedded content. Read until the end of file or the next tag.
m_type = VALUE;
m_value += n.string();
n = t.peek();
while (t.hasMore() && ! ((n.type() == Token::SYMBOL) && (n.string() == "<"))) {
m_value += " " + t.read().string();
n = t.peek();
}
}
}
}

View file

@ -1,4 +1,4 @@
/**
/*
@file constants.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@ -11,72 +11,6 @@
namespace G3D {
const std::string MirrorQuality::str[] = {"NONE", "STATIC_ENV", "DYNAMIC_PLANAR", "DYNAMIC_ENV", "BEST"};
const MirrorQuality::Value MirrorQuality::enm[] = {MirrorQuality::NONE, MirrorQuality::STATIC_ENV,
MirrorQuality::DYNAMIC_PLANAR, MirrorQuality::DYNAMIC_ENV, MirrorQuality::BEST};
MirrorQuality::MirrorQuality(const class Any& any) {
*this = any;
}
MirrorQuality& MirrorQuality::operator=(const Any& any) {
const std::string& s = toUpper(any.string());
for (int i = 0; ! str[i].empty(); ++i) {
if (s == str[i]) {
value = enm[i];
return *this;
}
}
any.verify(false, "Unrecognized MirrorQuality constant");
return *this;
}
MirrorQuality::operator Any() const {
return toString();
}
const std::string& MirrorQuality::toString() const {
return str[value];
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string RefractionQuality::str[] = {"NONE", "STATIC_ENV", "DYNAMIC_FLAT", "DYNAMIC_FLAT_MULTILAYER", "DYNAMIC_ENV", "BEST"};
const RefractionQuality::Value RefractionQuality::enm[] = {RefractionQuality::NONE, RefractionQuality::STATIC_ENV,
RefractionQuality::DYNAMIC_FLAT, RefractionQuality::DYNAMIC_FLAT_MULTILAYER, RefractionQuality::DYNAMIC_ENV, RefractionQuality::BEST};
RefractionQuality::RefractionQuality(const class Any& any) {
*this = any;
}
RefractionQuality& RefractionQuality::operator=(const Any& any) {
const std::string& s = toUpper(any.string());
for (int i = 0; ! str[i].empty(); ++i) {
if (s == str[i]) {
value = enm[i];
return *this;
}
}
any.verify(false, "Unrecognized RefractionQuality constant");
return *this;
}
RefractionQuality::operator Any() const {
return toString();
}
const std::string& RefractionQuality::toString() const {
return str[value];
}
} // G3D

View file

@ -1,4 +1,4 @@
/**
/*
@file debugAssert.cpp
Windows implementation of assertion routines.
@ -37,10 +37,10 @@ AssertionHook _debugHook = _handleDebugAssert_;
AssertionHook _failureHook = _handleErrorCheck_;
#ifdef G3D_LINUX
#if SOMEONE_MADE_THIS_USEFUL
#if SOMEONE_MADE_THIS_USEFUL /* G3DFIX: Disabled to avoid requirement for X11 libraries */
Display* x11Display = NULL;
Window x11Window = 0;
#endif
#endif /* G3DFIX: Disabled to avoid requirement for X11 libraries */
#endif
@ -63,7 +63,7 @@ static void postToClipboard(const char *text) {
}
#endif
/**
/*
outTitle should be set before the call
*/
static void createErrorMessage(
@ -252,7 +252,7 @@ void _releaseInputGrab_() {
ClipCursor(NULL);
#elif defined(G3D_LINUX)
#if SOMEONE_MADE_THIS_USEFUL
#if SOMEONE_MADE_THIS_USEFUL /* G3DFIX: Disabled to avoid requirement for X11 libraries */
if (x11Display != NULL) {
XUngrabPointer(x11Display, CurrentTime);
XUngrabKeyboard(x11Display, CurrentTime);
@ -267,7 +267,7 @@ void _releaseInputGrab_() {
XAllowEvents(x11Display, AsyncPointer, CurrentTime);
XFlush(x11Display);
}
#endif
#endif /* G3DFIX: Disabled to avoid requirement for X11 libraries */
#elif defined(G3D_OSX)
// TODO: OS X
#endif

View file

@ -1,4 +1,4 @@
/**
/*
@file fileutils.cpp
@author Morgan McGuire, graphics3d.com
@ -17,12 +17,13 @@
#include "G3D/stringutils.h"
#include "G3D/Set.h"
#include "G3D/g3dfnmatch.h"
#include "G3D/FileSystem.h"
#include <sys/stat.h>
#include <sys/types.h>
#if _HAVE_ZIP
#include "zip.h"
#endif
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
#include "zip.h"
#endif /* G3DFIX: Use ZIP-library only if defined */
#ifdef G3D_WIN32
// Needed for _getcwd
@ -104,17 +105,18 @@ std::string readWholeFile(
std::string s;
debugAssert(filename != "");
if (fileExists(filename, false)) {
debugAssertM(FileSystem::exists(filename), filename + " not found");
int64 length = fileLength(filename);
if (! FileSystem::inZipfile(filename)) {
int64 length = FileSystem::size(filename);
char* buffer = (char*)System::alignedMalloc(length + 1, 16);
debugAssert(buffer);
FILE* f = fopen(filename.c_str(), "rb");
FILE* f = FileSystem::fopen(filename.c_str(), "rb");
debugAssert(f);
int ret = fread(buffer, 1, length, f);
debugAssert(ret == length);(void)ret;
fclose(f);
FileSystem::fclose(f);
buffer[length] = '\0';
s = std::string(buffer);
@ -134,8 +136,6 @@ std::string readWholeFile(
buffer[length] = '\0';
s = std::string(buffer);
System::alignedFree(buffer);
} else {
debugAssertM(false, filename + " not found");
}
return s;
@ -146,7 +146,8 @@ void zipRead(const std::string& file,
void*& data,
size_t& length) {
std::string zip, desiredFile;
#if _HAVE_ZIP
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
if (zipfileExists(file, zip, desiredFile)) {
struct zip *z = zip_open( zip.c_str(), ZIP_CHECKCONS, NULL );
{
@ -169,9 +170,9 @@ void zipRead(const std::string& file,
} else {
data = NULL;
}
#else
data = NULL;
#endif
#else /* G3DFIX: Use ZIP-library only if defined */
data = NULL;
#endif /* G3DFIX: Use ZIP-library only if defined */
}
@ -185,7 +186,7 @@ int64 fileLength(const std::string& filename) {
int result = _stat(filename.c_str(), &st);
if (result == -1) {
#if _HAVE_ZIP
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
std::string zip, contents;
if(zipfileExists(filename, zip, contents)){
int64 requiredMem;
@ -196,6 +197,7 @@ int64 fileLength(const std::string& filename) {
struct zip_stat info;
zip_stat_init( &info ); // TODO: Docs unclear if zip_stat_init is required.
int success = zip_stat( z, contents.c_str(), ZIP_FL_NOCASE, &info );
(void)success;
debugAssertM(success == 0, zip + ": " + contents + ": zip stat failed.");
requiredMem = info.size;
}
@ -204,132 +206,14 @@ int64 fileLength(const std::string& filename) {
} else {
return -1;
}
#else
return -1;
#endif
#else /* G3DFIX: Use ZIP-library only if defined */
return -1;
#endif /* G3DFIX: Use ZIP-library only if defined */
}
return st.st_size;
}
/** Used by robustTmpfile. Returns nonzero if fread, fwrite, and fseek all
succeed on the file.
@author Morgan McGuire, http://graphics.cs.williams.edu */
static int isFileGood(FILE* f) {
int x, n, result;
/* Must be a valid file handle */
if (f == NULL) {
return 0;
}
/* Try to write */
x = 1234;
n = fwrite(&x, sizeof(int), 1, f);
if (n != 1) {
return 0;
}
/* Seek back to the beginning */
result = fseek(f, 0, SEEK_SET);
if (result != 0) {
return 0;
}
/* Read */
n = fread(&x, sizeof(int), 1, f);
if (n != 1) {
return 0;
}
/* Seek back to the beginning again */
fseek(f, 0, SEEK_SET);
return 1;
}
FILE* createTempFile() {
FILE* t = NULL;
//# ifdef G3D_WIN32
t = tmpfile();
//# else
// // On Unix, tmpfile generates a warning for any code that links against it.
// const char* tempfilename = "/tmp/g3dtemp.XXXXXXXX";
// mktemp(tempfilename);
// t = fopen(tempfilename, "w");
//# endif
# ifdef _WIN32
char* n = NULL;
# endif
char name[256];
if (isFileGood(t)) {
return t;
}
# ifdef G3D_WIN32
/* tmpfile failed; try the tmpnam routine */
t = fopen(tmpnam(NULL), "w+");
if (isFileGood(t)) {
return t;
}
n = _tempnam("c:/tmp/", "t");
/* Try to create something in C:\tmp */
t = fopen(n, "w+");
if (isFileGood(t)) {
return t;
}
/* Try c:\temp */
n = _tempnam("c:/temp/", "t");
t = fopen(n, "w+");
if (isFileGood(t)) {
return t;
}
/* try the current directory */
n = _tempnam("./", "t");
t = fopen(n, "w+");
if (isFileGood(t)) {
return t;
}
sprintf(name, "%s/tmp%d", "c:/temp", rand());
t = fopen(name, "w+");
if (isFileGood(t)) {
return t;
}
/* Try some hardcoded paths */
sprintf(name, "%s/tmp%d", "c:/tmp", rand());
t = fopen(name, "w+");
if (isFileGood(t)) {
return t;
}
# else
sprintf(name, "%s/tmp%d", "/tmp", rand());
t = fopen(name, "w+");
if (isFileGood(t)) {
return t;
}
#endif
sprintf(name, "tmp%d", rand());
t = fopen(name, "w+");
if (isFileGood(t)) {
return t;
}
fprintf(stderr, "Unable to create a temporary file; robustTmpfile returning NULL\n");
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
void writeWholeFile(
const std::string& filename,
@ -342,11 +226,11 @@ void writeWholeFile(
parseFilename(filename, root, pathArray, base, ext);
path = root + stringJoin(pathArray, '/');
if (! fileExists(path, false)) {
createDirectory(path);
if (! FileSystem::exists(path, false)) {
FileSystem::createDirectory(path);
}
FILE* file = fopen(filename.c_str(), "wb");
FILE* file = FileSystem::fopen(filename.c_str(), "wb");
debugAssert(file);
@ -355,12 +239,13 @@ void writeWholeFile(
if (flush) {
fflush(file);
}
fclose(file);
FileSystem::fclose(file);
}
///////////////////////////////////////////////////////////////////////////////
/**
/*
Creates the directory (which may optionally end in a /)
and any parents needed to reach it.
*/
@ -385,7 +270,7 @@ void createDirectory(
}
// If it already exists, do nothing
if (fileExists(d.substr(0, d.size() - 1)), false) {
if (FileSystem::exists(d.substr(0, d.size() - 1))) {
return;
}
@ -405,129 +290,22 @@ void createDirectory(
// Create any intermediate that doesn't exist
for (int i = 0; i < path.size(); ++i) {
p += "/" + path[i];
if (! fileExists(p, false)) {
if (! FileSystem::exists(p)) {
// Windows only requires one argument to mkdir,
// where as unix also requires the permissions.
# ifndef G3D_WIN32
mkdir(p.c_str(), 0777);
# else
# else
_mkdir(p.c_str());
# endif
# endif
}
}
}
///////////////////////////////////////////////////////////////////////////////
class FileSystemCache {
private:
Table<std::string, Array<std::string> > m_files;
public:
bool fileExists(const std::string& filename) {
const std::string& path = resolveFilename(filenamePath(filename));
const std::string& name = filenameBaseExt(filename);
bool neverBeforeSeen = false;
Array<std::string>& fileList = m_files.getCreate(path, neverBeforeSeen);
if (neverBeforeSeen) {
if (! G3D::fileExists(path, true, false)) {
// The path itself doesn't exist... back out our insertion (which makes fileList& invalid)
m_files.remove(path);
return false;
}
std::string spec = pathConcat(path, "*");
// Will automatically recurse into zipfiles
getFiles(spec, fileList);
getDirs(spec, fileList);
# ifdef G3D_WIN32
{
// Case insensitive
for (int i = 0; i < fileList.size(); ++i) {
fileList[i] = toLower(fileList[i]);
}
}
# endif
}
if (filenameContainsWildcards(name)) {
// See if anything matches
for (int i = 0; i < fileList.size(); ++i) {
if (g3dfnmatch(name.c_str(), fileList[i].c_str(), 0) == 0) {
return true;
}
}
return false;
} else {
// On windows, this is a lower-lower comparison, so it is case insensitive
return fileList.contains(name);
}
}
void clear() {
m_files.clear();
}
static FileSystemCache& instance() {
static FileSystemCache i;
return i;
}
};
void clearFileSystemCache() {
FileSystemCache::instance().clear();
}
bool fileExists
(const std::string& _filename,
bool lookInZipfiles,
bool trustCache) {
if (_filename.empty()) {
return false;
}
// Remove trailing slash from directories
const std::string& filename = (endsWith(_filename, "/") || endsWith(_filename, "\\")) ? _filename.substr(0, _filename.length() - 1) : _filename;
if (trustCache && lookInZipfiles) {
# ifdef G3D_WIN32
// Case insensitive
return FileSystemCache::instance().fileExists(toLower(filename));
# else
return FileSystemCache::instance().fileExists(filename);
# endif
}
// Useful for debugging
//char curdir[1024]; _getcwd(curdir, 1024);
struct _stat st;
int ret = _stat(filename.c_str(), &st);
// _stat returns zero on success
bool exists = (ret == 0);
if (! exists && lookInZipfiles) {
// Does not exist standalone, but might exist in a zipfile
// These output arguments will be ignored
std::string zipDir, internalPath;
return zipfileExists(filename, zipDir, internalPath);
} else {
return exists;
}
}
///////////////////////////////////////////////////////////////////////////////
#if _HAVE_ZIP
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
/* Helper methods for zipfileExists()*/
// Given a string (the drive) and an array (the path), computes the directory
static void _zip_resolveDirectory(std::string& completeDir, const std::string& drive, const Array<std::string>& path, const int length){
@ -561,12 +339,13 @@ static bool _zip_zipContains(const std::string& zipDir, const std::string& desir
}
return true;
}
#endif
#endif /* G3DFIX: Use ZIP-library only if defined */
// If no zipfile exists, outZipfile and outInternalFile are unchanged
bool zipfileExists(const std::string& filename, std::string& outZipfile,
std::string& outInternalFile){
#if _HAVE_ZIP
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
Array<std::string> path;
std::string drive, base, ext, zipfile, infile;
parseFilename(filename, drive, path, base, ext);
@ -607,12 +386,12 @@ bool zipfileExists(const std::string& filename, std::string& outZipfile,
return false;
}
if (fileExists(zipfile, false)) {
if (FileSystem::exists(zipfile)) {
// test if it actually is a zipfile
// if not, return false, a bad
// directory structure has been given,
// not a .zip
if (isZipfile(zipfile)){
if (FileSystem::isZipfile(zipfile)){
if (_zip_zipContains(zipfile, infile)){
outZipfile = zipfile;
@ -628,7 +407,7 @@ bool zipfileExists(const std::string& filename, std::string& outZipfile,
}
}
#endif
#endif /* G3DFIX: Use ZIP-library only if defined */
// not a valid directory structure ever,
// obviously no .zip was found within the path
return false;
@ -641,7 +420,7 @@ std::string generateFilenameBase(const std::string& prefix, const std::string& s
// Note "template" is a reserved word in C++
std::string templat = prefix + System::currentDateString() + "_";
getFiles(templat + "*", exist);
FileSystem::getFiles(templat + "*", exist);
// Remove extensions
for (int i = 0; i < exist.size(); ++i) {
@ -791,7 +570,7 @@ void parseFilename(
}
/**
/*
Helper for getFileList and getDirectoryList.
@param wantFiles If false, returns the directories, otherwise
@ -910,8 +689,9 @@ static void getFileOrDirListNormal
# endif
}
#if _HAVE_ZIP
/**
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
/*
@param path The zipfile name (no trailing slash)
@param prefix Directory inside the zipfile. No leading slash, must have trailing slash if non-empty.
@param file Name inside the zipfile that we are testing to see if it matches prefix + "*"
@ -961,14 +741,14 @@ static void _zip_addEntry(const std::string& path,
}
}
}
#endif
#endif /* G3DFIX: Use ZIP-library only if defined */
static void getFileOrDirListZip(const std::string& path,
const std::string& prefix,
Array<std::string>& files,
bool wantFiles,
bool includePath){
#if _HAVE_ZIP
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
struct zip *z = zip_open( path.c_str(), ZIP_CHECKCONS, NULL );
Set<std::string> fileSet;
@ -984,7 +764,7 @@ static void getFileOrDirListZip(const std::string& path,
zip_close( z );
fileSet.getMembers(files);
#endif
#endif /* G3DFIX: Use ZIP-library only if defined */
}
@ -1004,8 +784,8 @@ static void determineFileOrDirList(
path = path.substr(0, path.length() -1);
}
if ((path == "") || fileExists(path, false)) {
if ((path != "") && isZipfile(path)) {
if ((path == "") || FileSystem::exists(path)) {
if ((path != "") && FileSystem::isZipfile(path)) {
// .zip should only work if * is specified as the Base + Ext
// Here, we have been asked for the root's contents
debugAssertM(filenameBaseExt(filespec) == "*", "Can only call getFiles/getDirs on zipfiles using '*' wildcard");

View file

@ -1,4 +1,4 @@
/**
/*
@file filter.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file format.cpp
@author Morgan McGuire, graphics3d.com

View file

@ -1,40 +1,42 @@
/*-
* Copyright (c) 1992, 1993
*The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
*This product includes software developed by the University of
*California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*@(#)fnmatch.h8.1 (Berkeley) 6/2/93
*
* From FreeBSD fnmatch.h 1.7
* $Id: g3dfnmatch.cpp,v 1.2 2010/02/06 10:03:24 corey_taylor Exp $
*/
/* $Id: g3dfnmatch.cpp,v 1.3 2010/03/15 05:01:23 morgan3d Exp $ */
/* $OpenBSD: fnmatch.c,v 1.7 2000/03/23 19:13:51 millert Exp $ */
/*
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "G3D/g3dfnmatch.h"
#ifdef G3D_WIN32
@ -45,149 +47,166 @@
namespace G3D {
#define EOS '\0'
#define EOS '\0'
static const char *rangematch(const char *, char, int);
#define RANGE_MATCH 1
#define RANGE_NOMATCH 0
#define RANGE_ERROR (-1)
int g3dfnmatch(const char *pattern, const char *string, int flags)
static int rangematch(const char *, char, int, char **);
int
g3dfnmatch(const char *pattern, const char *string, int flags)
{
const char *stringstart;
char c, test;
const char *stringstart;
char *newp;
char c, test;
for (stringstart = string;;)
switch (c = *pattern++) {
case EOS:
if ((flags & FNM_LEADING_DIR) && *string == '/')
return (0);
return (*string == EOS ? 0 : FNM_NOMATCH);
case '?':
if (*string == EOS)
return (FNM_NOMATCH);
if (*string == '/' && (flags & FNM_PATHNAME))
return (FNM_NOMATCH);
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
return (FNM_NOMATCH);
++string;
break;
case '*':
c = *pattern;
/* Collapse multiple stars. */
while (c == '*')
c = *++pattern;
for (stringstart = string;;)
switch (c = *pattern++) {
case EOS:
if ((flags & FNM_LEADING_DIR) && *string == '/')
return (0);
return (*string == EOS ? 0 : FNM_NOMATCH);
case '?':
if (*string == EOS)
return (FNM_NOMATCH);
if (*string == '/' && (flags & FNM_PATHNAME))
return (FNM_NOMATCH);
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
return (FNM_NOMATCH);
++string;
break;
case '*':
c = *pattern;
/* Collapse multiple stars. */
while (c == '*')
c = *++pattern;
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
return (FNM_NOMATCH);
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
return (FNM_NOMATCH);
/* Optimize for pattern with * at end or before /. */
if (c == EOS)
if (flags & FNM_PATHNAME)
return ((flags & FNM_LEADING_DIR) ||
strchr(string, '/') == NULL ?
0 : FNM_NOMATCH);
else
return (0);
else if (c == '/' && flags & FNM_PATHNAME) {
if ((string = strchr(string, '/')) == NULL)
return (FNM_NOMATCH);
break;
}
/* Optimize for pattern with * at end or before /. */
if (c == EOS) {
if (flags & FNM_PATHNAME)
return ((flags & FNM_LEADING_DIR) ||
strchr(string, '/') == NULL ?
0 : FNM_NOMATCH);
else
return (0);
} else if (c == '/' && (flags & FNM_PATHNAME)) {
if ((string = strchr(string, '/')) == NULL)
return (FNM_NOMATCH);
break;
}
/* General case, use recursion. */
while ((test = *string) != EOS) {
if (!rangematch(pattern, *string, flags & ~FNM_PERIOD))
return (0);
if (test == '/' && flags & FNM_PATHNAME)
break;
++string;
}
return (FNM_NOMATCH);
case '[':
if (*string == EOS)
return (FNM_NOMATCH);
if (*string == '/' && flags & FNM_PATHNAME)
return (FNM_NOMATCH);
if ((pattern =
rangematch(pattern, *string, flags)) == NULL)
return (FNM_NOMATCH);
++string;
break;
case '\\':
if (!(flags & FNM_NOESCAPE)) {
if ((c = *pattern++) == EOS) {
c = '\\';
--pattern;
}
}
/* FALLTHROUGH */
default:
if (c == *string)
;
else if ((flags & FNM_CASEFOLD) &&
(tolower((unsigned char)c) ==
tolower((unsigned char)*string)))
;
else if ((flags & FNM_PREFIX_DIRS) && *string == EOS &&
((c == '/' && string != stringstart) ||
(string == stringstart+1 && *stringstart == '/')))
return (0);
else
return (FNM_NOMATCH);
string++;
break;
}
/* NOTREACHED */
/* General case, use recursion. */
while ((test = *string) != EOS) {
if (!g3dfnmatch(pattern, string, flags & ~FNM_PERIOD))
return (0);
if (test == '/' && (flags & FNM_PATHNAME))
break;
++string;
}
return (FNM_NOMATCH);
case '[':
if (*string == EOS)
return (FNM_NOMATCH);
if (*string == '/' && (flags & FNM_PATHNAME))
return (FNM_NOMATCH);
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
return (FNM_NOMATCH);
switch (rangematch(pattern, *string, flags, &newp)) {
case RANGE_ERROR:
/* not a good range, treat as normal text */
goto normal;
case RANGE_MATCH:
pattern = newp;
break;
case RANGE_NOMATCH:
return (FNM_NOMATCH);
}
++string;
break;
case '\\':
if (!(flags & FNM_NOESCAPE)) {
if ((c = *pattern++) == EOS) {
c = '\\';
--pattern;
}
}
/* FALLTHROUGH */
default:
normal:
if (c != *string && !((flags & FNM_CASEFOLD) &&
(tolower((unsigned char)c) ==
tolower((unsigned char)*string))))
return (FNM_NOMATCH);
++string;
break;
}
/* NOTREACHED */
}
static const char *
rangematch(const char *pattern, char test, int flags)
static int
rangematch(const char *pattern, char test, int flags, char **newp)
{
int negate, ok;
char c, c2;
int negate, ok;
char c, c2;
/*
* A bracket expression starting with an unquoted circumflex
* character produces unspecified results (IEEE 1003.2-1992,
* 3.13.2). This implementation treats it like '!', for
* consistency with the regular expression syntax.
* J.T. Conklin (conklin@ngai.kaleida.com)
*/
if ( (negate = (*pattern == '!' || *pattern == '^')) )
++pattern;
/*
* A bracket expression starting with an unquoted circumflex
* character produces unspecified results (IEEE 1003.2-1992,
* 3.13.2). This implementation treats it like '!', for
* consistency with the regular expression syntax.
* J.T. Conklin (conklin@ngai.kaleida.com)
*/
if ((negate = (*pattern == '!' || *pattern == '^')))
++pattern;
if (flags & FNM_CASEFOLD)
test = tolower((unsigned char)test);
if (flags & FNM_CASEFOLD)
test = tolower((unsigned char)test);
for (ok = 0; (c = *pattern++) != ']';) {
if (c == '\\' && !(flags & FNM_NOESCAPE))
c = *pattern++;
if (c == EOS)
return (NULL);
/*
* A right bracket shall lose its special meaning and represent
* itself in a bracket expression if it occurs first in the list.
* -- POSIX.2 2.8.3.2
*/
ok = 0;
c = *pattern++;
do {
if (c == '\\' && !(flags & FNM_NOESCAPE))
c = *pattern++;
if (c == EOS)
return (RANGE_ERROR);
if (c == '/' && (flags & FNM_PATHNAME))
return (RANGE_NOMATCH);
if ((flags & FNM_CASEFOLD))
c = tolower((unsigned char)c);
if (*pattern == '-'
&& (c2 = *(pattern+1)) != EOS && c2 != ']') {
pattern += 2;
if (c2 == '\\' && !(flags & FNM_NOESCAPE))
c2 = *pattern++;
if (c2 == EOS)
return (RANGE_ERROR);
if (flags & FNM_CASEFOLD)
c2 = tolower((unsigned char)c2);
if (c <= test && test <= c2)
ok = 1;
} else if (c == test)
ok = 1;
} while ((c = *pattern++) != ']');
if (flags & FNM_CASEFOLD)
c = tolower((unsigned char)c);
if (*pattern == '-'
&& (c2 = *(pattern+1)) != EOS && c2 != ']') {
pattern += 2;
if (c2 == '\\' && !(flags & FNM_NOESCAPE))
c2 = *pattern++;
if (c2 == EOS)
return (NULL);
if (flags & FNM_CASEFOLD)
c2 = tolower((unsigned char)c2);
if ((unsigned char)c <= (unsigned char)test &&
(unsigned char)test <= (unsigned char)c2)
ok = 1;
} else if (c == test)
ok = 1;
}
return (ok == negate ? NULL : pattern);
*newp = (char *)pattern;
return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
}
}

View file

@ -1,4 +1,4 @@
/**
/*
@file g3dmath.cpp
@author Morgan McGuire, graphics3d.com
@ -11,6 +11,7 @@
#include <cstdlib>
#include <cstring>
namespace G3D {
float gaussRandom(float mean, float stdev) {

View file

@ -1,4 +1,4 @@
/**
/*
@file license.cpp
@author Morgan McGuire, graphics3d.com

View file

@ -1,4 +1,4 @@
/**
/*
@file prompt.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu
@ -46,7 +46,7 @@ namespace G3D {
#ifdef G3D_WIN32
namespace _internal {
/**
/*
Generic Win32 dialog facility.
@author Max McGuire
*/
@ -179,7 +179,7 @@ public:
}
/**
/*
*
* Returns a pointer to the Win32 dialog template which the object
* represents. This pointer may become invalid if additional components
@ -295,7 +295,7 @@ struct PromptParams {
const char* title;
};
/**
/*
* Constants for controls.
*/
#define IDC_MESSAGE 1000
@ -351,7 +351,7 @@ INT_PTR CALLBACK PromptDlgProc(HWND hDlg, UINT msg,
using namespace _internal;
/**
/*
* Show a dialog prompt.
*/
static int guiPrompt(
@ -475,7 +475,7 @@ static int guiPrompt(
#endif /* MANGOS exclude for disabled gui prompt */
/**
/*
* Show a prompt on stdout
*/
static int textPrompt(
@ -557,7 +557,7 @@ struct CallbackData {
int* whichButton;
};
/**
/*
Assumes that userData is a pointer to a carbon_evt_data_t.
*/

View file

@ -1,4 +1,4 @@
/**
/*
@file stringutils.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,4 +1,4 @@
/**
/*
@file uint128.cpp
@maintainer Morgan McGuire, http://graphics.cs.williams.edu

View file

@ -1,5 +1,5 @@
#
# This file is part of the CMaNGOS Project. See AUTHORS file for Copyright information
# This code is part of MaNGOS. Contributor & Copyright details are in AUTHORS/THANKS.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View file

@ -1,5 +1,5 @@
#
# This file is part of the CMaNGOS Project. See AUTHORS file for Copyright information
# This code is part of MaNGOS. Contributor & Copyright details are in AUTHORS/THANKS.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by