1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-10-06 00:57:19 +02:00
openrw/framework2/LoaderCOL.cpp
Daniel Evans 04a8a7d9c5 Improved Collision data loading and debugging.
- Removed interleaved data from CollisionInstance as Bullet didn't
understand.
- Improved performance of the DebugDraw to around 2-3 fps
2013-07-22 02:38:43 +01:00

148 lines
3.4 KiB
C++

#include "renderwure/loaders/LoaderCOL.hpp"
#include <string>
#include <fstream>
template<class T> T readType(char* data, size_t* offset)
{
size_t orgoff = *offset; *offset += sizeof(T);
return *reinterpret_cast<T*>(data+orgoff);
}
bool LoaderCOL::load(char* data, const size_t size)
{
char* dataptr = data;
int version = 1;
size_t dataI = 0;
while( dataI < size ) {
size_t file_base = dataI;
CollTHeader head = readType<CollTHeader>(data, &dataI);
switch(head.magic[3]) {
case 'L':
break;
case '2':
version = 2;
break;
case '3':
version = 3;
break;
}
CollTHeaderV2 head2;
CollTHeaderV3 head3;
std::vector<CollTSphere> spheres;
std::vector<CollTBox> boxes;
std::vector<CollTVertex> meshvertices;
std::vector<CollTFaceTriangle> meshfaces;
if(version >= 2)
{
head2 = readType<CollTHeaderV2>(data, &dataI);
if(version >= 3)
{
head3 = readType<CollTHeaderV3>(data, &dataI);
}
}
if(version == 1)
{
head2.numspheres = readType<uint32_t>(data, &dataI);
head2.offsetspheres = file_base-4;
}
// Read spheres
for( size_t i = 0; i < head2.numspheres; ++i ) {
if(version == 1) {
auto s1 = readType<CollTSphereV1>(data, &dataI);
spheres.push_back({ s1.center, s1.radius, s1.surface });
}
else {
spheres.push_back(readType<CollTSphere>(data, &dataI));
}
}
if(version == 1)
{
// skip unused bytes
dataI += sizeof(uint32_t);
}
if(version == 1)
{
head2.numboxes = readType<uint32_t>(data, &dataI);
head2.offsetboxes = dataI-4;
}
for( size_t i = 0; i < head2.numboxes; ++i) {
boxes.push_back(readType<CollTBox>(data, &dataI));
}
if(version == 1)
{
uint32_t numverts = readType<uint32_t>(data, &dataI);
head2.offsetverts = dataI;
// Skip the vertex data for now, since it's accessed retroactivly.
dataI += numverts * sizeof(CollTVertex);
}
else {
// TODO support version 2 & 3.
}
if(version == 1)
{
head2.numfaces = readType<uint32_t>(data, &dataI);
}
size_t maxvert = 0;
meshfaces.reserve(head2.numfaces);
for( size_t f = 0; f < head2.numfaces; ++f) {
// todo: Support 2-3
CollTFaceV1 face = readType<CollTFaceV1>(data, &dataI);
size_t maxv = std::max(face.a, std::max(face.b, face.c));
maxvert = std::max( maxvert, maxv );
meshfaces.push_back({face.a, face.b, face.c});
}
// Load up to maxvert vertices.
meshvertices.reserve(maxvert+1);
for( size_t v = 0, vertI = head2.offsetverts; v < maxvert+1; ++v ) {
CollTVertex vert = readType<CollTVertex>(data, &vertI);
meshvertices.push_back(vert);
}
dataI += sizeof(CollTFace) * head2.numfaces;
instances.push_back({
version,
head,
head2,
head3,
spheres,
boxes,
meshvertices,
meshfaces
});
dataI = file_base + head.size + sizeof(char) * 8;
}
return true;
}
bool LoaderCOL::load(const std::string& file)
{
std::ifstream dfile(file.c_str());
if ( ! dfile.is_open()) {
return false;
}
dfile.seekg(0, std::ios_base::end);
size_t length = dfile.tellg();
dfile.seekg(0);
char* data = new char[length];
dfile.read(data, length);
auto res = load(data, length);
delete[] data;
return res;
}