2016-06-17 00:06:37 +02:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
|
|
|
|
#include "rwbase.h"
|
|
|
|
#include "rwerror.h"
|
|
|
|
#include "rwplg.h"
|
|
|
|
#include "rwpipeline.h"
|
|
|
|
#include "rwobjects.h"
|
2017-08-24 15:10:34 +02:00
|
|
|
#include "rwengine.h"
|
2016-06-17 00:06:37 +02:00
|
|
|
|
2017-08-24 15:10:34 +02:00
|
|
|
#define PLUGIN_ID ID_LIGHT
|
2016-06-17 00:06:37 +02:00
|
|
|
|
|
|
|
namespace rw {
|
|
|
|
|
2017-08-10 14:43:52 +02:00
|
|
|
PluginList Light::s_plglist = { sizeof(Light), sizeof(Light), nil, nil };
|
|
|
|
|
2016-06-21 23:16:09 +02:00
|
|
|
static void
|
|
|
|
lightSync(ObjectWithFrame*)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-06-23 16:39:34 +02:00
|
|
|
static void
|
|
|
|
worldLightSync(ObjectWithFrame *obj)
|
|
|
|
{
|
|
|
|
Light *light = (Light*)obj;
|
|
|
|
light->originalSync(obj);
|
|
|
|
}
|
|
|
|
|
2016-06-17 00:06:37 +02:00
|
|
|
Light*
|
|
|
|
Light::create(int32 type)
|
|
|
|
{
|
2017-08-24 15:10:34 +02:00
|
|
|
Light *light = (Light*)rwMalloc(s_plglist.size, MEMDUR_EVENT | ID_LIGHT);
|
2016-06-17 13:29:49 +02:00
|
|
|
if(light == nil){
|
2016-06-25 17:58:52 +02:00
|
|
|
RWERROR((ERR_ALLOC, s_plglist.size));
|
2016-06-17 13:29:49 +02:00
|
|
|
return nil;
|
2016-06-17 00:06:37 +02:00
|
|
|
}
|
|
|
|
light->object.object.init(Light::ID, type);
|
2016-06-21 23:16:09 +02:00
|
|
|
light->object.syncCB = lightSync;
|
2016-06-17 00:06:37 +02:00
|
|
|
light->radius = 0.0f;
|
|
|
|
light->color.red = 1.0f;
|
|
|
|
light->color.green = 1.0f;
|
|
|
|
light->color.blue = 1.0f;
|
|
|
|
light->color.alpha = 1.0f;
|
|
|
|
light->minusCosAngle = 1.0f;
|
|
|
|
light->object.object.privateFlags = 1;
|
|
|
|
light->object.object.flags = LIGHTATOMICS | LIGHTWORLD;
|
2016-06-23 16:39:34 +02:00
|
|
|
light->inWorld.init();
|
|
|
|
|
|
|
|
// clump extension
|
2016-06-17 13:29:49 +02:00
|
|
|
light->clump = nil;
|
2016-06-17 00:06:37 +02:00
|
|
|
light->inClump.init();
|
2016-06-23 16:39:34 +02:00
|
|
|
|
|
|
|
// world extension
|
|
|
|
light->world = nil;
|
|
|
|
light->originalSync = light->object.syncCB;
|
|
|
|
light->object.syncCB = worldLightSync;
|
|
|
|
|
2016-06-25 17:58:52 +02:00
|
|
|
s_plglist.construct(light);
|
2016-06-17 00:06:37 +02:00
|
|
|
return light;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Light::destroy(void)
|
|
|
|
{
|
2016-06-25 17:58:52 +02:00
|
|
|
s_plglist.destruct(this);
|
2016-06-17 00:06:37 +02:00
|
|
|
if(this->clump)
|
|
|
|
this->inClump.remove();
|
2016-06-23 16:39:34 +02:00
|
|
|
// we do not remove from world, be careful
|
2017-08-24 15:10:34 +02:00
|
|
|
rwFree(this);
|
2016-06-17 00:06:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Light::setAngle(float32 angle)
|
|
|
|
{
|
|
|
|
this->minusCosAngle = -cos(angle);
|
|
|
|
}
|
|
|
|
|
|
|
|
float32
|
|
|
|
Light::getAngle(void)
|
|
|
|
{
|
|
|
|
return acos(-this->minusCosAngle);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Light::setColor(float32 r, float32 g, float32 b)
|
|
|
|
{
|
|
|
|
this->color.red = r;
|
|
|
|
this->color.green = g;
|
|
|
|
this->color.blue = b;
|
|
|
|
this->object.object.privateFlags = r == g && r == b;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct LightChunkData
|
|
|
|
{
|
|
|
|
float32 radius;
|
|
|
|
float32 red, green, blue;
|
|
|
|
float32 minusCosAngle;
|
|
|
|
uint16 flags;
|
|
|
|
uint16 type;
|
|
|
|
};
|
|
|
|
|
|
|
|
Light*
|
|
|
|
Light::streamRead(Stream *stream)
|
|
|
|
{
|
|
|
|
uint32 version;
|
|
|
|
LightChunkData buf;
|
|
|
|
|
2016-06-17 13:29:49 +02:00
|
|
|
if(!findChunk(stream, ID_STRUCT, nil, &version)){
|
2016-06-17 00:06:37 +02:00
|
|
|
RWERROR((ERR_CHUNK, "STRUCT"));
|
2016-06-17 13:29:49 +02:00
|
|
|
return nil;
|
2016-06-17 00:06:37 +02:00
|
|
|
}
|
|
|
|
stream->read(&buf, sizeof(LightChunkData));
|
|
|
|
Light *light = Light::create(buf.type);
|
2016-06-17 13:29:49 +02:00
|
|
|
if(light == nil)
|
|
|
|
return nil;
|
2016-06-17 00:06:37 +02:00
|
|
|
light->radius = buf.radius;
|
|
|
|
light->setColor(buf.red, buf.green, buf.blue);
|
|
|
|
float32 a = buf.minusCosAngle;
|
|
|
|
if(version >= 0x30300)
|
|
|
|
light->minusCosAngle = a;
|
|
|
|
else
|
|
|
|
// tan -> -cos
|
|
|
|
light->minusCosAngle = -1.0f/sqrt(a*a+1.0f);
|
|
|
|
light->object.object.flags = (uint8)buf.flags;
|
2016-06-25 17:58:52 +02:00
|
|
|
if(s_plglist.streamRead(stream, light))
|
2016-06-17 13:29:49 +02:00
|
|
|
return light;
|
|
|
|
light->destroy();
|
|
|
|
return nil;
|
2016-06-17 00:06:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Light::streamWrite(Stream *stream)
|
|
|
|
{
|
|
|
|
LightChunkData buf;
|
|
|
|
writeChunkHeader(stream, ID_LIGHT, this->streamGetSize());
|
|
|
|
writeChunkHeader(stream, ID_STRUCT, sizeof(LightChunkData));
|
|
|
|
buf.radius = this->radius;
|
|
|
|
buf.red = this->color.red;
|
|
|
|
buf.green = this->color.green;
|
|
|
|
buf.blue = this->color.blue;
|
|
|
|
if(version >= 0x30300)
|
|
|
|
buf.minusCosAngle = this->minusCosAngle;
|
|
|
|
else
|
|
|
|
buf.minusCosAngle = tan(acos(-this->minusCosAngle));
|
|
|
|
buf.flags = this->object.object.flags;
|
|
|
|
buf.type = this->object.object.subType;
|
|
|
|
stream->write(&buf, sizeof(LightChunkData));
|
|
|
|
|
2016-06-25 17:58:52 +02:00
|
|
|
s_plglist.streamWrite(stream, this);
|
2016-06-17 00:06:37 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32
|
|
|
|
Light::streamGetSize(void)
|
|
|
|
{
|
2016-06-25 17:58:52 +02:00
|
|
|
return 12 + sizeof(LightChunkData) + 12 + s_plglist.streamGetSize(this);
|
2016-06-17 00:06:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|