librw/src/light.cpp

164 lines
3.3 KiB
C++
Raw Normal View History

2020-04-30 17:54:38 +02:00
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#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"
2017-08-24 15:10:34 +02:00
#define PLUGIN_ID ID_LIGHT
namespace rw {
int32 Light::numAllocated;
2020-04-25 00:37:49 +02:00
PluginList Light::s_plglist(sizeof(Light));
static void
lightSync(ObjectWithFrame*)
{
}
2016-06-23 16:39:34 +02:00
static void
worldLightSync(ObjectWithFrame *obj)
{
Light *light = (Light*)obj;
light->originalSync(obj);
}
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){
RWERROR((ERR_ALLOC, s_plglist.size));
2016-06-17 13:29:49 +02:00
return nil;
}
numAllocated++;
light->object.object.init(Light::ID, type);
light->object.syncCB = lightSync;
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;
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;
s_plglist.construct(light);
return light;
}
void
Light::destroy(void)
{
s_plglist.destruct(this);
2020-04-18 20:30:22 +02:00
assert(this->clump == nil);
assert(this->world == nil);
2020-08-10 08:22:50 +02:00
this->setFrame(nil);
2017-08-24 15:10:34 +02:00
rwFree(this);
numAllocated--;
}
void
Light::setAngle(float32 angle)
{
2020-06-04 21:56:17 +02:00
this->minusCosAngle = -cosf(angle);
}
float32
Light::getAngle(void)
{
2020-06-04 21:56:17 +02:00
return acosf(-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;
uint32 type_flags;
};
Light*
Light::streamRead(Stream *stream)
{
uint32 version;
LightChunkData buf;
2016-06-17 13:29:49 +02:00
if(!findChunk(stream, ID_STRUCT, nil, &version)){
RWERROR((ERR_CHUNK, "STRUCT"));
2016-06-17 13:29:49 +02:00
return nil;
}
stream->read32(&buf, sizeof(LightChunkData));
Light *light = Light::create(buf.type_flags>>16);
2016-06-17 13:29:49 +02:00
if(light == nil)
return nil;
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
2020-06-04 21:56:17 +02:00
light->minusCosAngle = -1.0f/sqrtf(a*a+1.0f);
light->object.object.flags = (uint8)buf.type_flags;
if(s_plglist.streamRead(stream, light))
2016-06-17 13:29:49 +02:00
return light;
light->destroy();
return nil;
}
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
2020-06-04 21:56:17 +02:00
buf.minusCosAngle = tanf(acosf(-this->minusCosAngle));
buf.type_flags = (uint32)this->object.object.flags |
(uint32)this->object.object.subType << 16;
stream->write32(&buf, sizeof(LightChunkData));
s_plglist.streamWrite(stream, this);
return true;
}
uint32
Light::streamGetSize(void)
{
return 12 + sizeof(LightChunkData) + 12 + s_plglist.streamGetSize(this);
}
}