diff --git a/src/geometry.cpp b/src/geometry.cpp index cc92e87..bd4edc9 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -43,10 +43,8 @@ Geometry::create(int32 numVerts, int32 numTris, uint32 flags) } geo->morphTargets = new MorphTarget[1]; MorphTarget *m = geo->morphTargets; - m->boundingSphere[0] = 0.0f; - m->boundingSphere[1] = 0.0f; - m->boundingSphere[2] = 0.0f; - m->boundingSphere[3] = 0.0f; + m->boundingSphere.center.set(0.0f, 0.0f, 0.0f); + m->boundingSphere.radius = 0.0f; m->vertices = NULL; m->normals = NULL; if(!(geo->geoflags & NATIVE) && geo->numVertices){ @@ -130,7 +128,7 @@ Geometry::streamRead(Stream *stream) for(int32 i = 0; i < geo->numMorphTargets; i++){ MorphTarget *m = &geo->morphTargets[i]; - stream->read(m->boundingSphere, 4*4); + stream->read(&m->boundingSphere, 4*4); int32 hasVertices = stream->readI32(); int32 hasNormals = stream->readI32(); if(hasVertices) @@ -217,7 +215,7 @@ Geometry::streamWrite(Stream *stream) for(int32 i = 0; i < this->numMorphTargets; i++){ MorphTarget *m = &this->morphTargets[i]; - stream->write(m->boundingSphere, 4*4); + stream->write(&m->boundingSphere, 4*4); if(!(this->geoflags & NATIVE)){ stream->writeI32(m->vertices != NULL); stream->writeI32(m->normals != NULL); @@ -288,25 +286,21 @@ Geometry::calculateBoundingSphere(void) { for(int32 i = 0; i < this->numMorphTargets; i++){ MorphTarget *m = &this->morphTargets[i]; - float32 min[3] = { 1000000.0f, 1000000.0f, 1000000.0f }; - float32 max[3] = { -1000000.0f, -1000000.0f, -1000000.0f }; + V3d min( 1000000.0f, 1000000.0f, 1000000.0f); + V3d max(-1000000.0f, -1000000.0f, -1000000.0f); float32 *v = m->vertices; for(int32 j = 0; j < this->numVertices; j++){ - if(v[0] > max[0]) max[0] = v[0]; - if(v[0] < min[0]) min[0] = v[0]; - if(v[1] > max[1]) max[1] = v[1]; - if(v[1] < min[1]) min[1] = v[1]; - if(v[2] > max[2]) max[2] = v[2]; - if(v[2] < min[2]) min[2] = v[2]; + if(v[0] > max.x) max.x = v[0]; + if(v[0] < min.x) min.x = v[0]; + if(v[1] > max.y) max.y = v[1]; + if(v[1] < min.y) min.y = v[1]; + if(v[2] > max.z) max.z = v[2]; + if(v[2] < min.z) min.z = v[2]; v += 3; } - m->boundingSphere[0] = (min[0] + max[0])/2.0f; - m->boundingSphere[1] = (min[1] + max[1])/2.0f; - m->boundingSphere[2] = (min[2] + max[2])/2.0f; - max[0] -= m->boundingSphere[0]; - max[1] -= m->boundingSphere[1]; - max[2] -= m->boundingSphere[2]; - m->boundingSphere[3] = sqrt(max[0]*max[0] + max[1]*max[1] + max[2]*max[2]); + m->boundingSphere.center = scale(add(min, max), 1/2.0f); + max = sub(max, m->boundingSphere.center); + m->boundingSphere.radius = length(max); } } diff --git a/src/image.cpp b/src/image.cpp index 788edb7..ef028cc 100755 --- a/src/image.cpp +++ b/src/image.cpp @@ -105,6 +105,12 @@ TexDictionary::streamGetSize(void) bool32 loadTextures; +static Texture *defaultFindCB(const char *name); +static Texture *defaultReadCB(const char *name, const char *mask); + +Texture *(*Texture::findCB)(const char *name) = defaultFindCB; +Texture *(*Texture::readCB)(const char *name, const char *mask) = defaultReadCB; + Texture* Texture::create(Raster *raster) { @@ -135,7 +141,36 @@ Texture::destroy(void) } } -// TODO: do this properly, pretty ugly right now +static Texture* +defaultFindCB(const char *name) +{ + if(currentTexDictionary) + return currentTexDictionary->find(name); + // TODO: RW searches *all* TXDs otherwise + return NULL; +} + +static Texture* +defaultReadCB(const char *name, const char *mask) +{ + Texture *tex; + Image *img; + char *n = (char*)malloc(strlen(name) + 5); + strcpy(n, name); + strcat(n, ".tga"); + img = readTGA(n); + free(n); + if(img){ + tex = Texture::create(Raster::createFromImage(img)); + strncpy(tex->name, name, 32); + if(mask) + strncpy(tex->mask, mask, 32); + img->destroy(); + return tex; + }else + return NULL; +} + Texture* Texture::read(const char *name, const char *mask) { @@ -143,31 +178,28 @@ Texture::read(const char *name, const char *mask) Raster *raster = NULL; Texture *tex; - if(currentTexDictionary && (tex = currentTexDictionary->find(name))){ + if(tex = Texture::findCB(name)){ tex->refCount++; return tex; } - tex = Texture::create(NULL); - strncpy(tex->name, name, 32); - if(mask) - strncpy(tex->mask, mask, 32); - Image *img = NULL; if(loadTextures){ - char *n = (char*)malloc(strlen(name) + 5); - strcpy(n, name); - strcat(n, ".tga"); - img = readTGA(n); - free(n); - if(img){ - raster = Raster::createFromImage(img); - img->destroy(); - }else - raster = Raster::create(0, 0, 0, 0x80); - }else + tex = Texture::readCB(name, mask); + if(tex == NULL) + goto dummytex; + }else{ + dummytex: + tex = Texture::create(NULL); + strncpy(tex->name, name, 32); + if(mask) + strncpy(tex->mask, mask, 32); raster = Raster::create(0, 0, 0, 0x80); - tex->raster = raster; - if(currentTexDictionary) + tex->raster = raster; + } + if(currentTexDictionary){ + if(tex->dict) + tex->inDict.remove(); currentTexDictionary->add(tex); + } return tex; } @@ -386,7 +418,7 @@ Image::getFilename(const char *name) { FILE *f; char *s, *p = searchPaths; - int len = strlen(name)+1; + size_t len = strlen(name)+1; if(numSearchPaths == 0){ f = fopen(name, "rb"); if(f){ diff --git a/src/rwbase.h b/src/rwbase.h index df695cd..ab552c2 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -152,6 +152,12 @@ bool32 matrixInvert(float32 *out, float32 *in); void matrixPrint(float32 *mat); bool32 equal(const Matrix &m1, const Matrix &m2); +struct Sphere +{ + V3d center; + float32 radius; +}; + class Stream { public: diff --git a/src/rwobjects.h b/src/rwobjects.h index 4b0236f..59296e8 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -318,6 +318,9 @@ struct Texture : PluginBase void streamWriteNative(Stream *stream); uint32 streamGetSizeNative(void); + static Texture *(*findCB)(const char *name); + static Texture *(*readCB)(const char *name, const char *mask); + enum FilterMode { NEAREST = 1, LINEAR, @@ -449,7 +452,7 @@ struct MeshHeader struct MorphTarget { - float32 boundingSphere[4]; + Sphere boundingSphere; float32 *vertices; float32 *normals; };