2015-01-07 23:06:44 +01:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
#include <cassert>
|
2015-06-10 22:52:59 +02:00
|
|
|
|
2015-01-07 23:06:44 +01:00
|
|
|
#include <new>
|
|
|
|
|
|
|
|
#include "rwbase.h"
|
|
|
|
#include "rwplugin.h"
|
2015-07-11 23:48:11 +02:00
|
|
|
#include "rwpipeline.h"
|
2015-01-07 23:06:44 +01:00
|
|
|
#include "rwobjects.h"
|
|
|
|
#include "gtaplg.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
2015-01-25 22:27:03 +01:00
|
|
|
namespace gta {
|
2015-01-07 23:06:44 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// Frame
|
|
|
|
//
|
|
|
|
|
|
|
|
// Node Name
|
|
|
|
|
2015-01-25 22:27:03 +01:00
|
|
|
int32 nodeNameOffset;
|
2015-01-17 00:29:50 +01:00
|
|
|
|
2015-01-07 23:06:44 +01:00
|
|
|
static void*
|
|
|
|
createNodeName(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
char *name = PLUGINOFFSET(char, object, offset);
|
|
|
|
name[0] = '\0';
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
copyNodeName(void *dst, void *src, int32 offset, int32)
|
|
|
|
{
|
|
|
|
char *dstname = PLUGINOFFSET(char, dst, offset);
|
|
|
|
char *srcname = PLUGINOFFSET(char, src, offset);
|
2015-01-17 00:29:50 +01:00
|
|
|
strncpy(dstname, srcname, 23);
|
2015-01-07 23:06:44 +01:00
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
destroyNodeName(void *object, int32, int32)
|
|
|
|
{
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
readNodeName(Stream *stream, int32 len, void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
char *name = PLUGINOFFSET(char, object, offset);
|
|
|
|
stream->read(name, len);
|
|
|
|
name[len] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
writeNodeName(Stream *stream, int32 len, void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
char *name = PLUGINOFFSET(char, object, offset);
|
|
|
|
stream->write(name, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32
|
2015-01-17 00:29:50 +01:00
|
|
|
getSizeNodeName(void *object, int32 offset, int32)
|
2015-01-07 23:06:44 +01:00
|
|
|
{
|
|
|
|
char *name = PLUGINOFFSET(char, object, offset);
|
|
|
|
int32 len = strlen(name);
|
|
|
|
return len > 0 ? len : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2015-01-25 22:27:03 +01:00
|
|
|
registerNodeNamePlugin(void)
|
2015-01-07 23:06:44 +01:00
|
|
|
{
|
2015-01-25 22:27:03 +01:00
|
|
|
nodeNameOffset = Frame::registerPlugin(24, ID_NODENAME,
|
2015-01-17 00:29:50 +01:00
|
|
|
createNodeName,
|
|
|
|
destroyNodeName,
|
|
|
|
copyNodeName);
|
|
|
|
Frame::registerPluginStream(ID_NODENAME,
|
|
|
|
readNodeName,
|
|
|
|
writeNodeName,
|
|
|
|
getSizeNodeName);
|
2015-01-07 23:06:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Geometry
|
|
|
|
//
|
|
|
|
|
|
|
|
// Breakable Model
|
|
|
|
|
2015-01-25 22:27:03 +01:00
|
|
|
int32 breakableOffset;
|
2015-01-17 00:29:50 +01:00
|
|
|
|
2015-01-07 23:06:44 +01:00
|
|
|
static void*
|
|
|
|
createBreakableModel(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
*PLUGINOFFSET(uint8*, object, offset) = 0;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
destroyBreakableModel(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
uint8 *p = *PLUGINOFFSET(uint8*, object, offset);
|
|
|
|
delete[] p;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
readBreakableModel(Stream *stream, int32, void *object, int32 o, int32)
|
|
|
|
{
|
|
|
|
uint32 header[13];
|
|
|
|
uint32 hasBreakable = stream->readU32();
|
|
|
|
if(hasBreakable == 0)
|
|
|
|
return;
|
|
|
|
stream->read(header, 13*4);
|
|
|
|
uint32 size = header[1]*(12+8+4) + header[5]*(6+2) +
|
|
|
|
header[8]*(32+32+12);
|
|
|
|
uint8 *p = new uint8[sizeof(Breakable)+size];
|
|
|
|
Breakable *breakable = (Breakable*)p;
|
|
|
|
*PLUGINOFFSET(Breakable*, object, o) = breakable;
|
|
|
|
breakable->position = header[0];
|
|
|
|
breakable->numVertices = header[1];
|
|
|
|
breakable->numFaces = header[5];
|
|
|
|
breakable->numMaterials = header[8];
|
|
|
|
p += sizeof(Breakable);
|
|
|
|
stream->read(p, size);
|
|
|
|
breakable->vertices = (float*)p;
|
|
|
|
p += breakable->numVertices*12;
|
|
|
|
breakable->texCoords = (float*)p;
|
|
|
|
p += breakable->numVertices*8;
|
|
|
|
breakable->colors = (uint8*)p;
|
|
|
|
p += breakable->numVertices*4;
|
|
|
|
breakable->faces = (uint16*)p;
|
|
|
|
p += breakable->numFaces*6;
|
|
|
|
breakable->matIDs = (uint16*)p;
|
|
|
|
p += breakable->numFaces*2;
|
|
|
|
breakable->texNames = (char(*)[32])p;
|
|
|
|
p += breakable->numMaterials*32;
|
|
|
|
breakable->maskNames = (char(*)[32])p;
|
|
|
|
p += breakable->numMaterials*32;
|
|
|
|
breakable->surfaceProps = (float32(*)[3])p;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
writeBreakableModel(Stream *stream, int32, void *object, int32 o, int32)
|
|
|
|
{
|
|
|
|
uint32 header[13];
|
|
|
|
Breakable *breakable = *PLUGINOFFSET(Breakable*, object, o);
|
|
|
|
uint8 *p = (uint8*)breakable;
|
|
|
|
if(breakable == NULL){
|
|
|
|
stream->writeU32(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
stream->writeU32(1);
|
|
|
|
memset((char*)header, 0, 13*4);
|
|
|
|
header[0] = breakable->position;
|
|
|
|
header[1] = breakable->numVertices;
|
|
|
|
header[5] = breakable->numFaces;
|
|
|
|
header[8] = breakable->numMaterials;
|
|
|
|
stream->write(header, 13*4);
|
|
|
|
p += sizeof(Breakable);
|
|
|
|
stream->write(p, breakable->numVertices*(12+8+4) +
|
|
|
|
breakable->numFaces*(6+2) +
|
|
|
|
breakable->numMaterials*(32+32+12));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32
|
|
|
|
getSizeBreakableModel(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
Breakable *breakable = *PLUGINOFFSET(Breakable*, object, offset);
|
|
|
|
if(breakable == NULL)
|
|
|
|
return 4;
|
|
|
|
return 56 + breakable->numVertices*(12+8+4) +
|
|
|
|
breakable->numFaces*(6+2) +
|
|
|
|
breakable->numMaterials*(32+32+12);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-01-25 22:27:03 +01:00
|
|
|
registerBreakableModelPlugin(void)
|
2015-01-07 23:06:44 +01:00
|
|
|
{
|
2015-01-25 22:27:03 +01:00
|
|
|
breakableOffset = Geometry::registerPlugin(sizeof(Breakable*),
|
2015-01-17 00:29:50 +01:00
|
|
|
ID_BREAKABLE,
|
|
|
|
createBreakableModel,
|
|
|
|
destroyBreakableModel, NULL);
|
2015-01-07 23:06:44 +01:00
|
|
|
Geometry::registerPluginStream(ID_BREAKABLE,
|
2015-01-17 00:29:50 +01:00
|
|
|
readBreakableModel,
|
|
|
|
writeBreakableModel,
|
|
|
|
getSizeBreakableModel);
|
2015-01-07 23:06:44 +01:00
|
|
|
}
|
|
|
|
|
2015-08-17 10:24:24 +02:00
|
|
|
// Extra normals
|
|
|
|
|
|
|
|
int32 extraNormalsOffset;
|
|
|
|
|
|
|
|
static void*
|
|
|
|
createExtraNormals(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
*PLUGINOFFSET(float*, object, offset) = NULL;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
destroyExtraNormals(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
float *extranormals = *PLUGINOFFSET(float*, object, offset);
|
|
|
|
delete[] extranormals;
|
|
|
|
*PLUGINOFFSET(float*, object, offset) = NULL;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
readExtraNormals(Stream *stream, int32, void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
Geometry *geo = (Geometry*)object;
|
|
|
|
float **plgp = PLUGINOFFSET(float*, object, offset);
|
|
|
|
if(*plgp)
|
|
|
|
delete[] *plgp;
|
|
|
|
float *extranormals = *plgp = new float[geo->numVertices*3];
|
|
|
|
stream->read(extranormals, geo->numVertices*3*4);
|
|
|
|
|
|
|
|
// for(int i = 0; i < geo->numVertices; i++){
|
|
|
|
// float *nx = extranormals+i*3;
|
|
|
|
// float *n = geo->morphTargets[0].normals;
|
|
|
|
// float len = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
|
|
|
|
// printf("%f %f %f %f\n", n[0], n[1], n[2], len);
|
|
|
|
// printf("%f %f %f\n", nx[0], nx[1], nx[2]);
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
writeExtraNormals(Stream *stream, int32, void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
Geometry *geo = (Geometry*)object;
|
|
|
|
float *extranormals = *PLUGINOFFSET(float*, object, offset);
|
|
|
|
assert(extranormals != NULL);
|
|
|
|
stream->write(extranormals, geo->numVertices*3*4);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32
|
|
|
|
getSizeExtraNormals(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
Geometry *geo = (Geometry*)object;
|
|
|
|
if(*PLUGINOFFSET(float*, object, offset))
|
|
|
|
return geo->numVertices*3*4;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
registerExtraNormalsPlugin(void)
|
|
|
|
{
|
|
|
|
extraNormalsOffset = Geometry::registerPlugin(sizeof(void*),
|
|
|
|
ID_EXTRANORMALS,
|
|
|
|
createExtraNormals,
|
|
|
|
destroyExtraNormals,
|
|
|
|
NULL);
|
|
|
|
Geometry::registerPluginStream(ID_EXTRANORMALS,
|
|
|
|
readExtraNormals,
|
|
|
|
writeExtraNormals,
|
|
|
|
getSizeExtraNormals);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-07 23:06:44 +01:00
|
|
|
// Extra colors
|
|
|
|
|
2015-01-25 22:27:03 +01:00
|
|
|
int32 extraVertColorOffset;
|
2015-01-07 23:06:44 +01:00
|
|
|
|
|
|
|
static void*
|
|
|
|
createExtraVertColors(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
ExtraVertColors *colordata =
|
|
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
|
|
colordata->nightColors = NULL;
|
|
|
|
colordata->dayColors = NULL;
|
|
|
|
colordata->balance = 0.0f;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
destroyExtraVertColors(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
ExtraVertColors *colordata =
|
|
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
|
|
delete[] colordata->nightColors;
|
|
|
|
delete[] colordata->dayColors;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
readExtraVertColors(Stream *stream, int32, void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
uint32 hasData;
|
|
|
|
ExtraVertColors *colordata =
|
|
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
|
|
hasData = stream->readU32();
|
|
|
|
if(!hasData)
|
|
|
|
return;
|
|
|
|
Geometry *geometry = (Geometry*)object;
|
|
|
|
colordata->nightColors = new uint8[geometry->numVertices*4];
|
|
|
|
colordata->dayColors = new uint8[geometry->numVertices*4];
|
|
|
|
colordata->balance = 1.0f;
|
|
|
|
stream->read(colordata->nightColors, geometry->numVertices*4);
|
2015-08-17 10:24:24 +02:00
|
|
|
printf("extra colors\n");
|
2015-01-07 23:06:44 +01:00
|
|
|
if(geometry->colors)
|
|
|
|
memcpy(colordata->dayColors, geometry->colors,
|
|
|
|
geometry->numVertices*4);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
writeExtraVertColors(Stream *stream, int32, void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
ExtraVertColors *colordata =
|
|
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
|
|
stream->writeU32(colordata->nightColors != NULL);
|
|
|
|
if(colordata->nightColors){
|
|
|
|
Geometry *geometry = (Geometry*)object;
|
|
|
|
stream->write(colordata->nightColors, geometry->numVertices*4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32
|
|
|
|
getSizeExtraVertColors(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
ExtraVertColors *colordata =
|
|
|
|
PLUGINOFFSET(ExtraVertColors, object, offset);
|
|
|
|
Geometry *geometry = (Geometry*)object;
|
|
|
|
if(colordata->nightColors)
|
|
|
|
return 4 + geometry->numVertices*4;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-01-25 22:27:03 +01:00
|
|
|
registerExtraVertColorPlugin(void)
|
2015-01-07 23:06:44 +01:00
|
|
|
{
|
2015-01-25 22:27:03 +01:00
|
|
|
extraVertColorOffset = Geometry::registerPlugin(sizeof(ExtraVertColors),
|
2015-01-17 00:29:50 +01:00
|
|
|
ID_EXTRAVERTCOLORS,
|
|
|
|
createExtraVertColors,
|
2015-01-19 13:32:12 +01:00
|
|
|
destroyExtraVertColors,
|
|
|
|
NULL);
|
2015-01-07 23:06:44 +01:00
|
|
|
Geometry::registerPluginStream(ID_EXTRAVERTCOLORS,
|
2015-01-17 00:29:50 +01:00
|
|
|
readExtraVertColors,
|
|
|
|
writeExtraVertColors,
|
|
|
|
getSizeExtraVertColors);
|
2015-01-07 23:06:44 +01:00
|
|
|
}
|
|
|
|
|
2015-01-19 13:32:12 +01:00
|
|
|
// Environment mat
|
|
|
|
|
2015-01-25 22:27:03 +01:00
|
|
|
int32 envMatOffset;
|
2015-01-19 13:32:12 +01:00
|
|
|
|
|
|
|
static void*
|
|
|
|
createEnvMat(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
*PLUGINOFFSET(EnvMat*, object, offset) = NULL;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
destroyEnvMat(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
EnvMat **envmat = PLUGINOFFSET(EnvMat*, object, offset);
|
|
|
|
delete *envmat;
|
|
|
|
*envmat = NULL;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
copyEnvMat(void *dst, void *src, int32 offset, int32)
|
|
|
|
{
|
|
|
|
EnvMat *srcenv = *PLUGINOFFSET(EnvMat*, src, offset);
|
|
|
|
if(srcenv == NULL)
|
|
|
|
return dst;
|
|
|
|
EnvMat *dstenv = new EnvMat;
|
|
|
|
dstenv->scaleX = srcenv->scaleX;
|
|
|
|
dstenv->scaleY = srcenv->scaleY;
|
|
|
|
dstenv->transScaleX = srcenv->transScaleX;
|
|
|
|
dstenv->transScaleY = srcenv->transScaleY;
|
|
|
|
dstenv->shininess = srcenv->shininess;
|
|
|
|
dstenv->texture = NULL;
|
|
|
|
*PLUGINOFFSET(EnvMat*, dst, offset) = dstenv;
|
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct EnvStream {
|
|
|
|
float scaleX, scaleY;
|
|
|
|
float transScaleX, transScaleY;
|
|
|
|
float shininess;
|
|
|
|
int32 zero;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
readEnvMat(Stream *stream, int32, void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
EnvStream buf;
|
|
|
|
EnvMat *env = new EnvMat;
|
|
|
|
*PLUGINOFFSET(EnvMat*, object, offset) = env;
|
|
|
|
stream->read(&buf, sizeof(buf));
|
|
|
|
env->scaleX = (int8)(buf.scaleX*8.0f);
|
|
|
|
env->scaleY = (int8)(buf.scaleY*8.0f);
|
|
|
|
env->transScaleX = (int8)(buf.transScaleX*8.0f);
|
|
|
|
env->transScaleY = (int8)(buf.transScaleY*8.0f);
|
|
|
|
env->shininess = (int8)(buf.shininess*255.0f);
|
|
|
|
env->texture = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
writeEnvMat(Stream *stream, int32, void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
EnvStream buf;
|
|
|
|
EnvMat *env = *PLUGINOFFSET(EnvMat*, object, offset);
|
|
|
|
buf.scaleX = env->scaleX/8.0f;
|
|
|
|
buf.scaleY = env->scaleY/8.0f;
|
|
|
|
buf.transScaleX = env->transScaleX/8.0f;
|
|
|
|
buf.transScaleY = env->transScaleY/8.0f;
|
|
|
|
buf.shininess = env->shininess/8.0f;
|
|
|
|
buf.zero = 0;
|
|
|
|
stream->write(&buf, sizeof(buf));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32
|
|
|
|
getSizeEnvMat(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
EnvMat *env = *PLUGINOFFSET(EnvMat*, object, offset);
|
2015-06-18 23:05:37 +02:00
|
|
|
return env ? (int)sizeof(EnvStream) : -1;
|
2015-01-19 13:32:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Specular mat
|
|
|
|
|
2015-01-25 22:27:03 +01:00
|
|
|
int32 specMatOffset;
|
2015-01-19 13:32:12 +01:00
|
|
|
|
|
|
|
static void*
|
|
|
|
createSpecMat(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
*PLUGINOFFSET(SpecMat*, object, offset) = NULL;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
destroySpecMat(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
SpecMat **specmat = PLUGINOFFSET(SpecMat*, object, offset);
|
|
|
|
if((*specmat)->texture)
|
|
|
|
(*specmat)->texture->decRef();
|
|
|
|
delete *specmat;
|
|
|
|
*specmat = NULL;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
copySpecMat(void *dst, void *src, int32 offset, int32)
|
|
|
|
{
|
|
|
|
SpecMat *srcspec = *PLUGINOFFSET(SpecMat*, src, offset);
|
|
|
|
if(srcspec == NULL)
|
|
|
|
return dst;
|
|
|
|
SpecMat *dstspec = new SpecMat;
|
|
|
|
*PLUGINOFFSET(SpecMat*, dst, offset) = dstspec;
|
|
|
|
dstspec->specularity = srcspec->specularity;
|
|
|
|
dstspec->texture = srcspec->texture;
|
|
|
|
dstspec->texture->refCount++;
|
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct SpecStream {
|
|
|
|
float specularity;
|
|
|
|
char texname[24];
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
readSpecMat(Stream *stream, int32, void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
SpecStream buf;
|
|
|
|
SpecMat *spec = new SpecMat;
|
|
|
|
*PLUGINOFFSET(SpecMat*, object, offset) = spec;
|
|
|
|
stream->read(&buf, sizeof(buf));
|
|
|
|
spec->specularity = buf.specularity;
|
|
|
|
spec->texture = new Texture;
|
|
|
|
strncpy(spec->texture->name, buf.texname, 24);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
writeSpecMat(Stream *stream, int32, void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
SpecStream buf;
|
|
|
|
SpecMat *spec = *PLUGINOFFSET(SpecMat*, object, offset);
|
|
|
|
buf.specularity = spec->specularity;
|
|
|
|
strncpy(buf.texname, spec->texture->name, 24);
|
|
|
|
stream->write(&buf, sizeof(buf));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32
|
|
|
|
getSizeSpecMat(void *object, int32 offset, int32)
|
|
|
|
{
|
|
|
|
SpecMat *spec = *PLUGINOFFSET(SpecMat*, object, offset);
|
2015-06-18 23:05:37 +02:00
|
|
|
return spec ? (int)sizeof(SpecStream) : -1;
|
2015-01-19 13:32:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-01-25 22:27:03 +01:00
|
|
|
registerEnvSpecPlugin(void)
|
2015-01-19 13:32:12 +01:00
|
|
|
{
|
2015-01-25 22:27:03 +01:00
|
|
|
specMatOffset = Material::registerPlugin(sizeof(SpecMat*), ID_SPECMAT,
|
2015-01-19 13:32:12 +01:00
|
|
|
createSpecMat,
|
|
|
|
destroySpecMat,
|
|
|
|
copySpecMat);
|
|
|
|
Material::registerPluginStream(ID_SPECMAT, readSpecMat,
|
|
|
|
writeSpecMat,
|
|
|
|
getSizeSpecMat);
|
2015-01-25 22:27:03 +01:00
|
|
|
envMatOffset = Material::registerPlugin(sizeof(EnvMat*), ID_ENVMAT,
|
2015-01-19 13:32:12 +01:00
|
|
|
createEnvMat,
|
|
|
|
destroyEnvMat,
|
|
|
|
copyEnvMat);
|
|
|
|
Material::registerPluginStream(ID_ENVMAT, readEnvMat,
|
|
|
|
writeEnvMat,
|
|
|
|
getSizeEnvMat);
|
|
|
|
}
|
|
|
|
|
2015-01-07 23:06:44 +01:00
|
|
|
}
|