mirror of
https://github.com/aap/librw.git
synced 2025-12-18 16:39:51 +00:00
Started implementing Rasters. OpenGL test has textures now.
This commit is contained in:
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user