Implemented basic TexDictionary.

This commit is contained in:
Angelo Papenhoff 2015-01-20 19:22:57 +01:00
parent fb78a7a7b9
commit 62c6fe006e
6 changed files with 209 additions and 131 deletions

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -107,7 +107,6 @@ struct Raster : PluginBase<Raster>
~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<Texture>
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;
}

View File

@ -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);

View File

@ -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/");