From 62c6fe006e0a22a10a185edb11f3725ee01170ce Mon Sep 17 00:00:00 2001 From: Angelo Papenhoff Date: Tue, 20 Jan 2015 19:22:57 +0100 Subject: [PATCH] Implemented basic TexDictionary. --- src/geometry.cpp | 86 ------------------------- src/image.cpp | 159 ++++++++++++++++++++++++++++++++++++++++------ src/ogl.cpp | 61 +++++++++++++----- src/rwobjects.h | 16 ++++- src/rwogl.h | 2 +- tests/gl/main.cpp | 16 ++--- 6 files changed, 209 insertions(+), 131 deletions(-) diff --git a/src/geometry.cpp b/src/geometry.cpp index 0c5c66c..dadb15a 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -430,90 +430,4 @@ RegisterMaterialRightsPlugin(void) } -// -// Texture -// - -Texture::Texture(void) -{ - memset(this->name, 0, 32); - memset(this->mask, 0, 32); - this->filterAddressing = (WRAP << 12) | (WRAP << 8) | NEAREST; - this->raster = NULL; - this->refCount = 1; - this->constructPlugins(); -} - -Texture::~Texture(void) -{ - this->destructPlugins(); -} - -void -Texture::decRef(void) -{ - this->refCount--; - if(this->refCount) - delete this; -} - -Texture* -Texture::streamRead(Stream *stream) -{ - uint32 length; - assert(FindChunk(stream, ID_STRUCT, NULL, NULL)); - Texture *tex = new Texture; - tex->filterAddressing = stream->readU16(); - // TODO: what is this? (mipmap? i think) - stream->seek(2); - - assert(FindChunk(stream, ID_STRING, &length, NULL)); - stream->read(tex->name, length); - - assert(FindChunk(stream, ID_STRING, &length, NULL)); - stream->read(tex->mask, length); - - tex->raster = Raster::read(tex->name, tex->mask); - if(tex->raster == NULL) - printf("didn't find texture %s\n", tex->name); - - tex->streamReadPlugins(stream); - - return tex; -} - -bool -Texture::streamWrite(Stream *stream) -{ - int size; - WriteChunkHeader(stream, ID_TEXTURE, this->streamGetSize()); - WriteChunkHeader(stream, ID_STRUCT, 4); - stream->writeU32(this->filterAddressing); - - // TODO: length can't be > 32 - size = strlen(this->name)+4 & ~3; - WriteChunkHeader(stream, ID_STRING, size); - stream->write(this->name, size); - - size = strlen(this->mask)+4 & ~3; - WriteChunkHeader(stream, ID_STRING, size); - stream->write(this->mask, size); - - this->streamWritePlugins(stream); - return true; -} - -uint32 -Texture::streamGetSize(void) -{ - uint32 size = 0; - int strsize; - size += 12 + 4; - size += 12 + 12; - size += strlen(this->name)+4 & ~3; - size += strlen(this->mask)+4 & ~3; - size += 12 + this->streamGetPluginSize(); - return size; -} - } diff --git a/src/image.cpp b/src/image.cpp index 442136a..a79bfdc 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -29,6 +29,147 @@ writeUInt8(uint8 tmp, ostream &rw) return sizeof(uint8); } +// +// TexDictionary +// + +TexDictionary *CurrentTexDictionary; + +TexDictionary::TexDictionary(void) +{ + this->first = NULL; +} + +void +TexDictionary::add(Texture *tex) +{ + tex->next = this->first; + this->first = tex; +} + +Texture* +TexDictionary::find(const char *name) +{ + for(Texture *tex = this->first; tex; tex = tex->next) + if(strncmp(tex->name, name, 32) == 0) + return tex; + return NULL; +} + +// +// Texture +// + +Texture::Texture(void) +{ + memset(this->name, 0, 32); + memset(this->mask, 0, 32); + this->filterAddressing = (WRAP << 12) | (WRAP << 8) | NEAREST; + this->raster = NULL; + this->refCount = 1; + this->next = NULL; + this->constructPlugins(); +} + +Texture::~Texture(void) +{ + this->destructPlugins(); +} + +void +Texture::decRef(void) +{ + this->refCount--; + if(this->refCount) + delete this; +} + +// TODO: do this properly, pretty ugly right now +Texture* +Texture::read(const char *name, const char *mask) +{ + (void)mask; + Raster *raster = NULL; + Texture *tex; + + if((tex = CurrentTexDictionary->find(name))) + return tex; + tex = new Texture; + strncpy(tex->name, name, 32); + strncpy(tex->mask, mask, 32); + char *n = (char*)malloc(strlen(name) + 5); + strcpy(n, name); + strcat(n, ".tga"); + Image *img = readTGA(n); + free(n); + if(img){ + raster = Raster::createFromImage(img); + delete img; + } + tex->raster = raster; + CurrentTexDictionary->add(tex); + return tex; +} + +Texture* +Texture::streamRead(Stream *stream) +{ + uint32 length; + char name[32], mask[32]; + assert(FindChunk(stream, ID_STRUCT, NULL, NULL)); + uint32 filterAddressing = stream->readU16(); + // TODO: what is this? (mipmap? i think) + stream->seek(2); + + assert(FindChunk(stream, ID_STRING, &length, NULL)); + stream->read(name, length); + + assert(FindChunk(stream, ID_STRING, &length, NULL)); + stream->read(mask, length); + + Texture *tex = Texture::read(name, mask); + tex->refCount++; + tex->filterAddressing = filterAddressing; + + tex->streamReadPlugins(stream); + + return tex; +} + +bool +Texture::streamWrite(Stream *stream) +{ + int size; + WriteChunkHeader(stream, ID_TEXTURE, this->streamGetSize()); + WriteChunkHeader(stream, ID_STRUCT, 4); + stream->writeU32(this->filterAddressing); + + // TODO: length can't be > 32 + size = strlen(this->name)+4 & ~3; + WriteChunkHeader(stream, ID_STRING, size); + stream->write(this->name, size); + + size = strlen(this->mask)+4 & ~3; + WriteChunkHeader(stream, ID_STRING, size); + stream->write(this->mask, size); + + this->streamWritePlugins(stream); + return true; +} + +uint32 +Texture::streamGetSize(void) +{ + uint32 size = 0; + int strsize; + size += 12 + 4; + size += 12 + 12; + size += strlen(this->name)+4 & ~3; + size += strlen(this->mask)+4 & ~3; + size += 12 + this->streamGetPluginSize(); + return size; +} + // // Image // @@ -352,22 +493,4 @@ Raster::createFromImage(Image *image) return raster; } -// TODO: do this properly, only an ugly hack right now -Raster* -Raster::read(const char *name, const char *mask) -{ - (void)mask; - char *n = (char*)malloc(strlen(name) + 5); - strcpy(n, name); - strcat(n, ".tga"); - Image *img = readTGA(n); - free(n); - if(img){ - Raster *raster = Raster::createFromImage(img); - delete img; - return raster; - } - return NULL; -} - } diff --git a/src/ogl.cpp b/src/ogl.cpp index 9e5c2d3..10ee992 100644 --- a/src/ogl.cpp +++ b/src/ogl.cpp @@ -432,42 +432,69 @@ RegisterNativeRaster(void) } void -Raster::upload(void) +Texture::upload(void) { GLuint id; glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); - if(this->palette){ + Raster *r = this->raster; + if(r->palette){ printf("can't upload paletted raster\n"); return; } - switch(this->format & 0xF00){ - case C8888: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexImage2D(GL_TEXTURE_2D, 0, 4, this->width, this->height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, this->texels); + + static GLenum filter[] = { + 0, GL_NEAREST, GL_LINEAR, + GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, + GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR + }; + static GLenum filternomip[] = { + 0, GL_NEAREST, GL_LINEAR, + GL_NEAREST, GL_LINEAR, + GL_NEAREST, GL_LINEAR + }; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + filternomip[this->filterAddressing & 0xFF]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + filternomip[this->filterAddressing & 0xFF]); + + static GLenum wrap[] = { + 0, GL_REPEAT, GL_MIRRORED_REPEAT, + GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER + }; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + wrap[(this->filterAddressing >> 8) & 0xF]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + wrap[(this->filterAddressing >> 12) & 0xF]); + + switch(r->format & 0xF00){ + case Raster::C8888: + glTexImage2D(GL_TEXTURE_2D, 0, 4, r->width, r->height, + 0, GL_RGBA, GL_UNSIGNED_BYTE, r->texels); break; default: - printf("unsupported raster format: %x\n", this->format); + printf("unsupported raster format: %x\n", r->format); break; } glBindTexture(GL_TEXTURE_2D, 0); - GlRaster *glr = PLUGINOFFSET(GlRaster, this, NativeRasterOffset); + GlRaster *glr = PLUGINOFFSET(GlRaster, r, NativeRasterOffset); glr->id = id; } void -Raster::bind(int n) +Texture::bind(int n) { - GlRaster *raster = PLUGINOFFSET(GlRaster, this, NativeRasterOffset); - if(raster->id == 0) - this->upload(); + Raster *r = this->raster; + GlRaster *glr = PLUGINOFFSET(GlRaster, r, NativeRasterOffset); glActiveTexture(GL_TEXTURE0+n); - glBindTexture(GL_TEXTURE_2D, raster->id); + if(r){ + if(glr->id == 0) + this->upload(); + glBindTexture(GL_TEXTURE_2D, glr->id); + }else + glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); + } #endif diff --git a/src/rwobjects.h b/src/rwobjects.h index 92ab277..ff90c5d 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -107,7 +107,6 @@ struct Raster : PluginBase ~Raster(void); static Raster *createFromImage(Image *image); - static Raster *read(const char *name, const char *mask); enum Format { DEFAULT = 0, @@ -137,12 +136,16 @@ struct Texture : PluginBase Raster *raster; int32 refCount; + // temporary - pointer to next tex in dictionary + Texture *next; + Texture(void); ~Texture(void); void decRef(void); static Texture *streamRead(Stream *stream); bool streamWrite(Stream *stream); uint32 streamGetSize(void); + static Texture *read(const char *name, const char *mask); enum FilterMode { NEAREST = 1, @@ -390,4 +393,15 @@ private: void frameListStreamWrite(Stream *stream, Frame **flp, int32 nf); }; +struct TexDictionary +{ + Texture *first; + + TexDictionary(void); + void add(Texture *tex); + Texture *find(const char *name); +}; + +extern TexDictionary *CurrentTexDictionary; + } diff --git a/src/rwogl.h b/src/rwogl.h index d4bd877..0ed10a4 100644 --- a/src/rwogl.h +++ b/src/rwogl.h @@ -45,7 +45,7 @@ int32 GetSizeNativeSkin(void *object, int32 offset); // Raster -struct Raster : Rw::Raster +struct Texture : Rw::Texture { void upload(void); void bind(int n); diff --git a/tests/gl/main.cpp b/tests/gl/main.cpp index 6e9f697..f814b59 100755 --- a/tests/gl/main.cpp +++ b/tests/gl/main.cpp @@ -49,14 +49,10 @@ renderAtomic(Rw::Atomic *atomic) color[3] = col[3] / 255.0f; glUniform4fv(glGetUniformLocation(program, "matColor"), 1, color); - Texture *tex = mesh->material->texture; - if(tex){ - Rw::Gl::Raster *raster = (Rw::Gl::Raster*)tex->raster; - if(raster) - raster->bind(0); - else - glBindTexture(GL_TEXTURE_2D, 0); - }else + Rw::Gl::Texture *tex =(Rw::Gl::Texture*)mesh->material->texture; + if(tex) + tex->bind(0); + else glBindTexture(GL_TEXTURE_2D, 0); glDrawElements(prim[meshHeader->flags], mesh->numIndices, GL_UNSIGNED_SHORT, (void*)offset); @@ -73,6 +69,7 @@ renderAtomic(Rw::Atomic *atomic) void render(void) { + static Mat4 worldMat(1.0f); glUseProgram(program); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -81,6 +78,8 @@ render(void) 1, GL_FALSE, camera->projMat.cr); glUniformMatrix4fv(glGetUniformLocation(program, "viewMat"), 1, GL_FALSE, camera->viewMat.cr); + glUniformMatrix4fv(glGetUniformLocation(program, "worldMat"), + 1, GL_FALSE, worldMat.cr); glVertexAttrib3f(2, -0.5f, 0.5f, 0.70710f); glBindBuffer(GL_ARRAY_BUFFER, vbo); @@ -181,6 +180,7 @@ init(void) camera->setTarget(Vec3(0.0f, 0.0f, 0.0f)); camera->setPosition(Vec3(0.0f, 5.0f, 0.0f)); + Rw::CurrentTexDictionary = new Rw::TexDictionary; // Rw::Image::setSearchPath("/home/aap/gamedata/ps2/gtasa/models/gta3_archive/txd_extracted/"); // Rw::Image::setSearchPath("/home/aap/gamedata/ps2/gtavc/MODELS/gta3_archive/txd_extracted/"); Rw::Image::setSearchPath("/home/aap/gamedata/ps2/gtavc/MODELS/gta3_archive/txd_extracted/;/home/aap/gamedata/ps2/gtasa/models/gta3_archive/txd_extracted/");