Added CRandom16 implementation

This commit is contained in:
Jack Andersen 2015-07-27 16:24:36 -10:00
parent a517adcb01
commit fca9e101a2
8 changed files with 278 additions and 4 deletions

142
DataSpec/DNAMP1/CMDL.cpp Normal file
View File

@ -0,0 +1,142 @@
#include <cstddef>
#include "CMDL.hpp"
#include "DNAMP1.hpp"
namespace Retro
{
namespace DNAMP1
{
bool CMDL::ReadToBlender(HECL::BlenderConnection& conn, Athena::io::IStreamReader& reader)
{
reader.setEndian(Athena::BigEndian);
CMDL::Header head;
head.read(reader);
if (head.magic != 0xDEADBABE)
{
Log.report(LogVisor::Error, "invalid CMDL magic");
return false;
}
if (head.version != 2)
{
Log.report(LogVisor::Error, "invalid CMDL version for MP1");
return false;
}
/* Open Py Stream */
HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut();
os << "bm = bmesh.new();\n";
for (size_t s=0 ; s<head.secCount ; ++s)
{
atUint64 secStart = reader.position();
std::unique_ptr<atVec3f[]> vertPos;
std::unique_ptr<atVec3f[]> vertNorm;
typedef atInt16 ShortVec3[3];
std::unique_ptr<ShortVec3[]> vertNormShort;
std::unique_ptr<atVec2f[]> vertUVs;
typedef atInt16 ShortVec2[2];
std::unique_ptr<ShortVec2[]> vertUVsShort;
bool visitedDLOffsets = false;
if (s < head.matSetCount)
{
MaterialSet matSet;
matSet.read(reader);
}
else
{
switch (s-head.matSetCount)
{
case 0:
{
/* Positions */
size_t vertCount = head.secSizes[s] / 12;
vertPos.reset(new atVec3f[vertCount]);
for (size_t i=0 ; i<vertCount ; ++i)
vertPos[i] = reader.readVec3f();
break;
}
case 1:
{
/* Normals */
if (head.flags.shortNormals())
{
size_t normCount = head.secSizes[s] / 6;
vertNormShort.reset(new ShortVec3[normCount]);
for (size_t i=0 ; i<normCount ; ++i)
{
vertNormShort[i][0] = reader.readInt16();
vertNormShort[i][1] = reader.readInt16();
vertNormShort[i][2] = reader.readInt16();
}
}
else
{
size_t normCount = head.secSizes[s] / 12;
vertNorm.reset(new atVec3f[normCount]);
for (size_t i=0 ; i<normCount ; ++i)
vertNorm[i] = reader.readVec3f();
}
break;
}
case 2:
{
/* Colors */
break;
}
case 3:
{
/* Float UVs */
size_t uvCount = head.secSizes[s] / 8;
vertUVs.reset(new atVec2f[uvCount]);
for (size_t i=0 ; i<uvCount ; ++i)
vertUVs[i] = reader.readVec2f();
break;
}
case 4:
{
/* Short UVs */
if (head.flags.shortUVs())
{
size_t uvCount = head.secSizes[s] / 4;
vertUVsShort.reset(new ShortVec2[uvCount]);
for (size_t i=0 ; i<uvCount ; ++i)
{
vertUVsShort[i][0] = reader.readInt16();
vertUVsShort[i][1] = reader.readInt16();
}
break;
}
/* DL Offsets (here or next section) */
visitedDLOffsets = true;
break;
}
default:
{
if (!visitedDLOffsets)
{
visitedDLOffsets = true;
break;
}
/* GX Display List (surface) */
SurfaceHeader sHead;
sHead.read(reader);
}
}
}
reader.seek(secStart + head.secSizes[s], Athena::Begin);
}
return true;
}
}
}

View File

@ -3,15 +3,59 @@
#include "../DNACommon/DNACommon.hpp"
#include "CMDLMaterials.hpp"
#include "BlenderConnection.hpp"
namespace Retro
{
namespace DNAMP1
{
struct CMDL : BigDNA
struct CMDL
{
DECL_DNA
struct Header : BigDNA
{
DECL_DNA
Value<atUint32> magic;
Value<atUint32> version;
struct Flags
{
DECL_DNA
Value<atUint32> flags;
inline bool shortNormals() const {return (flags & 0x2) != 0;}
inline void setShortNormals(bool val) {flags &= ~0x2; flags |= val << 1;}
inline bool shortUVs() const {return (flags & 0x4) != 0;}
inline void setShortUVs(bool val) {flags &= ~0x4; flags |= val << 2;}
} flags;
Value<atVec3f> aabbMin;
Value<atVec3f> aabbMax;
Value<atUint32> secCount;
Value<atUint32> matSetCount;
Vector<atUint32, DNA_COUNT(secCount)> secSizes;
};
struct SurfaceHeader : BigDNA
{
DECL_DNA
Value<atVec3f> centroid;
Value<atUint32> matIdx;
Value<atInt16> qDiv;
Value<atUint16> dlSize;
Seek<8, Athena::Current> seek;
Value<atUint32> aabbSz;
Value<atVec3f> reflectionNormal;
Seek<DNA_COUNT(aabbSz), Athena::Current> seek2;
Align<32> align;
};
static bool ReadToBlender(HECL::BlenderConnection& conn, Athena::io::IStreamReader& reader);
static bool Extract(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath)
{
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
if (!conn.createBlend(outPath.getAbsolutePath()))
return false;
return ReadToBlender(conn, rs);
}
};
}

View File

@ -7,4 +7,5 @@ add_library(DNAMP1
DNAMP1.hpp DNAMP1.cpp
${liblist}
PAK.cpp
STRG.hpp STRG.cpp)
STRG.hpp STRG.cpp
CMDL.cpp)

View File

@ -5,6 +5,7 @@
#include "STRG.hpp"
#include "MLVL.hpp"
#include "../DNACommon/TXTR.hpp"
#include "CMDL.hpp"
namespace Retro
{
@ -52,6 +53,8 @@ ResExtractor PAKBridge::LookupExtractor(const PAK::Entry& entry)
return {STRG::Extract, ".as"};
case SBIG('TXTR'):
return {TXTR::Extract, ".png"};
case SBIG('CMDL'):
return {CMDL::Extract, ".blend"};
}
return {};
}

2
NODLib

@ -1 +1 @@
Subproject commit 7fafe3ce0c14f9e244bb47572f5448e82b597a68
Subproject commit ebb5c0743da7fafbe4c3945d0117700c43845425

View File

@ -0,0 +1,2 @@
add_library(RetroCore
CRandom16.hpp CRandom16.cpp)

View File

@ -0,0 +1 @@
#include "CRandom16.hpp"

View File

@ -0,0 +1,81 @@
#ifndef RETRO_CRANDOM16_HPP
#define RETRO_CRANDOM16_HPP
#include <stdint.h>
#include "CRandom16.hpp"
namespace Retro
{
extern class CRandom16* GLOBAL_RANDOM;
extern class CGlobalRandom* GLOBAL_RANDOM_TOKEN;
class CRandom16
{
uint32_t m_seed;
public:
CRandom16(uint32_t p) : m_seed(p) {}
inline uint32_t Next()
{
m_seed = m_seed * 0x41c64e6d + 0x00003039;
return m_seed >> 16;
}
inline uint32_t GetSeed() const
{
return m_seed;
}
inline void SetSeed(time_t p)
{
m_seed = p;
}
inline float Float()
{
return Next() * 0.000015259022;
}
inline float Range(float min, float max)
{
return min + Float() * (max - min);
}
inline int32_t Range(int32_t min, int32_t max)
{
uint32_t diff = max - min;
uint32_t rand = 0xffffffff;
while (rand == 0xffffffff)
rand = (Next() << 16) | Next();
return rand % diff + min;
}
static CRandom16* GetRandomNumber() {return GLOBAL_RANDOM;}
static void SetRandomNumber(CRandom16* rnd) {GLOBAL_RANDOM = rnd;}
};
class CGlobalRandom
{
CRandom16& m_random;
CGlobalRandom* m_prev;
public:
CGlobalRandom(CRandom16& rand)
: m_random(rand), m_prev(GLOBAL_RANDOM_TOKEN)
{
GLOBAL_RANDOM_TOKEN = this;
CRandom16::SetRandomNumber(&m_random);
}
~CGlobalRandom()
{
GLOBAL_RANDOM_TOKEN = m_prev;
if (m_prev)
CRandom16::SetRandomNumber(&m_prev->m_random);
else
CRandom16::SetRandomNumber(nullptr);
}
};
}
#endif // RETRO_CRANDOM16_HPP