Started implementing Rasters. OpenGL test has textures now.

This commit is contained in:
Angelo Papenhoff 2015-01-20 14:48:18 +01:00
parent 542e56d7a2
commit 0d6216554c
8 changed files with 320 additions and 27 deletions

View File

@ -58,9 +58,12 @@ main(int argc, char *argv[])
in.close();
delete[] data;
Rw::Image::setSearchPath("./;/home/aap/gamedata/ps2/gtavc/MODELS/gta3_archive/txd_extracted/");
// Rw::Image *tga = Rw::readTGA("b.tga");
// assert(tga != NULL);
// Rw::writeTGA(tga, "out.tga");
Rw::Image *tga = Rw::readTGA("player.tga");
assert(tga != NULL);
Rw::writeTGA(tga, "out.tga");
// for(Rw::int32 i = 0; i < c->numAtomics; i++)
// Rw::Gl::Instance(c->atomicList[i]);

View File

@ -49,6 +49,7 @@ Geometry::Geometry(int32 numVerts, int32 numTris, uint32 flags)
this->numMaterials = 0;
this->materialList = NULL;
this->meshHeader = NULL;
this->instData = NULL;
this->refCount = 1;
this->constructPlugins();
@ -438,6 +439,7 @@ 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();
}
@ -462,6 +464,7 @@ Texture::streamRead(Stream *stream)
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));
@ -470,6 +473,10 @@ Texture::streamRead(Stream *stream)
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;
@ -483,17 +490,12 @@ Texture::streamWrite(Stream *stream)
WriteChunkHeader(stream, ID_STRUCT, 4);
stream->writeU32(this->filterAddressing);
// TODO: 4 char string -> 8 bytes
// TODO: length can't be > 32
size = strlen(this->name)+3 & ~3;
if(size < 4)
size = 4;
size = strlen(this->name)+4 & ~3;
WriteChunkHeader(stream, ID_STRING, size);
stream->write(this->name, size);
size = strlen(this->mask)+3 & ~3;
if(size < 4)
size = 4;
size = strlen(this->mask)+4 & ~3;
WriteChunkHeader(stream, ID_STRING, size);
stream->write(this->mask, size);
@ -508,11 +510,8 @@ Texture::streamGetSize(void)
int strsize;
size += 12 + 4;
size += 12 + 12;
// TODO: see above
strsize = strlen(this->name)+3 & ~3;
size += strsize < 4 ? 4 : strsize;
strsize = strlen(this->mask)+3 & ~3;
size += strsize < 4 ? 4 : strsize;
size += strlen(this->name)+4 & ~3;
size += strlen(this->mask)+4 & ~3;
size += 12 + this->streamGetPluginSize();
return size;
}

View File

@ -29,6 +29,9 @@ writeUInt8(uint8 tmp, ostream &rw)
return sizeof(uint8);
}
//
// Image
//
Image::Image(int32 width, int32 height, int32 depth)
{
@ -84,6 +87,71 @@ Image::setPalette(uint8 *palette)
this->flags |= 2;
}
static char *searchPaths = NULL;
int numSearchPaths = 0;
void
Image::setSearchPath(const char *path)
{
char *p, *end;
::free(searchPaths);
numSearchPaths = 0;
if(path)
searchPaths = p = strdup(path);
else{
searchPaths = NULL;
return;
}
while(p && *p){
end = strchr(p, ';');
if(end)
*end++ = '\0';
numSearchPaths++;
p = end;
}
}
void
Image::printSearchPath(void)
{
char *p = searchPaths;
for(int i = 0; i < numSearchPaths; i++){
printf("%s\n", p);
p += strlen(p) + 1;
}
}
char*
Image::getFilename(const char *name)
{
FILE *f;
char *s, *p = searchPaths;
int len = strlen(name)+1;
if(numSearchPaths == 0){
f = fopen(name, "r");
if(f){
fclose(f);
printf("found %s\n", name);
return strdup(name);
}
return NULL;
}else
for(int i = 0; i < numSearchPaths; i++){
s = (char*)malloc(strlen(p)+len);
strcpy(s, p);
strcat(s, name);
f = fopen(s, "r");
if(f){
fclose(f);
printf("found %s\n", name);
return s;
}
::free(s);
p += strlen(p) + 1;
}
return NULL;
}
//
// TGA I/O
//
@ -106,13 +174,18 @@ struct __attribute__((__packed__)) TGAHeader
//#pragma pack(push)
Image*
readTGA(const char *filename)
readTGA(const char *afilename)
{
TGAHeader header;
Image *image;
char *filename;
int depth = 0, palDepth = 0;
// TODO: open from image path
filename = Image::getFilename(afilename);
if(filename == NULL)
return NULL;
ifstream file(filename, ios::binary);
free(filename);
file.read((char*)&header, sizeof(header));
assert(header.imageType == 1 || header.imageType == 2);
@ -225,4 +298,76 @@ writeTGA(Image *image, const char *filename)
file.close();
}
//
// Raster
//
Raster::Raster(void)
{
this->type = 0;
this->width = this->height = this->depth = this->stride = 0;
this->format = 0;
this->texels = this->palette = NULL;
this->constructPlugins();
}
Raster::~Raster(void)
{
this->destructPlugins();
delete[] this->texels;
delete[] this->palette;
}
Raster*
Raster::createFromImage(Image *image)
{
Raster *raster = new Raster;
raster->type = 4;
raster->width = image->width;
raster->stride = image->stride;
raster->height = image->height;
raster->depth = image->depth;
raster->texels = raster->palette = NULL;
if(raster->depth == 32)
raster->format = Raster::C8888;
else if(raster->depth == 24)
raster->format = Raster::C888;
else if(raster->depth == 16)
raster->format = Raster::C1555;
else if(raster->depth == 8)
raster->format = Raster::PAL8 | Raster::C8888;
else if(raster->depth == 4)
raster->format = Raster::PAL4 | Raster::C8888;
else{
delete raster;
return NULL;
}
raster->texels = new uint8[raster->stride*raster->height];
memcpy(raster->texels, image->pixels, raster->stride*raster->height);
if(image->palette){
int size = raster->depth == 4 ? 16 : 256;
raster->palette = new uint8[size*4];
memcpy(raster->palette, image->palette, size*4);
}
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

@ -389,5 +389,87 @@ GetSizeNativeSkin(void *object, int32 offset)
return size;
}
// Raster
int32 NativeRasterOffset;
#ifdef RW_OPENGL
struct GlRaster {
GLuint id;
};
static void*
createNativeRaster(void *object, int32 offset, int32)
{
GlRaster *raster = PLUGINOFFSET(GlRaster, object, offset);
raster->id = 0;
return object;
}
static void*
destroyNativeRaster(void *object, int32 offset, int32)
{
// TODO:
return object;
}
static void*
copyNativeRaster(void *dst, void *, int32 offset, int32)
{
GlRaster *raster = PLUGINOFFSET(GlRaster, dst, offset);
raster->id = 0;
return dst;
}
void
RegisterNativeRaster(void)
{
NativeRasterOffset = Raster::registerPlugin(sizeof(GlRaster),
0x12340001,
createNativeRaster,
destroyNativeRaster,
copyNativeRaster);
}
void
Raster::upload(void)
{
GLuint id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
if(this->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);
break;
default:
printf("unsupported raster format: %x\n", this->format);
break;
}
glBindTexture(GL_TEXTURE_2D, 0);
GlRaster *glr = PLUGINOFFSET(GlRaster, this, NativeRasterOffset);
glr->id = id;
}
void
Raster::bind(int n)
{
GlRaster *raster = PLUGINOFFSET(GlRaster, this, NativeRasterOffset);
if(raster->id == 0)
this->upload();
glActiveTexture(GL_TEXTURE0+n);
glBindTexture(GL_TEXTURE_2D, raster->id);
glActiveTexture(GL_TEXTURE0);
}
#endif
}
}

View File

@ -21,7 +21,7 @@ namespace Rw {
int32 HAnimOffset;
static void*
createHAnim(void *object, int32 offset, int32 size)
createHAnim(void *object, int32 offset, int32)
{
HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset);
hanim->id = -1;
@ -30,7 +30,7 @@ createHAnim(void *object, int32 offset, int32 size)
}
static void*
destroyHAnim(void *object, int32 offset, int32 size)
destroyHAnim(void *object, int32 offset, int32)
{
HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset);
if(hanim->hierarchy){
@ -45,7 +45,7 @@ destroyHAnim(void *object, int32 offset, int32 size)
}
static void*
copyHAnim(void *dst, void *src, int32 offset, int32 size)
copyHAnim(void *dst, void *src, int32 offset, int32)
{
HAnimData *dsthanim = PLUGINOFFSET(HAnimData, dst, offset);
HAnimData *srchanim = PLUGINOFFSET(HAnimData, src, offset);
@ -56,7 +56,7 @@ copyHAnim(void *dst, void *src, int32 offset, int32 size)
}
static void
readHAnim(Stream *stream, int32 len, void *object, int32 offset, int32)
readHAnim(Stream *stream, int32, void *object, int32 offset, int32)
{
int32 cnst, numNodes;
HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset);
@ -94,7 +94,7 @@ readHAnim(Stream *stream, int32 len, void *object, int32 offset, int32)
}
static void
writeHAnim(Stream *stream, int32 len, void *object, int32 offset, int32)
writeHAnim(Stream *stream, int32, void *object, int32 offset, int32)
{
HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset);
stream->writeI32(256);
@ -587,7 +587,6 @@ static void
readAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32)
{
int32 flag;
uint32 version;
stream->read(&flag, 4);
*PLUGINOFFSET(int32, object, offset) = flag;
if(flag)

View File

@ -86,16 +86,55 @@ struct Image
void free(void);
void setPixels(uint8 *pixels);
void setPalette(uint8 *palette);
static void setSearchPath(const char*);
static void printSearchPath(void);
static char *getFilename(const char*);
};
Image *readTGA(const char *filename);
void writeTGA(Image *image, const char *filename);
// TODO: raster, link into texdict
struct Raster : PluginBase<Raster>
{
int32 type; // hardly used
int32 width, height, depth;
int32 stride;
int32 format;
uint8 *texels;
uint8 *palette;
Raster(void);
~Raster(void);
static Raster *createFromImage(Image *image);
static Raster *read(const char *name, const char *mask);
enum Format {
DEFAULT = 0,
C1555 = 0x100,
C565 = 0x200,
C4444 = 0x300,
LUM8 = 0x400,
C8888 = 0x500,
C888 = 0x600,
D16 = 0x700,
D24 = 0x800,
D32 = 0x900,
C555 = 0xa00,
AUTOMIPMAP = 0x1000,
PAL8 = 0x2000,
PAL4 = 0x4000,
MIPMAP = 0x8000
};
};
// TODO: link into texdict
struct Texture : PluginBase<Texture>
{
char name[32];
char mask[32];
uint32 filterAddressing;
Raster *raster;
int32 refCount;
Texture(void);

View File

@ -43,5 +43,16 @@ void ReadNativeSkin(Stream *stream, int32, void *object, int32 offset);
void WriteNativeSkin(Stream *stream, int32 len, void *object, int32 offset);
int32 GetSizeNativeSkin(void *object, int32 offset);
// Raster
struct Raster : Rw::Raster
{
void upload(void);
void bind(int n);
};
extern int32 NativeRasterOffset;
void RegisterNativeRaster(void);
}
}

View File

@ -41,6 +41,15 @@ renderAtomic(Rw::Atomic *atomic)
uint64 offset = 0;
for(uint32 i = 0; i < meshHeader->numMeshes; i++){
Mesh *mesh = &meshHeader->mesh[i];
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
glBindTexture(GL_TEXTURE_2D, 0);
glDrawElements(prim[meshHeader->flags], mesh->numIndices,
GL_UNSIGNED_SHORT, (void*)offset);
offset += mesh->numIndices*2;
@ -96,10 +105,11 @@ init(void)
"uniform mat4 viewMat;"
"uniform mat4 worldMat;"
"attribute vec3 in_vertex;"
"attribute vec3 in_texColor;"
"attribute vec2 in_texCoord;"
"attribute vec3 in_normal;"
"attribute vec4 in_color;"
"varying vec4 v_color;"
"varying vec2 v_texCoord;"
"vec3 lightdir = vec3(0.5, -0.5, -0.70710);"
"void main()"
"{"
@ -107,13 +117,17 @@ init(void)
" vec3 n = mat3(worldMat) * in_normal;"
" float l = max(0.0, dot(n, -lightdir));"
" v_color = in_color*l;"
" v_texCoord = in_texCoord;"
"}\n"
"#endif\n"
"#ifdef FRAGMENT\n"
"uniform sampler2D u_texture0;"
"varying vec4 v_color;"
"varying vec2 v_texCoord;"
"void main()"
"{"
" gl_FragColor = v_color;"
" vec4 c0 = texture2D(u_texture0, v_texCoord/512.0f);"
" gl_FragColor = v_color*c0;"
"}\n"
"#endif\n";
const char *srcarr[] = { "#define VERTEX", shadersrc };
@ -153,6 +167,10 @@ init(void)
camera->setTarget(Vec3(0.0f, 0.0f, 0.0f));
camera->setPosition(Vec3(0.0f, 5.0f, 0.0f));
// 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/");
Rw::Gl::RegisterNativeRaster();
Rw::RegisterMaterialRightsPlugin();
Rw::RegisterMatFXPlugin();
Rw::RegisterAtomicRightsPlugin();
@ -167,9 +185,6 @@ init(void)
Rw::RegisterMeshPlugin();
Rw::StreamFile in;
// in.open("player-vc-ogl.dff", "rb");
// in.open("player-iii.dff", "rb");
// in.open("admiral-ogl.dff", "rb");
in.open(filename, "rb");
Rw::FindChunk(&in, Rw::ID_CLUMP, NULL, NULL);
clump = Rw::Clump::streamRead(&in);