mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-11-23 05:12:05 +00:00
WIP:
- Converted BSP tree generation to use unique ptrs - Updated the linker to use BSP tree unique ptrs and use the new structure of custom map structs
This commit is contained in:
@@ -0,0 +1,147 @@
|
|||||||
|
#include "BinarySpacePartitionTree.h"
|
||||||
|
|
||||||
|
|
||||||
|
Object::Object(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int objPartitionIndex)
|
||||||
|
{
|
||||||
|
min.x = xMin;
|
||||||
|
min.y = yMin;
|
||||||
|
min.z = zMin;
|
||||||
|
max.x = xMax;
|
||||||
|
max.y = yMax;
|
||||||
|
max.z = zMax;
|
||||||
|
partitionIndex = objPartitionIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSPLeaf::addObject(std::shared_ptr<Object> object)
|
||||||
|
{
|
||||||
|
objectList.emplace_back(std::move(object));
|
||||||
|
}
|
||||||
|
|
||||||
|
Object* BSPLeaf::getObject(int index)
|
||||||
|
{
|
||||||
|
return objectList.at(index).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
int BSPLeaf::getObjectCount()
|
||||||
|
{
|
||||||
|
return objectList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
BSPNode::BSPNode(std::unique_ptr<BSPTree> frontTree, std::unique_ptr<BSPTree> backTree, PlaneAxis nodeAxis, float nodeDistance)
|
||||||
|
{
|
||||||
|
front = std::move(frontTree);
|
||||||
|
back = std::move(backTree);
|
||||||
|
axis = nodeAxis;
|
||||||
|
distance = nodeDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlaneSide BSPNode::objectIsInfront(Object* object)
|
||||||
|
{
|
||||||
|
float minCoord, maxCoord;
|
||||||
|
|
||||||
|
// Select the relevant coordinate based on the plane's axis
|
||||||
|
if (axis == AXIS_X)
|
||||||
|
{
|
||||||
|
minCoord = object->min.x;
|
||||||
|
maxCoord = object->max.x;
|
||||||
|
}
|
||||||
|
else if (axis == AXIS_Y)
|
||||||
|
{
|
||||||
|
minCoord = object->min.y;
|
||||||
|
maxCoord = object->max.y;
|
||||||
|
}
|
||||||
|
else // axis == AXIS_Z
|
||||||
|
{
|
||||||
|
minCoord = object->min.z;
|
||||||
|
maxCoord = object->max.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare with the plane's distance
|
||||||
|
if (maxCoord < distance)
|
||||||
|
{
|
||||||
|
return SIDE_BACK; // Object is entirely on the negative side
|
||||||
|
}
|
||||||
|
else if (minCoord > distance)
|
||||||
|
{
|
||||||
|
return SIDE_FRONT; // Object is entirely on the positive side
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return SIDE_INTERSECTS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BSPTree::BSPTree(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int treeLevel)
|
||||||
|
{
|
||||||
|
min.x = xMin;
|
||||||
|
min.y = yMin;
|
||||||
|
min.z = zMin;
|
||||||
|
max.x = xMax;
|
||||||
|
max.y = yMax;
|
||||||
|
max.z = zMax;
|
||||||
|
level = treeLevel;
|
||||||
|
splitTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
// For simplicity, only split across the X and Z axis.
|
||||||
|
// It is unlikely that there are many layers to a map, and is instead mostly flat
|
||||||
|
void BSPTree::splitTree()
|
||||||
|
{
|
||||||
|
std::unique_ptr<BSPTree> front;
|
||||||
|
std::unique_ptr<BSPTree> back;
|
||||||
|
float halfLength;
|
||||||
|
|
||||||
|
if (max.x - min.x > MAX_NODE_SIZE)
|
||||||
|
{
|
||||||
|
// split along the x axis
|
||||||
|
halfLength = (min.x + max.x) * 0.5f;
|
||||||
|
front = std::make_unique<BSPTree>(halfLength, min.y, min.z, max.x, max.y, max.z, level + 1);
|
||||||
|
back = std::make_unique<BSPTree>(min.x, min.y, min.z, halfLength, max.y, max.z, level + 1);
|
||||||
|
|
||||||
|
isLeaf = false;
|
||||||
|
node = std::make_unique<BSPNode>(std::move(front), std::move(back), AXIS_X, halfLength);
|
||||||
|
leaf = nullptr;
|
||||||
|
}
|
||||||
|
else if (max.z - min.z > MAX_NODE_SIZE)
|
||||||
|
{
|
||||||
|
// split along the z axis
|
||||||
|
halfLength = (min.z + max.z) * 0.5f;
|
||||||
|
front = std::make_unique<BSPTree>(min.x, min.y, halfLength, max.x, max.y, max.z, level + 1);
|
||||||
|
back = std::make_unique<BSPTree>(min.x, min.y, min.z, max.x, max.y, halfLength, level + 1);
|
||||||
|
|
||||||
|
isLeaf = false;
|
||||||
|
node = std::make_unique<BSPNode>(std::move(front), std::move(back), AXIS_Z, halfLength);
|
||||||
|
leaf = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isLeaf = true;
|
||||||
|
node = nullptr;
|
||||||
|
leaf = std::make_unique<BSPLeaf>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSPTree::addObjectToTree(std::shared_ptr<Object> object)
|
||||||
|
{
|
||||||
|
if (isLeaf)
|
||||||
|
{
|
||||||
|
leaf->addObject(std::move(object));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PlaneSide side = node->objectIsInfront(object.get());
|
||||||
|
if (side == SIDE_FRONT)
|
||||||
|
{
|
||||||
|
node->front->addObjectToTree(std::move(object));
|
||||||
|
}
|
||||||
|
else if (side == SIDE_BACK)
|
||||||
|
{
|
||||||
|
node->back->addObjectToTree(std::move(object));
|
||||||
|
}
|
||||||
|
else // intersects
|
||||||
|
{
|
||||||
|
node->front->addObjectToTree(object);
|
||||||
|
node->back->addObjectToTree(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
#include "Game/T6/T6.h"
|
||||||
using namespace T6;
|
using namespace T6;
|
||||||
@@ -15,194 +15,61 @@ enum PlaneAxis
|
|||||||
AXIS_Z
|
AXIS_Z
|
||||||
};
|
};
|
||||||
|
|
||||||
class Object
|
enum PlaneSide
|
||||||
{
|
|
||||||
public:
|
|
||||||
vec3_t min;
|
|
||||||
vec3_t max;
|
|
||||||
|
|
||||||
int partitionIndex; // index of the partition the object is contained in
|
|
||||||
|
|
||||||
Object(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int objPartitionIndex)
|
|
||||||
{
|
|
||||||
min.x = xMin;
|
|
||||||
min.y = yMin;
|
|
||||||
min.z = zMin;
|
|
||||||
max.x = xMax;
|
|
||||||
max.y = yMax;
|
|
||||||
max.z = zMax;
|
|
||||||
partitionIndex = objPartitionIndex;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
union u_BSPNode
|
|
||||||
{
|
|
||||||
BSPLeaf* leaf;
|
|
||||||
BSPNode* node;
|
|
||||||
};
|
|
||||||
class BSPTree;
|
|
||||||
|
|
||||||
class BSPLeaf
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::vector<std::unique_ptr<Object>> objectList;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void addObject(std::unique_ptr<Object> object)
|
|
||||||
{
|
|
||||||
objectList.push_back(std::move(object));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<Object> getObject(int index)
|
|
||||||
{
|
|
||||||
return std::move(objectList.at(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
int getObjectCount()
|
|
||||||
{
|
|
||||||
return objectList.size();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum objectPlaneSide
|
|
||||||
{
|
{
|
||||||
SIDE_FRONT,
|
SIDE_FRONT,
|
||||||
SIDE_BACK,
|
SIDE_BACK,
|
||||||
SIDE_INTERSECTS
|
SIDE_INTERSECTS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
vec3_t min;
|
||||||
|
vec3_t max;
|
||||||
|
int partitionIndex; // index of the partition the object is contained in
|
||||||
|
|
||||||
|
Object(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int objPartitionIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BSPLeaf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector<std::shared_ptr<Object>> objectList;
|
||||||
|
|
||||||
|
void addObject(std::shared_ptr<Object> object);
|
||||||
|
Object* getObject(int index);
|
||||||
|
int getObjectCount();
|
||||||
|
};
|
||||||
|
|
||||||
|
class BSPTree;
|
||||||
|
|
||||||
class BSPNode
|
class BSPNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BSPTree* front;
|
std::unique_ptr<BSPTree> front;
|
||||||
BSPTree* back;
|
std::unique_ptr<BSPTree> back;
|
||||||
|
|
||||||
PlaneAxis axis; // axis that the split plane is on
|
PlaneAxis axis; // axis that the split plane is on
|
||||||
double distance; // distance from the origin (0, 0, 0) to the plane
|
float distance; // distance from the origin (0, 0, 0) to the plane
|
||||||
|
|
||||||
BSPNode(BSPTree* _front, BSPTree* _back, PlaneAxis _axis, double _distance)
|
BSPNode(std::unique_ptr<BSPTree> frontTree, std::unique_ptr<BSPTree> backTree, PlaneAxis nodeAxis, float nodeDistance);
|
||||||
{
|
PlaneSide objectIsInfront(Object* object);
|
||||||
front = _front;
|
|
||||||
back = _back;
|
|
||||||
axis = _axis;
|
|
||||||
distance = _distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
objectPlaneSide objectIsInfront(Object* object)
|
|
||||||
{
|
|
||||||
float minCoord, maxCoord;
|
|
||||||
|
|
||||||
// Select the relevant coordinate based on the plane's axis
|
|
||||||
if (axis == AXIS_X)
|
|
||||||
{
|
|
||||||
minCoord = object->min.x;
|
|
||||||
maxCoord = object->max.x;
|
|
||||||
}
|
|
||||||
else if (axis == AXIS_Y)
|
|
||||||
{
|
|
||||||
minCoord = object->min.y;
|
|
||||||
maxCoord = object->max.y;
|
|
||||||
}
|
|
||||||
else // axis == AXIS_Z
|
|
||||||
{
|
|
||||||
minCoord = object->min.z;
|
|
||||||
maxCoord = object->max.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare with the plane's distance
|
|
||||||
if (maxCoord < distance)
|
|
||||||
{
|
|
||||||
return SIDE_BACK; // Object is entirely on the negative side
|
|
||||||
}
|
|
||||||
else if (minCoord > distance)
|
|
||||||
{
|
|
||||||
return SIDE_FRONT; // Object is entirely on the positive side
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return SIDE_INTERSECTS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class BSPTree
|
class BSPTree
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool isLeaf;
|
bool isLeaf;
|
||||||
u_BSPNode u;
|
std::unique_ptr<BSPLeaf> leaf;
|
||||||
|
std::unique_ptr<BSPNode> node;
|
||||||
|
|
||||||
int level; // level in the BSP tree
|
int level; // level in the BSP tree
|
||||||
double low[3]; // mins
|
vec3_t min;
|
||||||
double high[3]; // maxs
|
vec3_t max;
|
||||||
|
|
||||||
BSPTree(double min_x, double min_y, double min_z, double max_x, double max_y, double max_z, int _level)
|
BSPTree(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int treeLevel);
|
||||||
{
|
void splitTree();
|
||||||
low[0] = min_x;
|
void addObjectToTree(std::shared_ptr<Object> object);
|
||||||
low[1] = min_y, low[2] = min_z;
|
|
||||||
high[0] = max_x;
|
|
||||||
high[1] = max_y;
|
|
||||||
high[2] = max_z;
|
|
||||||
level = _level;
|
|
||||||
splitTree();
|
|
||||||
}
|
|
||||||
|
|
||||||
// For simplicity, only split across the X and Z axis.
|
|
||||||
// It is unlikely that there are many layers to a map, and is instead mostly flat
|
|
||||||
void splitTree()
|
|
||||||
{
|
|
||||||
BSPTree* front;
|
|
||||||
BSPTree* back;
|
|
||||||
double halfLength;
|
|
||||||
|
|
||||||
if (high[0] - low[0] > MAX_NODE_SIZE)
|
|
||||||
{
|
|
||||||
// split along the x axis
|
|
||||||
halfLength = (low[0] + high[0]) * 0.5f;
|
|
||||||
front = new BSPTree(halfLength, low[1], low[2], high[0], high[1], high[2], level + 1);
|
|
||||||
back = new BSPTree(low[0], low[1], low[2], halfLength, high[1], high[2], level + 1);
|
|
||||||
|
|
||||||
isLeaf = false;
|
|
||||||
u.node = new BSPNode(front, back, AXIS_X, halfLength);
|
|
||||||
}
|
|
||||||
else if (high[2] - low[2] > MAX_NODE_SIZE)
|
|
||||||
{
|
|
||||||
// split along the z axis
|
|
||||||
halfLength = (low[2] + high[2]) * 0.5f;
|
|
||||||
front = new BSPTree(low[0], low[1], halfLength, high[0], high[1], high[2], level + 1);
|
|
||||||
back = new BSPTree(low[0], low[1], low[2], high[0], high[1], halfLength, level + 1);
|
|
||||||
|
|
||||||
isLeaf = false;
|
|
||||||
u.node = new BSPNode(front, back, AXIS_Z, halfLength);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isLeaf = true;
|
|
||||||
u.leaf = new BSPLeaf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addObject(Object* object)
|
|
||||||
{
|
|
||||||
if (isLeaf)
|
|
||||||
{
|
|
||||||
u.leaf->addToList(object);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
objectPlaneSide side = u.node->objectIsInfront(object);
|
|
||||||
if (side == SIDE_FRONT)
|
|
||||||
{
|
|
||||||
u.node->front->addObject(object);
|
|
||||||
}
|
|
||||||
else if (side == SIDE_BACK)
|
|
||||||
{
|
|
||||||
u.node->back->addObject(object);
|
|
||||||
}
|
|
||||||
else // intersects
|
|
||||||
{
|
|
||||||
u.node->front->addObject(object);
|
|
||||||
u.node->back->addObject(object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "BinarySpacePartitionTreePreCalc.h"
|
#include "BinarySpacePartitionTree.h"
|
||||||
#include "CustomMapConsts.h"
|
#include "CustomMapConsts.h"
|
||||||
#include "CustomMapOptions.h"
|
#include "CustomMapOptions.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
@@ -23,7 +23,7 @@ public:
|
|||||||
hasLinkFailed = false;
|
hasLinkFailed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool linkCustomMap(customMapInfo* projInfo)
|
bool linkCustomMap(CustomMapBSP* projInfo)
|
||||||
{
|
{
|
||||||
_ASSERT(projInfo != NULL);
|
_ASSERT(projInfo != NULL);
|
||||||
|
|
||||||
@@ -72,27 +72,24 @@ private:
|
|||||||
// used for UVs of sub-textures, when it is set to empty all of them turn a blank colour
|
// used for UVs of sub-textures, when it is set to empty all of them turn a blank colour
|
||||||
// could fix by removing sub textures or figure out how they are created and redo that
|
// could fix by removing sub textures or figure out how they are created and redo that
|
||||||
// its not an important issue though
|
// its not an important issue though
|
||||||
bool overwriteDrawData(customMapInfo* projInfo, GfxWorld* gfxWorld)
|
bool overwriteDrawData(CustomMapBSP* projInfo, GfxWorld* gfxWorld)
|
||||||
{
|
{
|
||||||
int vertexCount = projInfo->gfxInfo.vertexCount;
|
int vertexCount = projInfo->gfxWorld.vertices.size();
|
||||||
customMapVertex* worldVertices = projInfo->gfxInfo.vertices;
|
|
||||||
|
|
||||||
gfxWorld->draw.vertexCount = vertexCount;
|
gfxWorld->draw.vertexCount = vertexCount;
|
||||||
gfxWorld->draw.vertexDataSize0 = vertexCount * sizeof(GfxPackedWorldVertex);
|
gfxWorld->draw.vertexDataSize0 = vertexCount * sizeof(GfxPackedWorldVertex);
|
||||||
GfxPackedWorldVertex* vertexBuffer = new GfxPackedWorldVertex[vertexCount];
|
GfxPackedWorldVertex* vertexBuffer = new GfxPackedWorldVertex[vertexCount];
|
||||||
for (int i = 0; i < vertexCount; i++)
|
for (int i = 0; i < vertexCount; i++)
|
||||||
{
|
{
|
||||||
customMapVertex* WorldVertex = &worldVertices[i];
|
CustomMapVertex* WorldVertex = &projInfo->gfxWorld.vertices[i];
|
||||||
GfxPackedWorldVertex* GfxVertex = &vertexBuffer[i];
|
GfxPackedWorldVertex* GfxVertex = &vertexBuffer[i];
|
||||||
|
|
||||||
GfxVertex->xyz = CMUtil::convertToBO2Coords(WorldVertex->pos);
|
GfxVertex->xyz = CMUtil::convertToBO2Coords(WorldVertex->pos);
|
||||||
//GfxVertex->xyz = WorldVertex->pos;
|
//GfxVertex->xyz = WorldVertex->pos;
|
||||||
|
|
||||||
GfxVertex->binormalSign = WorldVertex->binormalSign;
|
GfxVertex->color.packed = pack32::Vec4PackGfxColor(WorldVertex->color.v);
|
||||||
|
|
||||||
GfxVertex->color.packed = pack32::Vec4PackGfxColor(WorldVertex->color);
|
GfxVertex->texCoord.packed = pack32::Vec2PackTexCoordsUV(WorldVertex->texCoord.v);
|
||||||
|
|
||||||
GfxVertex->texCoord.packed = pack32::Vec2PackTexCoordsUV(WorldVertex->texCoord);
|
|
||||||
|
|
||||||
GfxVertex->normal.packed = pack32::Vec3PackUnitVecThirdBased(CMUtil::convertToBO2Coords(WorldVertex->normal).v);
|
GfxVertex->normal.packed = pack32::Vec3PackUnitVecThirdBased(CMUtil::convertToBO2Coords(WorldVertex->normal).v);
|
||||||
//GfxVertex->normal.packed = pack32::Vec3PackUnitVecThirdBased(WorldVertex->normal.v);
|
//GfxVertex->normal.packed = pack32::Vec3PackUnitVecThirdBased(WorldVertex->normal.v);
|
||||||
@@ -100,7 +97,11 @@ private:
|
|||||||
GfxVertex->tangent.packed = pack32::Vec3PackUnitVecThirdBased(CMUtil::convertToBO2Coords(WorldVertex->tangent).v);
|
GfxVertex->tangent.packed = pack32::Vec3PackUnitVecThirdBased(CMUtil::convertToBO2Coords(WorldVertex->tangent).v);
|
||||||
//GfxVertex->tangent.packed = pack32::Vec3PackUnitVecThirdBased(WorldVertex->tangent.v);
|
//GfxVertex->tangent.packed = pack32::Vec3PackUnitVecThirdBased(WorldVertex->tangent.v);
|
||||||
|
|
||||||
GfxVertex->lmapCoord.packed = WorldVertex->packedLmapCoord;
|
// unknown use variables
|
||||||
|
// binormalSign may be bitangent of the vertex
|
||||||
|
// lmapCoord may be the lightmap coordinate of the vertex
|
||||||
|
GfxVertex->binormalSign = 0.0f;
|
||||||
|
GfxVertex->lmapCoord.packed = 0;
|
||||||
}
|
}
|
||||||
gfxWorld->draw.vd0.data = (char*)vertexBuffer;
|
gfxWorld->draw.vd0.data = (char*)vertexBuffer;
|
||||||
|
|
||||||
@@ -110,16 +111,16 @@ private:
|
|||||||
gfxWorld->draw.vd1.data = new char[gfxWorld->draw.vertexDataSize1];
|
gfxWorld->draw.vd1.data = new char[gfxWorld->draw.vertexDataSize1];
|
||||||
memset(gfxWorld->draw.vd1.data, 0, gfxWorld->draw.vertexDataSize1);
|
memset(gfxWorld->draw.vd1.data, 0, gfxWorld->draw.vertexDataSize1);
|
||||||
|
|
||||||
int indexCount = projInfo->gfxInfo.indexCount;
|
int indexCount = projInfo->gfxWorld.indices.size();
|
||||||
_ASSERT(indexCount % 3 == 0);
|
_ASSERT(indexCount % 3 == 0);
|
||||||
gfxWorld->draw.indexCount = indexCount;
|
gfxWorld->draw.indexCount = indexCount;
|
||||||
gfxWorld->draw.indices = new uint16_t[indexCount];
|
gfxWorld->draw.indices = new uint16_t[indexCount];
|
||||||
for (int i = 0; i < indexCount; i += 3)
|
for (int i = 0; i < indexCount; i += 3)
|
||||||
{
|
{
|
||||||
// the editor orders their vertices opposite to bo2, so its converted here
|
// the editor orders their vertices opposite to bo2, so its converted here
|
||||||
gfxWorld->draw.indices[i + 2] = projInfo->gfxInfo.indices[i + 0];
|
gfxWorld->draw.indices[i + 2] = projInfo->gfxWorld.indices[i + 0];
|
||||||
gfxWorld->draw.indices[i + 1] = projInfo->gfxInfo.indices[i + 1];
|
gfxWorld->draw.indices[i + 1] = projInfo->gfxWorld.indices[i + 1];
|
||||||
gfxWorld->draw.indices[i + 0] = projInfo->gfxInfo.indices[i + 2];
|
gfxWorld->draw.indices[i + 0] = projInfo->gfxWorld.indices[i + 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -164,20 +165,20 @@ private:
|
|||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
void overwriteMapSurfaces(customMapInfo* projInfo, GfxWorld* gfxWorld)
|
void overwriteMapSurfaces(CustomMapBSP* projInfo, GfxWorld* gfxWorld)
|
||||||
{
|
{
|
||||||
bool overwriteResult = overwriteDrawData(projInfo, gfxWorld);
|
bool overwriteResult = overwriteDrawData(projInfo, gfxWorld);
|
||||||
if (!overwriteResult)
|
if (!overwriteResult)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned int surfaceCount = projInfo->gfxInfo.surfaceCount;
|
unsigned int surfaceCount = projInfo->gfxWorld.surfaces.size();
|
||||||
gfxWorld->surfaceCount = surfaceCount;
|
gfxWorld->surfaceCount = surfaceCount;
|
||||||
gfxWorld->dpvs.staticSurfaceCount = surfaceCount;
|
gfxWorld->dpvs.staticSurfaceCount = surfaceCount;
|
||||||
gfxWorld->dpvs.surfaces = new GfxSurface[surfaceCount];
|
gfxWorld->dpvs.surfaces = new GfxSurface[surfaceCount];
|
||||||
for (unsigned int i = 0; i < surfaceCount; i++)
|
for (unsigned int i = 0; i < surfaceCount; i++)
|
||||||
{
|
{
|
||||||
auto currSurface = &gfxWorld->dpvs.surfaces[i];
|
auto currSurface = &gfxWorld->dpvs.surfaces[i];
|
||||||
auto objSurface = &projInfo->gfxInfo.surfaces[i];
|
auto objSurface = &projInfo->gfxWorld.surfaces[i];
|
||||||
|
|
||||||
currSurface->primaryLightIndex = DEFAULT_SURFACE_LIGHT;
|
currSurface->primaryLightIndex = DEFAULT_SURFACE_LIGHT;
|
||||||
currSurface->lightmapIndex = DEFAULT_SURFACE_LIGHTMAP;
|
currSurface->lightmapIndex = DEFAULT_SURFACE_LIGHTMAP;
|
||||||
@@ -185,20 +186,20 @@ private:
|
|||||||
currSurface->flags = DEFAULT_SURFACE_FLAGS;
|
currSurface->flags = DEFAULT_SURFACE_FLAGS;
|
||||||
|
|
||||||
currSurface->tris.triCount = objSurface->triCount;
|
currSurface->tris.triCount = objSurface->triCount;
|
||||||
currSurface->tris.baseIndex = objSurface->firstIndex_Index;
|
currSurface->tris.baseIndex = objSurface->indexOfFirstIndex;
|
||||||
|
|
||||||
currSurface->tris.vertexDataOffset0 = objSurface->firstVertexIndex * sizeof(GfxPackedWorldVertex);
|
currSurface->tris.vertexDataOffset0 = objSurface->indexOfFirstVertex * sizeof(GfxPackedWorldVertex);
|
||||||
currSurface->tris.vertexDataOffset1 = 0;
|
currSurface->tris.vertexDataOffset1 = 0;
|
||||||
|
|
||||||
std::string surfMaterialName;
|
std::string surfMaterialName;
|
||||||
switch (objSurface->material.materialType)
|
switch (objSurface->material.materialType)
|
||||||
{
|
{
|
||||||
case CM_MATERIAL_TEXTURE:
|
case MATERIAL_TYPE_TEXTURE:
|
||||||
surfMaterialName = objSurface->material.materialName;
|
surfMaterialName = objSurface->material.materialName;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CM_MATERIAL_COLOUR:
|
case MATERIAL_TYPE_COLOUR:
|
||||||
case CM_MATERIAL_EMPTY:
|
case MATERIAL_TYPE_EMPTY:
|
||||||
surfMaterialName = colorOnlyImageName;
|
surfMaterialName = colorOnlyImageName;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -278,78 +279,92 @@ private:
|
|||||||
gfxWorld->dpvs.litTransSurfsEnd = surfaceCount;
|
gfxWorld->dpvs.litTransSurfsEnd = surfaceCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void overwriteMapSModels(customMapInfo* projInfo, GfxWorld* gfxWorld)
|
void overwriteMapSModels(CustomMapBSP* projInfo, GfxWorld* gfxWorld)
|
||||||
{
|
{
|
||||||
unsigned int modelCount = projInfo->modelCount;
|
/*
|
||||||
|
Models are unsupported right now
|
||||||
|
Code is left in in case it is supported later on
|
||||||
|
*/
|
||||||
|
//unsigned int modelCount = projInfo->modelCount;
|
||||||
|
//gfxWorld->dpvs.smodelCount = modelCount;
|
||||||
|
//gfxWorld->dpvs.smodelInsts = new GfxStaticModelInst[modelCount];
|
||||||
|
//gfxWorld->dpvs.smodelDrawInsts = new GfxStaticModelDrawInst[modelCount];
|
||||||
|
//
|
||||||
|
//for (unsigned int i = 0; i < modelCount; i++)
|
||||||
|
//{
|
||||||
|
// auto currModel = &gfxWorld->dpvs.smodelDrawInsts[i];
|
||||||
|
// auto currModelInst = &gfxWorld->dpvs.smodelInsts[i];
|
||||||
|
// customMapModel* inModel = &projInfo->models[i];
|
||||||
|
//
|
||||||
|
// auto xModelAsset = m_context.LoadDependency<AssetXModel>(inModel->name);
|
||||||
|
// if (xModelAsset == NULL)
|
||||||
|
// {
|
||||||
|
// printf("XModel %s not found!\n", inModel->name.c_str());
|
||||||
|
// currModel->model = NULL;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// currModel->model = (XModel*)xModelAsset->Asset();
|
||||||
|
//
|
||||||
|
// currModel->placement.origin.x = inModel->origin.x;
|
||||||
|
// currModel->placement.origin.y = inModel->origin.y;
|
||||||
|
// currModel->placement.origin.z = inModel->origin.z;
|
||||||
|
// currModel->placement.origin = CMUtil::convertToBO2Coords(currModel->placement.origin);
|
||||||
|
// currModel->placement.scale = inModel->scale;
|
||||||
|
//
|
||||||
|
// CMUtil::convertAnglesToAxis(&inModel->rotation, currModel->placement.axis);
|
||||||
|
//
|
||||||
|
// // mins and maxs are calculated in world space not local space
|
||||||
|
// // TODO: this does not account for model rotation or scale
|
||||||
|
// currModelInst->mins.x = currModel->model->mins.x + currModel->placement.origin.x;
|
||||||
|
// currModelInst->mins.y = currModel->model->mins.y + currModel->placement.origin.y;
|
||||||
|
// currModelInst->mins.z = currModel->model->mins.z + currModel->placement.origin.z;
|
||||||
|
// currModelInst->maxs.x = currModel->model->maxs.x + currModel->placement.origin.x;
|
||||||
|
// currModelInst->maxs.y = currModel->model->maxs.y + currModel->placement.origin.y;
|
||||||
|
// currModelInst->maxs.z = currModel->model->maxs.z + currModel->placement.origin.z;
|
||||||
|
//
|
||||||
|
// currModel->cullDist = DEFAULT_SMODEL_CULL_DIST;
|
||||||
|
// currModel->flags = DEFAULT_SMODEL_FLAGS;
|
||||||
|
// currModel->primaryLightIndex = DEFAULT_SMODEL_LIGHT;
|
||||||
|
// currModel->reflectionProbeIndex = DEFAULT_SMODEL_REFLECTION_PROBE;
|
||||||
|
//
|
||||||
|
// // unknown use / unused
|
||||||
|
// currModel->smid = i;
|
||||||
|
// memset(&currModel->lightingSH, 0, sizeof(GfxLightingSHQuantized));
|
||||||
|
// currModel->invScaleSq = 0.0f;
|
||||||
|
// currModel->lightingHandle = 0;
|
||||||
|
// currModel->colorsIndex = 0;
|
||||||
|
// currModel->visibility = 0;
|
||||||
|
//
|
||||||
|
// // setting these to NULL makes any static/baked lighting go black when not rendered by real-time lighting or in a shadow
|
||||||
|
// // TODO: calculate lighting and store it here
|
||||||
|
// currModel->lmapVertexInfo[0].numLmapVertexColors = 0;
|
||||||
|
// currModel->lmapVertexInfo[0].lmapVertexColors = NULL;
|
||||||
|
// currModel->lmapVertexInfo[1].numLmapVertexColors = 0;
|
||||||
|
// currModel->lmapVertexInfo[1].lmapVertexColors = NULL;
|
||||||
|
// currModel->lmapVertexInfo[2].numLmapVertexColors = 0;
|
||||||
|
// currModel->lmapVertexInfo[2].lmapVertexColors = NULL;
|
||||||
|
// currModel->lmapVertexInfo[3].numLmapVertexColors = 0;
|
||||||
|
// currModel->lmapVertexInfo[3].lmapVertexColors = NULL;
|
||||||
|
//}
|
||||||
|
|
||||||
|
unsigned int modelCount = 0;
|
||||||
gfxWorld->dpvs.smodelCount = modelCount;
|
gfxWorld->dpvs.smodelCount = modelCount;
|
||||||
gfxWorld->dpvs.smodelInsts = new GfxStaticModelInst[modelCount];
|
gfxWorld->dpvs.smodelInsts = new GfxStaticModelInst[modelCount];
|
||||||
gfxWorld->dpvs.smodelDrawInsts = new GfxStaticModelDrawInst[modelCount];
|
gfxWorld->dpvs.smodelDrawInsts = new GfxStaticModelDrawInst[modelCount];
|
||||||
|
|
||||||
for (unsigned int i = 0; i < modelCount; i++)
|
|
||||||
{
|
|
||||||
auto currModel = &gfxWorld->dpvs.smodelDrawInsts[i];
|
|
||||||
auto currModelInst = &gfxWorld->dpvs.smodelInsts[i];
|
|
||||||
customMapModel* inModel = &projInfo->models[i];
|
|
||||||
|
|
||||||
auto xModelAsset = m_context.LoadDependency<AssetXModel>(inModel->name);
|
|
||||||
if (xModelAsset == NULL)
|
|
||||||
{
|
|
||||||
printf("XModel %s not found!\n", inModel->name.c_str());
|
|
||||||
currModel->model = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
currModel->model = (XModel*)xModelAsset->Asset();
|
|
||||||
|
|
||||||
currModel->placement.origin.x = inModel->origin.x;
|
|
||||||
currModel->placement.origin.y = inModel->origin.y;
|
|
||||||
currModel->placement.origin.z = inModel->origin.z;
|
|
||||||
currModel->placement.origin = CMUtil::convertToBO2Coords(currModel->placement.origin);
|
|
||||||
currModel->placement.scale = inModel->scale;
|
|
||||||
|
|
||||||
CMUtil::convertAnglesToAxis(&inModel->rotation, currModel->placement.axis);
|
|
||||||
|
|
||||||
// mins and maxs are calculated in world space not local space
|
|
||||||
// TODO: this does not account for model rotation or scale
|
|
||||||
currModelInst->mins.x = currModel->model->mins.x + currModel->placement.origin.x;
|
|
||||||
currModelInst->mins.y = currModel->model->mins.y + currModel->placement.origin.y;
|
|
||||||
currModelInst->mins.z = currModel->model->mins.z + currModel->placement.origin.z;
|
|
||||||
currModelInst->maxs.x = currModel->model->maxs.x + currModel->placement.origin.x;
|
|
||||||
currModelInst->maxs.y = currModel->model->maxs.y + currModel->placement.origin.y;
|
|
||||||
currModelInst->maxs.z = currModel->model->maxs.z + currModel->placement.origin.z;
|
|
||||||
|
|
||||||
currModel->cullDist = DEFAULT_SMODEL_CULL_DIST;
|
|
||||||
currModel->flags = DEFAULT_SMODEL_FLAGS;
|
|
||||||
currModel->primaryLightIndex = DEFAULT_SMODEL_LIGHT;
|
|
||||||
currModel->reflectionProbeIndex = DEFAULT_SMODEL_REFLECTION_PROBE;
|
|
||||||
|
|
||||||
// unknown use / unused
|
|
||||||
currModel->smid = i;
|
|
||||||
memset(&currModel->lightingSH, 0, sizeof(GfxLightingSHQuantized));
|
|
||||||
currModel->invScaleSq = 0.0f;
|
|
||||||
currModel->lightingHandle = 0;
|
|
||||||
currModel->colorsIndex = 0;
|
|
||||||
currModel->visibility = 0;
|
|
||||||
|
|
||||||
// setting these to NULL makes any static/baked lighting go black when not rendered by real-time lighting or in a shadow
|
|
||||||
// TODO: calculate lighting and store it here
|
|
||||||
currModel->lmapVertexInfo[0].numLmapVertexColors = 0;
|
|
||||||
currModel->lmapVertexInfo[0].lmapVertexColors = NULL;
|
|
||||||
currModel->lmapVertexInfo[1].numLmapVertexColors = 0;
|
|
||||||
currModel->lmapVertexInfo[1].lmapVertexColors = NULL;
|
|
||||||
currModel->lmapVertexInfo[2].numLmapVertexColors = 0;
|
|
||||||
currModel->lmapVertexInfo[2].lmapVertexColors = NULL;
|
|
||||||
currModel->lmapVertexInfo[3].numLmapVertexColors = 0;
|
|
||||||
currModel->lmapVertexInfo[3].lmapVertexColors = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// all visdata is alligned by 128
|
// all visdata is alligned by 128
|
||||||
gfxWorld->dpvs.smodelVisDataCount = CMUtil::allignBy128(modelCount);
|
int allignedModelCount = CMUtil::allignBy128(modelCount);
|
||||||
gfxWorld->dpvs.smodelVisData[0] = new char[modelCount];
|
gfxWorld->dpvs.smodelVisDataCount = allignedModelCount;
|
||||||
gfxWorld->dpvs.smodelVisData[1] = new char[modelCount];
|
gfxWorld->dpvs.smodelVisData[0] = new char[allignedModelCount];
|
||||||
gfxWorld->dpvs.smodelVisData[2] = new char[modelCount];
|
gfxWorld->dpvs.smodelVisData[1] = new char[allignedModelCount];
|
||||||
gfxWorld->dpvs.smodelVisDataCameraSaved = new char[modelCount];
|
gfxWorld->dpvs.smodelVisData[2] = new char[allignedModelCount];
|
||||||
gfxWorld->dpvs.smodelCastsShadow = new char[modelCount];
|
gfxWorld->dpvs.smodelVisDataCameraSaved = new char[allignedModelCount];
|
||||||
|
gfxWorld->dpvs.smodelCastsShadow = new char[allignedModelCount];
|
||||||
|
memset(gfxWorld->dpvs.smodelVisData[0], 0, allignedModelCount);
|
||||||
|
memset(gfxWorld->dpvs.smodelVisData[1], 0, allignedModelCount);
|
||||||
|
memset(gfxWorld->dpvs.smodelVisData[2], 0, allignedModelCount);
|
||||||
|
memset(gfxWorld->dpvs.smodelVisDataCameraSaved, 0, allignedModelCount);
|
||||||
|
memset(gfxWorld->dpvs.smodelCastsShadow, 0, allignedModelCount);
|
||||||
for (unsigned int i = 0; i < modelCount; i++)
|
for (unsigned int i = 0; i < modelCount; i++)
|
||||||
{
|
{
|
||||||
if ((gfxWorld->dpvs.smodelDrawInsts[i].flags & SMODEL_FLAG_NO_SHADOW) == 0)
|
if ((gfxWorld->dpvs.smodelDrawInsts[i].flags & SMODEL_FLAG_NO_SHADOW) == 0)
|
||||||
@@ -357,16 +372,14 @@ private:
|
|||||||
else
|
else
|
||||||
gfxWorld->dpvs.smodelCastsShadow[i] = 0;
|
gfxWorld->dpvs.smodelCastsShadow[i] = 0;
|
||||||
}
|
}
|
||||||
memset(gfxWorld->dpvs.smodelVisData[0], 0, modelCount);
|
|
||||||
memset(gfxWorld->dpvs.smodelVisData[1], 0, modelCount);
|
|
||||||
memset(gfxWorld->dpvs.smodelVisData[2], 0, modelCount);
|
|
||||||
memset(gfxWorld->dpvs.smodelVisDataCameraSaved, 0, modelCount);
|
|
||||||
|
|
||||||
|
// always set to 0
|
||||||
gfxWorld->dpvs.usageCount = 0;
|
gfxWorld->dpvs.usageCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanGfxWorld(GfxWorld* gfxWorld)
|
void cleanGfxWorld(GfxWorld* gfxWorld)
|
||||||
{
|
{
|
||||||
|
// checksum is generated by the game
|
||||||
gfxWorld->checksum = 0;
|
gfxWorld->checksum = 0;
|
||||||
|
|
||||||
// Remove Coronas
|
// Remove Coronas
|
||||||
@@ -513,22 +526,16 @@ private:
|
|||||||
memset(gfxWorld->lightGrid.rowDataStart, 0, rowDataStartSize * sizeof(uint16_t));
|
memset(gfxWorld->lightGrid.rowDataStart, 0, rowDataStartSize * sizeof(uint16_t));
|
||||||
|
|
||||||
gfxWorld->lightGrid.rawRowDataSize = sizeof(GfxLightGridRow);
|
gfxWorld->lightGrid.rawRowDataSize = sizeof(GfxLightGridRow);
|
||||||
GfxLightGridRow* row = new GfxLightGridRow[1];
|
GfxLightGridRow* row = (GfxLightGridRow*)m_memory.AllocRaw(sizeof(GfxLightGridRow) + 0x10);
|
||||||
row->colStart = 0;
|
row->colStart = 0;
|
||||||
row->colCount = 0x1000; // 0x1000 as this is large enough for all checks done by the game
|
row->colCount = 0x1000; // 0x1000 as this is large enough for all checks done by the game
|
||||||
row->zStart = 0;
|
row->zStart = 0;
|
||||||
row->zCount = 0xFF; // 0xFF as this is large enough for all checks done by the game, but small enough not to mess with other checks
|
row->zCount = 0xFF; // 0xFF as this is large enough for all checks done by the game, but small enough not to mess with other checks
|
||||||
row->firstEntry = 0;
|
row->firstEntry = 0;
|
||||||
// this unknown part is weird, bo2 code uses up to unk5 and possibly onwards but the dumped rawRowData looks like it has a different structure.
|
for (int i = 0; i < 0x11; i++) // set the lookup table to all 0
|
||||||
// this seems to work though
|
{
|
||||||
row->unk.unknown1 = 0;
|
row->lookupTable[i] = 0;
|
||||||
row->unk.unknown2 = 0;
|
}
|
||||||
row->unk.unknown3 = 0;
|
|
||||||
row->unk.unknown4 = 0;
|
|
||||||
row->unk.unknown5 = 0;
|
|
||||||
row->unk.unknown6 = 0;
|
|
||||||
row->unk.unknown7 = 0;
|
|
||||||
row->unk.unknown8 = 0;
|
|
||||||
gfxWorld->lightGrid.rawRowData = (aligned_byte_pointer*)row;
|
gfxWorld->lightGrid.rawRowData = (aligned_byte_pointer*)row;
|
||||||
|
|
||||||
// entries are looked up based on the lightgrid sample pos and data within GfxLightGridRow
|
// entries are looked up based on the lightgrid sample pos and data within GfxLightGridRow
|
||||||
@@ -785,7 +792,7 @@ private:
|
|||||||
gfxWorld->draw.lightmaps[0].secondary = secondaryTextureAsset->Asset();
|
gfxWorld->draw.lightmaps[0].secondary = secondaryTextureAsset->Asset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void overwriteSkyBox(customMapInfo* projInfo, GfxWorld* gfxWorld)
|
void overwriteSkyBox(CustomMapBSP* projInfo, GfxWorld* gfxWorld)
|
||||||
{
|
{
|
||||||
std::string skyBoxName = "skybox_" + projInfo->name;
|
std::string skyBoxName = "skybox_" + projInfo->name;
|
||||||
gfxWorld->skyBoxModel = _strdup(skyBoxName.c_str());
|
gfxWorld->skyBoxModel = _strdup(skyBoxName.c_str());
|
||||||
@@ -871,7 +878,7 @@ private:
|
|||||||
gfxWorld->outdoorImage = outdoorImageAsset->Asset();
|
gfxWorld->outdoorImage = outdoorImageAsset->Asset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void createGfxWorld(customMapInfo* projInfo)
|
void createGfxWorld(CustomMapBSP* projInfo)
|
||||||
{
|
{
|
||||||
GfxWorld* gfxWorld = new GfxWorld;
|
GfxWorld* gfxWorld = new GfxWorld;
|
||||||
gfxWorld->baseName = _strdup(projInfo->name.c_str());
|
gfxWorld->baseName = _strdup(projInfo->name.c_str());
|
||||||
@@ -915,7 +922,7 @@ private:
|
|||||||
m_context.AddAsset<AssetGfxWorld>(gfxWorld->name, gfxWorld);
|
m_context.AddAsset<AssetGfxWorld>(gfxWorld->name, gfxWorld);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addXModelsToCollision(customMapInfo* projInfo, clipMap_t* clipMap)
|
void addXModelsToCollision(CustomMapBSP* projInfo, clipMap_t* clipMap)
|
||||||
{
|
{
|
||||||
auto gfxWorldAsset = m_context.LoadDependency<AssetGfxWorld>(projInfo->bspName);
|
auto gfxWorldAsset = m_context.LoadDependency<AssetGfxWorld>(projInfo->bspName);
|
||||||
_ASSERT(gfxWorldAsset != NULL);
|
_ASSERT(gfxWorldAsset != NULL);
|
||||||
@@ -992,20 +999,20 @@ private:
|
|||||||
{
|
{
|
||||||
(*numLeafs)++;
|
(*numLeafs)++;
|
||||||
// there won't be an AABB tree when objectList is empty
|
// there won't be an AABB tree when objectList is empty
|
||||||
if (node->u.leaf->getObjectCount() > 0)
|
if (node->leaf->getObjectCount() > 0)
|
||||||
{
|
{
|
||||||
*numAABBTrees += node->u.leaf->getObjectCount() + 1;
|
*numAABBTrees += node->leaf->getObjectCount() + 1;
|
||||||
|
|
||||||
if (node->u.leaf->getObjectCount() > *maxObjsPerLeaf)
|
if (node->leaf->getObjectCount() > *maxObjsPerLeaf)
|
||||||
*maxObjsPerLeaf = node->u.leaf->getObjectCount();
|
*maxObjsPerLeaf = node->leaf->getObjectCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
(*numPlanes)++;
|
(*numPlanes)++;
|
||||||
(*numNodes)++;
|
(*numNodes)++;
|
||||||
traverseBSPTreeForCounts(node->u.node->front, numPlanes, numNodes, numLeafs, numAABBTrees, maxObjsPerLeaf);
|
traverseBSPTreeForCounts(node->node->front.get(), numPlanes, numNodes, numLeafs, numAABBTrees, maxObjsPerLeaf);
|
||||||
traverseBSPTreeForCounts(node->u.node->back, numPlanes, numNodes, numLeafs, numAABBTrees, maxObjsPerLeaf);
|
traverseBSPTreeForCounts(node->node->back.get(), numPlanes, numNodes, numLeafs, numAABBTrees, maxObjsPerLeaf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1022,14 +1029,14 @@ private:
|
|||||||
{
|
{
|
||||||
_ASSERT(node->isLeaf);
|
_ASSERT(node->isLeaf);
|
||||||
|
|
||||||
int objectCount = node->u.leaf->getObjectCount();
|
int objectCount = node->leaf->getObjectCount();
|
||||||
int firstAABBIndex = currAABBCount;
|
int firstAABBIndex = currAABBCount;
|
||||||
currAABBCount += objectCount + 1;
|
currAABBCount += objectCount + 1;
|
||||||
|
|
||||||
// calculate root AABB node mins and maxs
|
// calculate root AABB node mins and maxs
|
||||||
// cannot convert mins and maxs coord to BO2 directly as this will result in incorrect mins and maxs
|
// cannot convert mins and maxs coord to BO2 directly as this will result in incorrect mins and maxs
|
||||||
// so we have to recompute every min and max, not hard just tedious
|
// so we have to recompute every min and max, not hard just tedious
|
||||||
int firstPartitionIndex = node->u.leaf->getObject(0)->partitionIndex;
|
int firstPartitionIndex = node->leaf->getObject(0)->partitionIndex;
|
||||||
auto firstPartition = &clipMap->partitions[firstPartitionIndex];
|
auto firstPartition = &clipMap->partitions[firstPartitionIndex];
|
||||||
uint16_t* firstTri = clipMap->triIndices[firstPartition->firstTri];
|
uint16_t* firstTri = clipMap->triIndices[firstPartition->firstTri];
|
||||||
vec3_t* firstVert = &clipMap->verts[firstTri[0]];
|
vec3_t* firstVert = &clipMap->verts[firstTri[0]];
|
||||||
@@ -1043,7 +1050,7 @@ private:
|
|||||||
aabbMaxs.z = firstVert->z;
|
aabbMaxs.z = firstVert->z;
|
||||||
for (int i = 0; i < objectCount; i++)
|
for (int i = 0; i < objectCount; i++)
|
||||||
{
|
{
|
||||||
int currPartitionIndex = node->u.leaf->getObject(i)->partitionIndex;
|
int currPartitionIndex = node->leaf->getObject(i)->partitionIndex;
|
||||||
auto currPartition = &clipMap->partitions[currPartitionIndex];
|
auto currPartition = &clipMap->partitions[currPartitionIndex];
|
||||||
|
|
||||||
for (int k = 0; k < currPartition->triCount; k++)
|
for (int k = 0; k < currPartition->triCount; k++)
|
||||||
@@ -1067,7 +1074,7 @@ private:
|
|||||||
for (int i = 0; i < objectCount; i++)
|
for (int i = 0; i < objectCount; i++)
|
||||||
{
|
{
|
||||||
CollisionAabbTree* currAabbTree = &clipMap->aabbTrees[rootAABB->u.firstChildIndex + i];
|
CollisionAabbTree* currAabbTree = &clipMap->aabbTrees[rootAABB->u.firstChildIndex + i];
|
||||||
int currPartitionIndex = node->u.leaf->getObject(i)->partitionIndex;
|
int currPartitionIndex = node->leaf->getObject(i)->partitionIndex;
|
||||||
|
|
||||||
currAabbTree->materialIndex = 0;
|
currAabbTree->materialIndex = 0;
|
||||||
currAabbTree->childCount = 0;
|
currAabbTree->childCount = 0;
|
||||||
@@ -1126,7 +1133,7 @@ private:
|
|||||||
currLeaf->maxs.z = 0.0f;
|
currLeaf->maxs.z = 0.0f;
|
||||||
currLeaf->leafBrushNode = 0;
|
currLeaf->leafBrushNode = 0;
|
||||||
|
|
||||||
if (node->u.leaf->getObjectCount() > 0)
|
if (node->leaf->getObjectCount() > 0)
|
||||||
{
|
{
|
||||||
currLeaf->firstCollAabbIndex = addAABBTreeFromLeaf(node, clipMap);
|
currLeaf->firstCollAabbIndex = addAABBTreeFromLeaf(node, clipMap);
|
||||||
currLeaf->collAabbCount = 1;
|
currLeaf->collAabbCount = 1;
|
||||||
@@ -1144,14 +1151,14 @@ private:
|
|||||||
cplane_s* currPlane = &clipMap->info.planes[currPlaneCount];
|
cplane_s* currPlane = &clipMap->info.planes[currPlaneCount];
|
||||||
currPlaneCount++;
|
currPlaneCount++;
|
||||||
|
|
||||||
if (node->u.node->axis == AXIS_X)
|
if (node->node->axis == AXIS_X)
|
||||||
{
|
{
|
||||||
// X is unchanged when going from OGL x -> BO2 x
|
// X is unchanged when going from OGL x -> BO2 x
|
||||||
currPlane->normal = normalX;
|
currPlane->normal = normalX;
|
||||||
|
|
||||||
// converting OGL -> BO2 X coords doesn't change the x coords at all, so
|
// converting OGL -> BO2 X coords doesn't change the x coords at all, so
|
||||||
// the dist stays the same
|
// the dist stays the same
|
||||||
currPlane->dist = (float)node->u.node->distance;
|
currPlane->dist = (float)node->node->distance;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1163,7 +1170,7 @@ private:
|
|||||||
|
|
||||||
// converting OGL -> BO2 Z coords negates the z coords and sets it to the y coord.
|
// converting OGL -> BO2 Z coords negates the z coords and sets it to the y coord.
|
||||||
// just negate it here as it is just the distance from the orgin along the axis
|
// just negate it here as it is just the distance from the orgin along the axis
|
||||||
currPlane->dist = (float)(-node->u.node->distance);
|
currPlane->dist = (float)(-node->node->distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool foundType = false;
|
bool foundType = false;
|
||||||
@@ -1211,13 +1218,13 @@ private:
|
|||||||
// Do the OGL -> Bo2 coord change on paper and it will make sense
|
// Do the OGL -> Bo2 coord change on paper and it will make sense
|
||||||
if (currPlane->type == 1)
|
if (currPlane->type == 1)
|
||||||
{
|
{
|
||||||
currNode->children[1] = populateBSPTree_r(clipMap, node->u.node->front);
|
currNode->children[1] = populateBSPTree_r(clipMap, node->node->front.get());
|
||||||
currNode->children[0] = populateBSPTree_r(clipMap, node->u.node->back);
|
currNode->children[0] = populateBSPTree_r(clipMap, node->node->back.get());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
currNode->children[0] = populateBSPTree_r(clipMap, node->u.node->front);
|
currNode->children[0] = populateBSPTree_r(clipMap, node->node->front.get());
|
||||||
currNode->children[1] = populateBSPTree_r(clipMap, node->u.node->back);
|
currNode->children[1] = populateBSPTree_r(clipMap, node->node->back.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
return currNodeIndex;
|
return currNodeIndex;
|
||||||
@@ -1263,14 +1270,14 @@ private:
|
|||||||
_ASSERT(clipMap->aabbTreeCount == currAABBCount);
|
_ASSERT(clipMap->aabbTreeCount == currAABBCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createPartitions(customMapInfo* projInfo, clipMap_t* clipMap)
|
void createPartitions(CustomMapBSP* projInfo, clipMap_t* clipMap)
|
||||||
{
|
{
|
||||||
int collisionVertexCount = projInfo->colInfo.vertexCount;
|
int collisionVertexCount = projInfo->colWorld.vertices.size();
|
||||||
std::vector<vec3_t> collisionVertVec;
|
std::vector<vec3_t> collisionVertVec;
|
||||||
for (int i = 0; i < collisionVertexCount; i++)
|
for (int i = 0; i < collisionVertexCount; i++)
|
||||||
{
|
{
|
||||||
collisionVertVec.push_back(CMUtil::convertToBO2Coords(projInfo->colInfo.vertices[i].pos));
|
collisionVertVec.push_back(CMUtil::convertToBO2Coords(projInfo->colWorld.vertices[i].pos));
|
||||||
//collisionVertVec.push_back(projInfo->colInfo.vertices[i].pos);
|
//collisionVertVec.push_back(projInfo->colWorld.vertices[i].pos);
|
||||||
}
|
}
|
||||||
clipMap->vertCount = collisionVertexCount;
|
clipMap->vertCount = collisionVertexCount;
|
||||||
clipMap->verts = new vec3_t[collisionVertexCount];
|
clipMap->verts = new vec3_t[collisionVertexCount];
|
||||||
@@ -1286,21 +1293,21 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint16_t> triIndexVec;
|
std::vector<uint16_t> triIndexVec;
|
||||||
for (int i = 0; i < projInfo->colInfo.surfaceCount; i++)
|
for (size_t i = 0; i < projInfo->colWorld.surfaces.size(); i++)
|
||||||
{
|
{
|
||||||
worldSurface* currSurface = &projInfo->colInfo.surfaces[i];
|
CustomMapSurface* currSurface = &projInfo->colWorld.surfaces[i];
|
||||||
int triCount = currSurface->triCount;
|
int triCount = currSurface->triCount;
|
||||||
|
|
||||||
for (int k = 0; k < triCount * 3; k += 3)
|
for (int k = 0; k < triCount * 3; k += 3)
|
||||||
{
|
{
|
||||||
int firstIndex_Index = currSurface->firstIndex_Index;
|
int firstIndex_Index = currSurface->indexOfFirstIndex;
|
||||||
int firstVertexIndex = currSurface->firstVertexIndex;
|
int firstVertexIndex = currSurface->indexOfFirstVertex;
|
||||||
|
|
||||||
// gfx index bufer starts at 0 for each new mesh, while the clipmap index buffer indexes the entire
|
// gfx index bufer starts at 0 for each new mesh, while the clipmap index buffer indexes the entire
|
||||||
// clipmap verts buffer, so this code updates the indexes to follow that.
|
// clipmap verts buffer, so this code updates the indexes to follow that.
|
||||||
int triIndex0 = projInfo->colInfo.indices[firstIndex_Index + (k + 0)] + firstVertexIndex;
|
int triIndex0 = projInfo->colWorld.indices[firstIndex_Index + (k + 0)] + firstVertexIndex;
|
||||||
int triIndex1 = projInfo->colInfo.indices[firstIndex_Index + (k + 1)] + firstVertexIndex;
|
int triIndex1 = projInfo->colWorld.indices[firstIndex_Index + (k + 1)] + firstVertexIndex;
|
||||||
int triIndex2 = projInfo->colInfo.indices[firstIndex_Index + (k + 2)] + firstVertexIndex;
|
int triIndex2 = projInfo->colWorld.indices[firstIndex_Index + (k + 2)] + firstVertexIndex;
|
||||||
|
|
||||||
// triangle index ordering is opposite to blenders, so its converted here
|
// triangle index ordering is opposite to blenders, so its converted here
|
||||||
triIndexVec.push_back(triIndex2);
|
triIndexVec.push_back(triIndex2);
|
||||||
@@ -1317,10 +1324,10 @@ private:
|
|||||||
// one for each surface causes physics bugs, as the entire bounding box is considered solid instead of the surface itself (for some reason).
|
// one for each surface causes physics bugs, as the entire bounding box is considered solid instead of the surface itself (for some reason).
|
||||||
// so a partition is made for each triangle which removes the physics bugs but likely makes the game run slower
|
// so a partition is made for each triangle which removes the physics bugs but likely makes the game run slower
|
||||||
std::vector<CollisionPartition> partitionVec;
|
std::vector<CollisionPartition> partitionVec;
|
||||||
for (int i = 0; i < projInfo->colInfo.surfaceCount; i++)
|
for (size_t i = 0; i < projInfo->colWorld.surfaces.size(); i++)
|
||||||
{
|
{
|
||||||
int triCount = projInfo->colInfo.surfaces[i].triCount;
|
int triCount = projInfo->colWorld.surfaces[i].triCount;
|
||||||
int firstTriIndex = projInfo->colInfo.surfaces[i].firstIndex_Index / 3;
|
int firstTriIndex = projInfo->colWorld.surfaces[i].indexOfFirstIndex / 3;
|
||||||
for (int k = 0; k < triCount; k++)
|
for (int k = 0; k < triCount; k++)
|
||||||
{
|
{
|
||||||
CollisionPartition newPartition;
|
CollisionPartition newPartition;
|
||||||
@@ -1375,7 +1382,7 @@ private:
|
|||||||
memcpy(clipMap->info.uinds, &uindVec[0], sizeof(uint16_t) * totalUindCount);
|
memcpy(clipMap->info.uinds, &uindVec[0], sizeof(uint16_t) * totalUindCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createClipMap(customMapInfo* projInfo)
|
void createClipMap(CustomMapBSP* projInfo)
|
||||||
{
|
{
|
||||||
clipMap_t* clipMap = new clipMap_t;
|
clipMap_t* clipMap = new clipMap_t;
|
||||||
|
|
||||||
@@ -1605,9 +1612,9 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Object* currObject = new Object(mins.x, mins.y, mins.z, maxs.x, maxs.y, maxs.z, i);
|
std::shared_ptr<Object> currObject = std::make_shared<Object>(mins.x, mins.y, mins.z, maxs.x, maxs.y, maxs.z, i);
|
||||||
|
|
||||||
tree->addObject(currObject);
|
tree->addObjectToTree(std::move(currObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
populateBSPTree(clipMap, tree);
|
populateBSPTree(clipMap, tree);
|
||||||
@@ -1615,7 +1622,7 @@ private:
|
|||||||
m_context.AddAsset<AssetClipMapPvs>(clipMap->name, clipMap);
|
m_context.AddAsset<AssetClipMapPvs>(clipMap->name, clipMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createComWorld(customMapInfo* projInfo)
|
void createComWorld(CustomMapBSP* projInfo)
|
||||||
{
|
{
|
||||||
// all lights that aren't the sunlight or default light need their own GfxLightDef asset
|
// all lights that aren't the sunlight or default light need their own GfxLightDef asset
|
||||||
ComWorld* comWorld = new ComWorld;
|
ComWorld* comWorld = new ComWorld;
|
||||||
@@ -1800,7 +1807,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void createMapEnts(customMapInfo* projInfo)
|
void createMapEnts(CustomMapBSP* projInfo)
|
||||||
{
|
{
|
||||||
MapEnts* mapEnts = new MapEnts;
|
MapEnts* mapEnts = new MapEnts;
|
||||||
|
|
||||||
@@ -1862,7 +1869,7 @@ private:
|
|||||||
m_context.AddAsset<AssetMapEnts>(mapEnts->name, mapEnts);
|
m_context.AddAsset<AssetMapEnts>(mapEnts->name, mapEnts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createGameWorldMp(customMapInfo* projInfo)
|
void createGameWorldMp(CustomMapBSP* projInfo)
|
||||||
{
|
{
|
||||||
GameWorldMp* gameWorldMp = new GameWorldMp;
|
GameWorldMp* gameWorldMp = new GameWorldMp;
|
||||||
|
|
||||||
@@ -1887,11 +1894,13 @@ private:
|
|||||||
m_context.AddAsset<AssetGameWorldMp>(gameWorldMp->name, gameWorldMp);
|
m_context.AddAsset<AssetGameWorldMp>(gameWorldMp->name, gameWorldMp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createSkinnedVerts(customMapInfo* projInfo)
|
void createSkinnedVerts(CustomMapBSP* projInfo)
|
||||||
{
|
{
|
||||||
SkinnedVertsDef* skinnedVerts = new SkinnedVertsDef;
|
SkinnedVertsDef* skinnedVerts = new SkinnedVertsDef;
|
||||||
skinnedVerts->name = "skinnedverts";
|
skinnedVerts->name = "skinnedverts";
|
||||||
skinnedVerts->maxSkinnedVerts = projInfo->gfxInfo.vertexCount;
|
skinnedVerts->maxSkinnedVerts = projInfo->gfxWorld.vertices.size();
|
||||||
|
// I'm pretty sure maxSkinnedVerts relates to the max amount of xmodel skinned verts a map will have
|
||||||
|
// But setting it to the world vertex count seems to work
|
||||||
|
|
||||||
m_context.AddAsset<AssetSkinnedVerts>("skinnedverts", skinnedVerts);
|
m_context.AddAsset<AssetSkinnedVerts>("skinnedverts", skinnedVerts);
|
||||||
}
|
}
|
||||||
@@ -1910,7 +1919,7 @@ private:
|
|||||||
return footstepTable;
|
return footstepTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkAndAddDefaultRequiredAssets(customMapInfo* projectInfo)
|
void checkAndAddDefaultRequiredAssets(CustomMapBSP* projectInfo)
|
||||||
{
|
{
|
||||||
auto templateFile = m_search_path.Open("materials/material_template.json");
|
auto templateFile = m_search_path.Open("materials/material_template.json");
|
||||||
if (!templateFile.IsOpen())
|
if (!templateFile.IsOpen())
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
#include "Game/T6/T6.h"
|
||||||
using namespace T6;
|
using namespace T6;
|
||||||
|
|||||||
Reference in New Issue
Block a user