mirror of https://github.com/aap/librw.git
Started implementing Rasters. OpenGL test has textures now.
This commit is contained in:
parent
542e56d7a2
commit
0d6216554c
|
@ -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]);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
147
src/image.cpp
147
src/image.cpp
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
82
src/ogl.cpp
82
src/ogl.cpp
|
@ -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
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
11
src/rwogl.h
11
src/rwogl.h
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue