mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-12 02:58:32 +00:00
Correct scene making, merged the old raw into the new.
added option to automatically write the raw obj file Added scene colors to the obj use proper scene colors from hf
This commit is contained in:
34
dCommon/NiColor.h
Normal file
34
dCommon/NiColor.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef NICOLOR_H
|
||||
#define NICOLOR_H
|
||||
|
||||
struct NiColor {
|
||||
float m_Red;
|
||||
float m_Green;
|
||||
float m_Blue;
|
||||
|
||||
NiColor(float red, float green, float blue) : m_Red(red), m_Green(green), m_Blue(blue) {}
|
||||
NiColor() : NiColor(0.0f, 0.0f, 0.0f) {}
|
||||
|
||||
/* reduce RGB files to grayscale, with or without alpha
|
||||
* using the equation given in Poynton's ColorFAQ at
|
||||
* <http://www.inforamp.net/~poynton/> // dead link
|
||||
* Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net
|
||||
*
|
||||
* Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
|
||||
*
|
||||
* We approximate this with
|
||||
*
|
||||
* Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
|
||||
*
|
||||
* which can be expressed with integers as
|
||||
*
|
||||
* Y = (6969 * R + 23434 * G + 2365 * B)/32768
|
||||
*
|
||||
* The calculation is to be done in a linear colorspace.
|
||||
*
|
||||
* Other integer coefficents can be used via png_set_rgb_to_gray().
|
||||
*/
|
||||
float ToXYZ() const { return (m_Red * 0.212671f) + (m_Green * 0.71516f) + (m_Blue * 0.072169f); };
|
||||
};
|
||||
|
||||
#endif // NICOLOR_H
|
||||
170
dCommon/dClient/SceneColor.h
Normal file
170
dCommon/dClient/SceneColor.h
Normal file
@@ -0,0 +1,170 @@
|
||||
#ifndef SCENE_COLOR_H
|
||||
#define SCENE_COLOR_H
|
||||
|
||||
#include "NiColor.h"
|
||||
#include <vector>
|
||||
|
||||
class SceneColor {
|
||||
public:
|
||||
SceneColor() {
|
||||
TEMPLATE_COLORS.resize(146);
|
||||
|
||||
// these are not random values, they are the actual template colors used by the game
|
||||
TEMPLATE_COLORS[0] = NiColor(0.5019608f, 0.5019608f, 0.5019608f);
|
||||
TEMPLATE_COLORS[1] = NiColor(1.0f, 0.0f, 0.0f);
|
||||
TEMPLATE_COLORS[2] = NiColor(0.0f, 1.0f, 0.0f);
|
||||
TEMPLATE_COLORS[3] = NiColor(0.0f, 0.0f, 1.0f);
|
||||
TEMPLATE_COLORS[4] = NiColor(1.0f, 1.0f, 0.0f);
|
||||
TEMPLATE_COLORS[5] = NiColor(1.0f, 0.0f, 1.0f);
|
||||
TEMPLATE_COLORS[6] = NiColor(0.0f, 1.0f, 1.0f);
|
||||
TEMPLATE_COLORS[7] = NiColor(0.5019608f, 0.0f, 1.0f);
|
||||
TEMPLATE_COLORS[8] = NiColor(1.0f, 0.5019608f, 0.0f);
|
||||
TEMPLATE_COLORS[9] = NiColor(1.0f, 0.5019608f, 0.5019608f);
|
||||
TEMPLATE_COLORS[10] = NiColor(0.5019608f, 0.2509804f, 0.0f);
|
||||
TEMPLATE_COLORS[11] = NiColor(0.5019608f, 0.0f, 0.2509804f);
|
||||
TEMPLATE_COLORS[12] = NiColor(0.0f, 0.5019608f, 0.2509804f);
|
||||
TEMPLATE_COLORS[13] = NiColor(0.2509804f, 0.0f, 0.5019608f);
|
||||
TEMPLATE_COLORS[14] = NiColor(0.8745098f, 0.0f, 0.2509804f);
|
||||
TEMPLATE_COLORS[15] = NiColor(0.2509804f, 0.8745098f, 0.5019608f);
|
||||
TEMPLATE_COLORS[16] = NiColor(1.0f, 0.7490196f, 0.0f);
|
||||
TEMPLATE_COLORS[17] = NiColor(1.0f, 0.2509804f, 0.0627451f);
|
||||
TEMPLATE_COLORS[18] = NiColor(0.2509804f, 0.0f, 0.8745098f);
|
||||
TEMPLATE_COLORS[19] = NiColor(0.7490196f, 0.0627451f, 0.0627451f);
|
||||
TEMPLATE_COLORS[20] = NiColor(0.0627451f, 0.7490196f, 0.0627451f);
|
||||
TEMPLATE_COLORS[21] = NiColor(1.0f, 0.5019608f, 1.0f);
|
||||
TEMPLATE_COLORS[22] = NiColor(0.9372549f, 0.8705882f, 0.8039216f);
|
||||
TEMPLATE_COLORS[23] = NiColor(0.8039216f, 0.5843138f, 0.4588235f);
|
||||
TEMPLATE_COLORS[24] = NiColor(0.9921569f, 0.8509804f, 0.7098039f);
|
||||
TEMPLATE_COLORS[25] = NiColor(0.4705882f, 0.8588235f, 0.8862745f);
|
||||
TEMPLATE_COLORS[26] = NiColor(0.5294118f, 0.6627451f, 0.4196078f);
|
||||
TEMPLATE_COLORS[27] = NiColor(1.0f, 0.6431373f, 0.454902f);
|
||||
TEMPLATE_COLORS[28] = NiColor(0.9803922f, 0.9058824f, 0.7098039f);
|
||||
TEMPLATE_COLORS[29] = NiColor(0.6235294f, 0.5058824f, 0.4392157f);
|
||||
TEMPLATE_COLORS[30] = NiColor(0.9921569f, 0.4862745f, 0.4313726f);
|
||||
TEMPLATE_COLORS[31] = NiColor(0.0f, 0.0f, 0.0f);
|
||||
TEMPLATE_COLORS[32] = NiColor(0.6745098f, 0.8980392f, 0.9333333f);
|
||||
TEMPLATE_COLORS[33] = NiColor(0.1215686f, 0.4588235f, 0.9960784f);
|
||||
TEMPLATE_COLORS[34] = NiColor(0.6352941f, 0.6352941f, 0.8156863f);
|
||||
TEMPLATE_COLORS[35] = NiColor(0.4f, 0.6f, 0.8f);
|
||||
TEMPLATE_COLORS[36] = NiColor(0.05098039f, 0.5960785f, 0.7294118f);
|
||||
TEMPLATE_COLORS[37] = NiColor(0.4509804f, 0.4f, 0.7411765f);
|
||||
TEMPLATE_COLORS[38] = NiColor(0.8705882f, 0.3647059f, 0.5137255f);
|
||||
TEMPLATE_COLORS[39] = NiColor(0.7960784f, 0.254902f, 0.3294118f);
|
||||
TEMPLATE_COLORS[40] = NiColor(0.7058824f, 0.4039216f, 0.3019608f);
|
||||
TEMPLATE_COLORS[41] = NiColor(1.0f, 0.4980392f, 0.2862745f);
|
||||
TEMPLATE_COLORS[42] = NiColor(0.9176471f, 0.4941176f, 0.3647059f);
|
||||
TEMPLATE_COLORS[43] = NiColor(0.6901961f, 0.7176471f, 0.7764706f);
|
||||
TEMPLATE_COLORS[44] = NiColor(1.0f, 1.0f, 0.6f);
|
||||
TEMPLATE_COLORS[45] = NiColor(0.1098039f, 0.827451f, 0.6352941f);
|
||||
TEMPLATE_COLORS[46] = NiColor(1.0f, 0.6666667f, 0.8f);
|
||||
TEMPLATE_COLORS[47] = NiColor(0.8666667f, 0.2666667f, 0.572549f);
|
||||
TEMPLATE_COLORS[48] = NiColor(0.1137255f, 0.6745098f, 0.8392157f);
|
||||
TEMPLATE_COLORS[49] = NiColor(0.7372549f, 0.3647059f, 0.345098f);
|
||||
TEMPLATE_COLORS[50] = NiColor(0.8666667f, 0.5803922f, 0.4588235f);
|
||||
TEMPLATE_COLORS[51] = NiColor(0.6039216f, 0.8078431f, 0.9215686f);
|
||||
TEMPLATE_COLORS[52] = NiColor(1.0f, 0.7372549f, 0.8509804f);
|
||||
TEMPLATE_COLORS[53] = NiColor(0.9921569f, 0.8588235f, 0.427451f);
|
||||
TEMPLATE_COLORS[54] = NiColor(0.1686275f, 0.4235294f, 0.7686275f);
|
||||
TEMPLATE_COLORS[55] = NiColor(0.9372549f, 0.8039216f, 0.7215686f);
|
||||
TEMPLATE_COLORS[56] = NiColor(0.4313726f, 0.3176471f, 0.3764706f);
|
||||
TEMPLATE_COLORS[57] = NiColor(0.8078431f, 1.0f, 0.1137255f);
|
||||
TEMPLATE_COLORS[58] = NiColor(0.427451f, 0.682353f, 0.5058824f);
|
||||
TEMPLATE_COLORS[59] = NiColor(0.7647059f, 0.3921569f, 0.772549f);
|
||||
TEMPLATE_COLORS[60] = NiColor(0.8f, 0.4f, 0.4f);
|
||||
TEMPLATE_COLORS[61] = NiColor(0.9058824f, 0.7764706f, 0.5921569f);
|
||||
TEMPLATE_COLORS[62] = NiColor(0.9882353f, 0.8509804f, 0.4588235f);
|
||||
TEMPLATE_COLORS[63] = NiColor(0.6588235f, 0.8941177f, 0.627451f);
|
||||
TEMPLATE_COLORS[64] = NiColor(0.5843138f, 0.5686275f, 0.5490196f);
|
||||
TEMPLATE_COLORS[65] = NiColor(0.1098039f, 0.6745098f, 0.4705882f);
|
||||
TEMPLATE_COLORS[66] = NiColor(0.06666667f, 0.3921569f, 0.7058824f);
|
||||
TEMPLATE_COLORS[67] = NiColor(0.9411765f, 0.9098039f, 0.5686275f);
|
||||
TEMPLATE_COLORS[68] = NiColor(1.0f, 0.1137255f, 0.8078431f);
|
||||
TEMPLATE_COLORS[69] = NiColor(0.6980392f, 0.9254902f, 0.3647059f);
|
||||
TEMPLATE_COLORS[70] = NiColor(0.3647059f, 0.4627451f, 0.7960784f);
|
||||
TEMPLATE_COLORS[71] = NiColor(0.7921569f, 0.2156863f, 0.4039216f);
|
||||
TEMPLATE_COLORS[72] = NiColor(0.2313726f, 0.6901961f, 0.5607843f);
|
||||
TEMPLATE_COLORS[73] = NiColor(0.9882353f, 0.7058824f, 0.8352941f);
|
||||
TEMPLATE_COLORS[74] = NiColor(1.0f, 0.9568627f, 0.3098039f);
|
||||
TEMPLATE_COLORS[75] = NiColor(1.0f, 0.7411765f, 0.5333334f);
|
||||
TEMPLATE_COLORS[76] = NiColor(0.9647059f, 0.3921569f, 0.6862745f);
|
||||
TEMPLATE_COLORS[77] = NiColor(0.6666667f, 0.9411765f, 0.8196079f);
|
||||
TEMPLATE_COLORS[78] = NiColor(0.8039216f, 0.2901961f, 0.2980392f);
|
||||
TEMPLATE_COLORS[79] = NiColor(0.9294118f, 0.8196079f, 0.6117647f);
|
||||
TEMPLATE_COLORS[80] = NiColor(0.5921569f, 0.6039216f, 0.6666667f);
|
||||
TEMPLATE_COLORS[81] = NiColor(0.7843137f, 0.2196078f, 0.3529412f);
|
||||
TEMPLATE_COLORS[82] = NiColor(0.9372549f, 0.5960785f, 0.6666667f);
|
||||
TEMPLATE_COLORS[83] = NiColor(0.9921569f, 0.7372549f, 0.7058824f);
|
||||
TEMPLATE_COLORS[84] = NiColor(0.1019608f, 0.282353f, 0.4627451f);
|
||||
TEMPLATE_COLORS[85] = NiColor(0.1882353f, 0.7294118f, 0.5607843f);
|
||||
TEMPLATE_COLORS[86] = NiColor(0.772549f, 0.2941177f, 0.5490196f);
|
||||
TEMPLATE_COLORS[87] = NiColor(0.09803922f, 0.454902f, 0.8235294f);
|
||||
TEMPLATE_COLORS[88] = NiColor(0.7294118f, 0.7215686f, 0.4235294f);
|
||||
TEMPLATE_COLORS[89] = NiColor(1.0f, 0.4588235f, 0.2196078f);
|
||||
TEMPLATE_COLORS[90] = NiColor(1.0f, 0.1686275f, 0.1686275f);
|
||||
TEMPLATE_COLORS[91] = NiColor(0.972549f, 0.8352941f, 0.4078431f);
|
||||
TEMPLATE_COLORS[92] = NiColor(0.9019608f, 0.6588235f, 0.8431373f);
|
||||
TEMPLATE_COLORS[93] = NiColor(0.254902f, 0.2901961f, 0.2980392f);
|
||||
TEMPLATE_COLORS[94] = NiColor(1.0f, 0.4313726f, 0.2901961f);
|
||||
TEMPLATE_COLORS[95] = NiColor(0.1098039f, 0.6627451f, 0.7882353f);
|
||||
TEMPLATE_COLORS[96] = NiColor(1.0f, 0.8117647f, 0.6705883f);
|
||||
TEMPLATE_COLORS[97] = NiColor(0.772549f, 0.8156863f, 0.9019608f);
|
||||
TEMPLATE_COLORS[98] = NiColor(0.9921569f, 0.8666667f, 0.9019608f);
|
||||
TEMPLATE_COLORS[99] = NiColor(0.08235294f, 0.5019608f, 0.4705882f);
|
||||
TEMPLATE_COLORS[100] = NiColor(0.9882353f, 0.454902f, 0.9921569f);
|
||||
TEMPLATE_COLORS[101] = NiColor(0.9686275f, 0.5607843f, 0.654902f);
|
||||
TEMPLATE_COLORS[102] = NiColor(0.5568628f, 0.2705882f, 0.5215687f);
|
||||
TEMPLATE_COLORS[103] = NiColor(0.454902f, 0.2588235f, 0.7843137f);
|
||||
TEMPLATE_COLORS[104] = NiColor(0.6156863f, 0.5058824f, 0.7294118f);
|
||||
TEMPLATE_COLORS[105] = NiColor(1.0f, 0.2862745f, 0.4235294f);
|
||||
TEMPLATE_COLORS[106] = NiColor(0.8392157f, 0.5411765f, 0.3490196f);
|
||||
TEMPLATE_COLORS[107] = NiColor(0.4431373f, 0.2941177f, 0.1372549f);
|
||||
TEMPLATE_COLORS[108] = NiColor(1.0f, 0.282353f, 0.8156863f);
|
||||
TEMPLATE_COLORS[109] = NiColor(0.9333333f, 0.1254902f, 0.3019608f);
|
||||
TEMPLATE_COLORS[110] = NiColor(1.0f, 0.3254902f, 0.2862745f);
|
||||
TEMPLATE_COLORS[111] = NiColor(0.7529412f, 0.2666667f, 0.5607843f);
|
||||
TEMPLATE_COLORS[112] = NiColor(0.1215686f, 0.8078431f, 0.7960784f);
|
||||
TEMPLATE_COLORS[113] = NiColor(0.4705882f, 0.3176471f, 0.6627451f);
|
||||
TEMPLATE_COLORS[114] = NiColor(1.0f, 0.6078432f, 0.6666667f);
|
||||
TEMPLATE_COLORS[115] = NiColor(0.9882353f, 0.1568628f, 0.2784314f);
|
||||
TEMPLATE_COLORS[116] = NiColor(0.4627451f, 1.0f, 0.4784314f);
|
||||
TEMPLATE_COLORS[117] = NiColor(0.6235294f, 0.8862745f, 0.7490196f);
|
||||
TEMPLATE_COLORS[118] = NiColor(0.6470588f, 0.4117647f, 0.3098039f);
|
||||
TEMPLATE_COLORS[119] = NiColor(0.5411765f, 0.4745098f, 0.3647059f);
|
||||
TEMPLATE_COLORS[120] = NiColor(0.2705882f, 0.8078431f, 0.6352941f);
|
||||
TEMPLATE_COLORS[121] = NiColor(0.8039216f, 0.772549f, 0.7607843f);
|
||||
TEMPLATE_COLORS[122] = NiColor(0.5019608f, 0.854902f, 0.9215686f);
|
||||
TEMPLATE_COLORS[123] = NiColor(0.9254902f, 0.9176471f, 0.7450981f);
|
||||
TEMPLATE_COLORS[124] = NiColor(1.0f, 0.8117647f, 0.282353f);
|
||||
TEMPLATE_COLORS[125] = NiColor(0.9921569f, 0.3686275f, 0.3254902f);
|
||||
TEMPLATE_COLORS[126] = NiColor(0.9803922f, 0.654902f, 0.4235294f);
|
||||
TEMPLATE_COLORS[127] = NiColor(0.09411765f, 0.654902f, 0.7098039f);
|
||||
TEMPLATE_COLORS[128] = NiColor(0.9215686f, 0.7803922f, 0.8745098f);
|
||||
TEMPLATE_COLORS[129] = NiColor(0.9882353f, 0.5372549f, 0.6745098f);
|
||||
TEMPLATE_COLORS[130] = NiColor(0.8588235f, 0.8431373f, 0.8235294f);
|
||||
TEMPLATE_COLORS[131] = NiColor(0.8705882f, 0.6666667f, 0.5333334f);
|
||||
TEMPLATE_COLORS[132] = NiColor(0.4666667f, 0.8666667f, 0.9058824f);
|
||||
TEMPLATE_COLORS[133] = NiColor(1.0f, 1.0f, 0.4f);
|
||||
TEMPLATE_COLORS[134] = NiColor(0.572549f, 0.4313726f, 0.682353f);
|
||||
TEMPLATE_COLORS[135] = NiColor(0.1960784f, 0.2901961f, 0.6980392f);
|
||||
TEMPLATE_COLORS[136] = NiColor(0.9686275f, 0.3254902f, 0.5803922f);
|
||||
TEMPLATE_COLORS[137] = NiColor(1.0f, 0.627451f, 0.5372549f);
|
||||
TEMPLATE_COLORS[138] = NiColor(0.5607843f, 0.3137255f, 0.6156863f);
|
||||
TEMPLATE_COLORS[139] = NiColor(1.0f, 1.0f, 1.0f);
|
||||
TEMPLATE_COLORS[140] = NiColor(0.6352941f, 0.6784314f, 0.8156863f);
|
||||
TEMPLATE_COLORS[141] = NiColor(0.9882353f, 0.4235294f, 0.5215687f);
|
||||
TEMPLATE_COLORS[142] = NiColor(0.8039216f, 0.6431373f, 0.8705882f);
|
||||
TEMPLATE_COLORS[143] = NiColor(0.9882353f, 0.9098039f, 0.5137255f);
|
||||
TEMPLATE_COLORS[144] = NiColor(0.772549f, 0.8901961f, 0.5176471f);
|
||||
TEMPLATE_COLORS[145] = NiColor(1.0f, 0.682353f, 0.2588235f);
|
||||
}
|
||||
|
||||
const NiColor& Get(unsigned char index) const {
|
||||
return (index < 146) ? TEMPLATE_COLORS[index] : FALLBACK_COLOR;
|
||||
}
|
||||
|
||||
private:
|
||||
const NiColor FALLBACK_COLOR = NiColor(1.0f, 1.0f, 1.0f);
|
||||
std::vector<NiColor> TEMPLATE_COLORS;
|
||||
};
|
||||
|
||||
#endif // SCENE_COLOR_H
|
||||
@@ -1,11 +1,5 @@
|
||||
set(DNAVIGATION_SOURCES "dNavMesh.cpp")
|
||||
|
||||
add_subdirectory(dTerrain)
|
||||
|
||||
foreach(file ${DNAVIGATIONS_DTERRAIN_SOURCES})
|
||||
set(DNAVIGATION_SOURCES ${DNAVIGATION_SOURCES} "dTerrain/${file}")
|
||||
endforeach()
|
||||
|
||||
add_library(dNavigation OBJECT ${DNAVIGATION_SOURCES})
|
||||
target_include_directories(dNavigation PUBLIC "."
|
||||
PRIVATE
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "dNavMesh.h"
|
||||
|
||||
#include "RawFile.h"
|
||||
|
||||
#include "Game.h"
|
||||
#include "Logger.h"
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
set(DNAVIGATIONS_DTERRAIN_SOURCES "RawFile.cpp"
|
||||
"RawChunk.cpp"
|
||||
"RawHeightMap.cpp" PARENT_SCOPE)
|
||||
@@ -1,92 +0,0 @@
|
||||
#include "RawChunk.h"
|
||||
|
||||
#include "BinaryIO.h"
|
||||
|
||||
#include "RawMesh.h"
|
||||
#include "RawHeightMap.h"
|
||||
|
||||
RawChunk::RawChunk(std::ifstream& stream) {
|
||||
// Read the chunk index and info
|
||||
|
||||
BinaryIO::BinaryRead(stream, m_ChunkIndex);
|
||||
BinaryIO::BinaryRead(stream, m_Width);
|
||||
BinaryIO::BinaryRead(stream, m_Height);
|
||||
BinaryIO::BinaryRead(stream, m_X);
|
||||
BinaryIO::BinaryRead(stream, m_Z);
|
||||
|
||||
m_HeightMap = new RawHeightMap(stream, m_Height, m_Width);
|
||||
|
||||
// We can just skip the rest of the data so we can read the next chunks, we don't need anymore data
|
||||
|
||||
uint32_t colorMapSize;
|
||||
BinaryIO::BinaryRead(stream, colorMapSize);
|
||||
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (colorMapSize * colorMapSize * 4));
|
||||
|
||||
uint32_t lightmapSize;
|
||||
BinaryIO::BinaryRead(stream, lightmapSize);
|
||||
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (lightmapSize));
|
||||
|
||||
uint32_t colorMapSize2;
|
||||
BinaryIO::BinaryRead(stream, colorMapSize2);
|
||||
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (colorMapSize2 * colorMapSize2 * 4));
|
||||
|
||||
uint8_t unknown;
|
||||
BinaryIO::BinaryRead(stream, unknown);
|
||||
|
||||
uint32_t blendmapSize;
|
||||
BinaryIO::BinaryRead(stream, blendmapSize);
|
||||
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (blendmapSize));
|
||||
|
||||
uint32_t pointSize;
|
||||
BinaryIO::BinaryRead(stream, pointSize);
|
||||
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (pointSize * 9 * 4));
|
||||
|
||||
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (colorMapSize * colorMapSize));
|
||||
|
||||
uint32_t endCounter;
|
||||
BinaryIO::BinaryRead(stream, endCounter);
|
||||
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (endCounter * 2));
|
||||
|
||||
if (endCounter != 0) {
|
||||
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (32));
|
||||
|
||||
for (int i = 0; i < 0x10; i++) {
|
||||
uint16_t finalCountdown;
|
||||
BinaryIO::BinaryRead(stream, finalCountdown);
|
||||
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (finalCountdown * 2));
|
||||
}
|
||||
}
|
||||
|
||||
// Generate our mesh/geo data for this chunk
|
||||
|
||||
this->GenerateMesh();
|
||||
}
|
||||
|
||||
RawChunk::~RawChunk() {
|
||||
if (m_Mesh) delete m_Mesh;
|
||||
if (m_HeightMap) delete m_HeightMap;
|
||||
}
|
||||
|
||||
void RawChunk::GenerateMesh() {
|
||||
RawMesh* meshData = new RawMesh();
|
||||
|
||||
for (int i = 0; i < m_Width; ++i) {
|
||||
for (int j = 0; j < m_Height; ++j) {
|
||||
float y = *std::next(m_HeightMap->m_FloatMap.begin(), m_Width * i + j);
|
||||
|
||||
meshData->m_Vertices.push_back(NiPoint3(i, y, j));
|
||||
|
||||
if (i == 0 || j == 0) continue;
|
||||
|
||||
meshData->m_Triangles.push_back(m_Width * i + j);
|
||||
meshData->m_Triangles.push_back(m_Width * i + j - 1);
|
||||
meshData->m_Triangles.push_back(m_Width * (i - 1) + j - 1);
|
||||
|
||||
meshData->m_Triangles.push_back(m_Width * (i - 1) + j - 1);
|
||||
meshData->m_Triangles.push_back(m_Width * (i - 1) + j);
|
||||
meshData->m_Triangles.push_back(m_Width * i + j);
|
||||
}
|
||||
}
|
||||
|
||||
m_Mesh = meshData;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
|
||||
struct RawMesh;
|
||||
class RawHeightMap;
|
||||
|
||||
class RawChunk {
|
||||
public:
|
||||
RawChunk(std::ifstream& stream);
|
||||
~RawChunk();
|
||||
|
||||
void GenerateMesh();
|
||||
|
||||
uint32_t m_ChunkIndex;
|
||||
uint32_t m_Width;
|
||||
uint32_t m_Height;
|
||||
float m_X;
|
||||
float m_Z;
|
||||
|
||||
RawHeightMap* m_HeightMap;
|
||||
RawMesh* m_Mesh;
|
||||
};
|
||||
@@ -1,84 +0,0 @@
|
||||
#include "RawFile.h"
|
||||
|
||||
#include "BinaryIO.h"
|
||||
#include "RawChunk.h"
|
||||
#include "RawMesh.h"
|
||||
#include "RawHeightMap.h"
|
||||
|
||||
RawFile::RawFile(std::string fileName) {
|
||||
if (!BinaryIO::DoesFileExist(fileName)) return;
|
||||
|
||||
std::ifstream file(fileName, std::ios::binary);
|
||||
|
||||
// Read header
|
||||
|
||||
BinaryIO::BinaryRead(file, m_Version);
|
||||
BinaryIO::BinaryRead(file, m_Padding);
|
||||
BinaryIO::BinaryRead(file, m_ChunkCount);
|
||||
BinaryIO::BinaryRead(file, m_Width);
|
||||
BinaryIO::BinaryRead(file, m_Height);
|
||||
|
||||
|
||||
if (m_Version < 0x20) {
|
||||
return; // Version is too old to be supported
|
||||
}
|
||||
|
||||
// Read in chunks
|
||||
|
||||
m_Chunks = {};
|
||||
|
||||
for (uint32_t i = 0; i < m_ChunkCount; i++) {
|
||||
RawChunk* chunk = new RawChunk(file);
|
||||
m_Chunks.push_back(chunk);
|
||||
}
|
||||
|
||||
m_FinalMesh = new RawMesh();
|
||||
|
||||
this->GenerateFinalMeshFromChunks();
|
||||
}
|
||||
|
||||
RawFile::~RawFile() {
|
||||
if (m_FinalMesh) delete m_FinalMesh;
|
||||
for (const auto* item : m_Chunks) {
|
||||
if (item) delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void RawFile::GenerateFinalMeshFromChunks() {
|
||||
uint32_t lenOfLastChunk = 0; // index of last vert set in the last chunk
|
||||
|
||||
for (const auto& chunk : m_Chunks) {
|
||||
for (const auto& vert : chunk->m_Mesh->m_Vertices) {
|
||||
auto tempVert = vert;
|
||||
|
||||
// Scale X and Z by the chunk's position in the world
|
||||
// Scale Y by the chunk's heightmap scale factor
|
||||
tempVert.SetX(tempVert.GetX() + (chunk->m_X / chunk->m_HeightMap->m_ScaleFactor));
|
||||
tempVert.SetY(tempVert.GetY() / chunk->m_HeightMap->m_ScaleFactor);
|
||||
tempVert.SetZ(tempVert.GetZ() + (chunk->m_Z / chunk->m_HeightMap->m_ScaleFactor));
|
||||
|
||||
// Then scale it again for some reason
|
||||
tempVert *= chunk->m_HeightMap->m_ScaleFactor;
|
||||
|
||||
m_FinalMesh->m_Vertices.push_back(tempVert);
|
||||
}
|
||||
|
||||
for (const auto& tri : chunk->m_Mesh->m_Triangles) {
|
||||
m_FinalMesh->m_Triangles.push_back(tri + lenOfLastChunk);
|
||||
}
|
||||
|
||||
lenOfLastChunk += chunk->m_Mesh->m_Vertices.size();
|
||||
}
|
||||
}
|
||||
|
||||
void RawFile::WriteFinalMeshToOBJ(std::string path) {
|
||||
std::ofstream file(path);
|
||||
|
||||
for (const auto& v : m_FinalMesh->m_Vertices) {
|
||||
file << "v " << v.x << ' ' << v.y << ' ' << v.z << '\n';
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_FinalMesh->m_Triangles.size(); i += 3) {
|
||||
file << "f " << *std::next(m_FinalMesh->m_Triangles.begin(), i) + 1 << ' ' << *std::next(m_FinalMesh->m_Triangles.begin(), i + 1) + 1 << ' ' << *std::next(m_FinalMesh->m_Triangles.begin(), i + 2) + 1 << '\n';
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
class RawChunk;
|
||||
struct RawMesh;
|
||||
|
||||
class RawFile {
|
||||
public:
|
||||
RawFile(std::string filePath);
|
||||
~RawFile();
|
||||
|
||||
private:
|
||||
|
||||
void GenerateFinalMeshFromChunks();
|
||||
void WriteFinalMeshToOBJ(std::string path);
|
||||
|
||||
uint8_t m_Version;
|
||||
uint16_t m_Padding;
|
||||
uint32_t m_ChunkCount;
|
||||
uint32_t m_Width;
|
||||
uint32_t m_Height;
|
||||
|
||||
std::vector<RawChunk*> m_Chunks;
|
||||
RawMesh* m_FinalMesh = nullptr;
|
||||
};
|
||||
@@ -1,27 +0,0 @@
|
||||
#include "RawHeightMap.h"
|
||||
|
||||
#include "BinaryIO.h"
|
||||
|
||||
RawHeightMap::RawHeightMap() {}
|
||||
|
||||
RawHeightMap::RawHeightMap(std::ifstream& stream, float height, float width) {
|
||||
// Read in height map data header and scale
|
||||
|
||||
BinaryIO::BinaryRead(stream, m_Unknown1);
|
||||
BinaryIO::BinaryRead(stream, m_Unknown2);
|
||||
BinaryIO::BinaryRead(stream, m_Unknown3);
|
||||
BinaryIO::BinaryRead(stream, m_Unknown4);
|
||||
BinaryIO::BinaryRead(stream, m_ScaleFactor);
|
||||
|
||||
// read all vertices in
|
||||
|
||||
for (uint64_t i = 0; i < width * height; i++) {
|
||||
float value;
|
||||
BinaryIO::BinaryRead(stream, value);
|
||||
m_FloatMap.push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
RawHeightMap::~RawHeightMap() {
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
class RawHeightMap {
|
||||
public:
|
||||
RawHeightMap();
|
||||
RawHeightMap(std::ifstream& stream, float height, float width);
|
||||
~RawHeightMap();
|
||||
|
||||
uint32_t m_Unknown1;
|
||||
uint32_t m_Unknown2;
|
||||
uint32_t m_Unknown3;
|
||||
uint32_t m_Unknown4;
|
||||
|
||||
float m_ScaleFactor;
|
||||
|
||||
std::vector<float> m_FloatMap = {};
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "NiPoint3.h"
|
||||
|
||||
struct RawMesh {
|
||||
std::vector<NiPoint3> m_Vertices;
|
||||
std::vector<uint32_t> m_Triangles;
|
||||
};
|
||||
@@ -15,6 +15,7 @@ target_include_directories(dZoneManager PUBLIC "."
|
||||
"${PROJECT_SOURCE_DIR}/dGame" # Entity.h
|
||||
"${PROJECT_SOURCE_DIR}/dGame/dEntity" # EntityInfo.h
|
||||
PRIVATE
|
||||
"${PROJECT_SOURCE_DIR}/dCommon/dClient" # SceneColors.h
|
||||
"${PROJECT_SOURCE_DIR}/dGame/dComponents" #InventoryComponent.h
|
||||
"${PROJECT_SOURCE_DIR}/dGame/dInventory" #InventoryComponent.h (transitive)
|
||||
"${PROJECT_SOURCE_DIR}/dGame/dBehaviors" #BehaviorSlot.h
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "Raw.h"
|
||||
#include "BinaryIO.h"
|
||||
#include "Logger.h"
|
||||
#include "SceneColor.h"
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Raw {
|
||||
|
||||
@@ -279,16 +281,22 @@ namespace Raw {
|
||||
return; // No scene data available
|
||||
}
|
||||
|
||||
LOG("GenerateTerrainMesh: Processing %u chunks", raw.chunks.size());
|
||||
|
||||
uint32_t vertexOffset = 0;
|
||||
|
||||
for (const auto& chunk : raw.chunks) {
|
||||
// Skip chunks without scene maps
|
||||
if (chunk.sceneMap.empty() || chunk.colorMapResolution == 0 || chunk.heightMap.empty()) {
|
||||
LOG("Skipping chunk %u (sceneMap: %zu, colorMapRes: %u, heightMap: %zu)",
|
||||
chunk.id, chunk.sceneMap.size(), chunk.colorMapResolution, chunk.heightMap.size());
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG("Processing chunk %u: width=%u, height=%u, colorMapRes=%u, sceneMapSize=%zu",
|
||||
chunk.id, chunk.width, chunk.height, chunk.colorMapResolution, chunk.sceneMap.size());
|
||||
|
||||
// Generate vertices for this chunk
|
||||
// Similar to RawChunk::GenerateMesh() in dTerrain but with scene IDs
|
||||
for (uint32_t i = 0; i < chunk.width; ++i) {
|
||||
for (uint32_t j = 0; j < chunk.height; ++j) {
|
||||
// Get height at this position
|
||||
@@ -310,21 +318,23 @@ namespace Raw {
|
||||
|
||||
NiPoint3 worldPos(worldX, worldY, worldZ);
|
||||
|
||||
// Get scene ID at this position
|
||||
// Map heightmap position to scene map position
|
||||
const float sceneMapX = (static_cast<float>(i) / static_cast<float>(chunk.width - 1)) * static_cast<float>(chunk.colorMapResolution - 1);
|
||||
const float sceneMapZ = (static_cast<float>(j) / static_cast<float>(chunk.height - 1)) * static_cast<float>(chunk.colorMapResolution - 1);
|
||||
|
||||
const uint32_t sceneX = std::min(static_cast<uint32_t>(sceneMapX), chunk.colorMapResolution - 1);
|
||||
const uint32_t sceneZ = std::min(static_cast<uint32_t>(sceneMapZ), chunk.colorMapResolution - 1);
|
||||
const uint32_t sceneIndex = sceneZ * chunk.colorMapResolution + sceneX;
|
||||
// Get scene ID at this position
|
||||
// Map heightmap position to scene map position
|
||||
// The scene map is colorMapResolution x colorMapResolution
|
||||
// We need to map from heightmap coordinates (i, j) to scene map coordinates
|
||||
const float sceneMapI = (static_cast<float>(i) / static_cast<float>(chunk.width - 1)) * static_cast<float>(chunk.colorMapResolution - 1);
|
||||
const float sceneMapJ = (static_cast<float>(j) / static_cast<float>(chunk.height - 1)) * static_cast<float>(chunk.colorMapResolution - 1);
|
||||
|
||||
const uint32_t sceneI = std::min(static_cast<uint32_t>(sceneMapI), chunk.colorMapResolution - 1);
|
||||
const uint32_t sceneJ = std::min(static_cast<uint32_t>(sceneMapJ), chunk.colorMapResolution - 1);
|
||||
// Scene map uses the same indexing pattern as heightmap: row * width + col
|
||||
const uint32_t sceneIndex = sceneI * chunk.colorMapResolution + sceneJ;
|
||||
|
||||
uint8_t sceneID = 0;
|
||||
if (sceneIndex < chunk.sceneMap.size()) {
|
||||
sceneID = chunk.sceneMap[sceneIndex];
|
||||
}
|
||||
|
||||
outMesh.vertices.emplace_back(worldPos, sceneID);
|
||||
uint8_t sceneID = 0;
|
||||
if (sceneIndex < chunk.sceneMap.size()) {
|
||||
sceneID = chunk.sceneMap[sceneIndex];
|
||||
}
|
||||
outMesh.vertices.emplace_back(worldPos, sceneID);
|
||||
|
||||
// Generate triangles (same pattern as dTerrain)
|
||||
if (i > 0 && j > 0) {
|
||||
@@ -346,8 +356,49 @@ namespace Raw {
|
||||
}
|
||||
}
|
||||
|
||||
vertexOffset += chunk.width * chunk.height;
|
||||
}
|
||||
vertexOffset += chunk.width * chunk.height;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Raw
|
||||
bool WriteTerrainMeshToOBJ(const TerrainMesh& mesh, const std::string& path) {
|
||||
try {
|
||||
std::ofstream file(path);
|
||||
if (!file.is_open()) {
|
||||
LOG("Failed to open OBJ file for writing: %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create instance of SceneColor for color lookup
|
||||
SceneColor sceneColor;
|
||||
|
||||
// Write vertices with colors
|
||||
// OBJ format supports vertex colors as: v x y z r g b
|
||||
for (const auto& v : mesh.vertices) {
|
||||
file << "v " << v.position.x << ' ' << v.position.y << ' ' << v.position.z;
|
||||
|
||||
uint8_t sceneID = v.sceneID;
|
||||
|
||||
const NiColor& color = sceneColor.Get(sceneID);
|
||||
file << ' ' << color.m_Red << ' ' << color.m_Green << ' ' << color.m_Blue;
|
||||
file << '\n';
|
||||
}
|
||||
|
||||
// Write faces (triangles)
|
||||
for (size_t i = 0; i < mesh.triangles.size(); i += 3) {
|
||||
// OBJ indices are 1-based
|
||||
file << "f " << (mesh.triangles[i] + 1) << ' '
|
||||
<< (mesh.triangles[i + 1] + 1) << ' '
|
||||
<< (mesh.triangles[i + 2] + 1) << '\n';
|
||||
}
|
||||
|
||||
file.close();
|
||||
LOG("Successfully wrote terrain mesh to OBJ: %s (%zu vertices, %zu triangles)",
|
||||
path.c_str(), mesh.vertices.size(), mesh.triangles.size() / 3);
|
||||
return true;
|
||||
} catch (const std::exception& e) {
|
||||
LOG("Exception while writing OBJ file: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Raw
|
||||
@@ -7,7 +7,9 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <istream>
|
||||
#include <map>
|
||||
#include "NiPoint3.h"
|
||||
#include "dCommonVars.h"
|
||||
|
||||
namespace Raw {
|
||||
|
||||
@@ -138,6 +140,17 @@ bool ReadRaw(std::istream& stream, Raw& outRaw);
|
||||
*/
|
||||
void GenerateTerrainMesh(const Raw& raw, TerrainMesh& outMesh);
|
||||
|
||||
/**
|
||||
* @brief Write terrain mesh to OBJ file for debugging/visualization
|
||||
* Merged from dTerrain's WriteFinalMeshToOBJ functionality
|
||||
* Vertices are colored based on their scene ID using a hash function
|
||||
*
|
||||
* @param mesh The terrain mesh to export
|
||||
* @param path Output path for the OBJ file
|
||||
* @return true if successfully written, false otherwise
|
||||
*/
|
||||
bool WriteTerrainMeshToOBJ(const TerrainMesh& mesh, const std::string& path);
|
||||
|
||||
} // namespace Raw
|
||||
|
||||
#endif // __RAW_H__
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "GeneralUtils.h"
|
||||
#include "BinaryIO.h"
|
||||
#include "LUTriggers.h"
|
||||
#include "dConfig.h"
|
||||
|
||||
#include "AssetManager.h"
|
||||
#include "CDClientManager.h"
|
||||
@@ -102,6 +103,14 @@ void Zone::LoadZoneIntoMemory() {
|
||||
LOG("Generated terrain mesh with %llu vertices and %llu triangles",
|
||||
m_TerrainMesh.vertices.size(), m_TerrainMesh.triangles.size() / 3);
|
||||
|
||||
// Optionally export terrain mesh to OBJ for debugging/visualization
|
||||
if (Game::config->GetValue("export_terrain_to_obj") == "1") {
|
||||
std::string objFileName = "terrain_" + std::to_string(m_ZoneID.GetMapID()) + ".obj";
|
||||
if (Raw::WriteTerrainMeshToOBJ(m_TerrainMesh, objFileName)) {
|
||||
LOG("Exported terrain mesh to %s", objFileName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (m_FileFormatVersion >= Zone::FileFormatVersion::PreAlpha) {
|
||||
BinaryIO::BinaryRead(file, m_NumberOfSceneTransitionsLoaded);
|
||||
for (uint32_t i = 0; i < m_NumberOfSceneTransitionsLoaded; ++i) {
|
||||
|
||||
@@ -399,6 +399,23 @@ void dZoneManager::BuildSceneGraph() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scene 0 (global scene) is always loaded and adjacent to all other scenes
|
||||
LWOSCENEID globalScene = LWOSCENEID(m_ZoneID.GetMapID(), 0);
|
||||
for (auto& [sceneID, adjacentScenes] : m_SceneAdjacencyList) {
|
||||
if (sceneID != globalScene) {
|
||||
// Add global scene to this scene's adjacency list if not already present
|
||||
if (std::find(adjacentScenes.begin(), adjacentScenes.end(), globalScene) == adjacentScenes.end()) {
|
||||
adjacentScenes.push_back(globalScene);
|
||||
}
|
||||
|
||||
// Add this scene to global scene's adjacency list if not already present
|
||||
auto& globalAdjacent = m_SceneAdjacencyList[globalScene];
|
||||
if (std::find(globalAdjacent.begin(), globalAdjacent.end(), sceneID) == globalAdjacent.end()) {
|
||||
globalAdjacent.push_back(sceneID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LWOSCENEID> dZoneManager::GetAdjacentScenes(LWOSCENEID sceneID) const {
|
||||
|
||||
403
enc_temp_folder/48a84d7fa3b1c27696794fcc62d106d/Raw.cpp
Normal file
403
enc_temp_folder/48a84d7fa3b1c27696794fcc62d106d/Raw.cpp
Normal file
@@ -0,0 +1,403 @@
|
||||
#include "Raw.h"
|
||||
#include "BinaryIO.h"
|
||||
#include "Logger.h"
|
||||
#include "SceneColor.h"
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Raw {
|
||||
|
||||
/**
|
||||
* @brief Read flair attributes from stream
|
||||
*/
|
||||
static bool ReadFlairAttributes(std::istream& stream, FlairAttributes& flair) {
|
||||
try {
|
||||
BinaryIO::BinaryRead(stream, flair.id);
|
||||
BinaryIO::BinaryRead(stream, flair.scaleFactor);
|
||||
BinaryIO::BinaryRead(stream, flair.position.x);
|
||||
BinaryIO::BinaryRead(stream, flair.position.y);
|
||||
BinaryIO::BinaryRead(stream, flair.position.z);
|
||||
BinaryIO::BinaryRead(stream, flair.rotation.x);
|
||||
BinaryIO::BinaryRead(stream, flair.rotation.y);
|
||||
BinaryIO::BinaryRead(stream, flair.rotation.z);
|
||||
BinaryIO::BinaryRead(stream, flair.colorR);
|
||||
BinaryIO::BinaryRead(stream, flair.colorG);
|
||||
BinaryIO::BinaryRead(stream, flair.colorB);
|
||||
BinaryIO::BinaryRead(stream, flair.colorA);
|
||||
return true;
|
||||
} catch (const std::exception&) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read mesh triangle data from stream
|
||||
*/
|
||||
static bool ReadMeshTri(std::istream& stream, MeshTri& meshTri) {
|
||||
try {
|
||||
BinaryIO::BinaryRead(stream, meshTri.meshTriListSize);
|
||||
meshTri.meshTriList.resize(meshTri.meshTriListSize);
|
||||
for (uint16_t i = 0; i < meshTri.meshTriListSize; ++i) {
|
||||
BinaryIO::BinaryRead(stream, meshTri.meshTriList[i]);
|
||||
}
|
||||
return true;
|
||||
} catch (const std::exception&) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a chunk from stream
|
||||
*/
|
||||
static bool ReadChunk(std::istream& stream, Chunk& chunk, uint16_t version) {
|
||||
try {
|
||||
// Read basic chunk info
|
||||
BinaryIO::BinaryRead(stream, chunk.id);
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BinaryIO::BinaryRead(stream, chunk.width);
|
||||
BinaryIO::BinaryRead(stream, chunk.height);
|
||||
BinaryIO::BinaryRead(stream, chunk.offsetWorldX);
|
||||
BinaryIO::BinaryRead(stream, chunk.offsetWorldZ);
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// For version < 32, shader ID comes before texture IDs
|
||||
if (version < 32) {
|
||||
BinaryIO::BinaryRead(stream, chunk.shaderId);
|
||||
}
|
||||
|
||||
// Read texture IDs (4 textures)
|
||||
chunk.textureIds.resize(4);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
BinaryIO::BinaryRead(stream, chunk.textureIds[i]);
|
||||
}
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read scale factor
|
||||
BinaryIO::BinaryRead(stream, chunk.scaleFactor);
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read heightmap
|
||||
uint32_t heightMapSize = chunk.width * chunk.height;
|
||||
|
||||
chunk.heightMap.resize(heightMapSize);
|
||||
for (uint32_t i = 0; i < heightMapSize; ++i) {
|
||||
BinaryIO::BinaryRead(stream, chunk.heightMap[i]);
|
||||
}
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ColorMap (size varies by version)
|
||||
if (version >= 32) {
|
||||
BinaryIO::BinaryRead(stream, chunk.colorMapResolution);
|
||||
} else {
|
||||
chunk.colorMapResolution = chunk.width; // Default to chunk width for older versions
|
||||
}
|
||||
|
||||
uint32_t colorMapPixelCount = chunk.colorMapResolution * chunk.colorMapResolution * 4; // RGBA
|
||||
chunk.colorMap.resize(colorMapPixelCount);
|
||||
stream.read(reinterpret_cast<char*>(chunk.colorMap.data()), colorMapPixelCount);
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// LightMap DDS
|
||||
uint32_t lightMapSize;
|
||||
BinaryIO::BinaryRead(stream, lightMapSize);
|
||||
|
||||
chunk.lightMap.resize(lightMapSize);
|
||||
stream.read(reinterpret_cast<char*>(chunk.lightMap.data()), lightMapSize);
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TextureMap (size varies by version)
|
||||
if (version >= 32) {
|
||||
BinaryIO::BinaryRead(stream, chunk.textureMapResolution);
|
||||
} else {
|
||||
chunk.textureMapResolution = chunk.width; // Default to chunk width for older versions
|
||||
}
|
||||
|
||||
uint32_t textureMapPixelCount = chunk.textureMapResolution * chunk.textureMapResolution * 4;
|
||||
chunk.textureMap.resize(textureMapPixelCount);
|
||||
stream.read(reinterpret_cast<char*>(chunk.textureMap.data()), textureMapPixelCount);
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Texture settings
|
||||
BinaryIO::BinaryRead(stream, chunk.textureSettings);
|
||||
|
||||
// Blend map DDS
|
||||
uint32_t blendMapDDSSize;
|
||||
BinaryIO::BinaryRead(stream, blendMapDDSSize);
|
||||
|
||||
chunk.blendMap.resize(blendMapDDSSize);
|
||||
stream.read(reinterpret_cast<char*>(chunk.blendMap.data()), blendMapDDSSize);
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read flairs
|
||||
uint32_t numFlairs;
|
||||
BinaryIO::BinaryRead(stream, numFlairs);
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
chunk.flairs.resize(numFlairs);
|
||||
for (uint32_t i = 0; i < numFlairs; ++i) {
|
||||
if (!ReadFlairAttributes(stream, chunk.flairs[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Scene map (version 32+ only)
|
||||
if (version >= 32) {
|
||||
uint32_t sceneMapSize = chunk.colorMapResolution * chunk.colorMapResolution;
|
||||
|
||||
chunk.sceneMap.resize(sceneMapSize);
|
||||
stream.read(reinterpret_cast<char*>(chunk.sceneMap.data()), sceneMapSize);
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Mesh vertex usage (read size first, then check if empty)
|
||||
BinaryIO::BinaryRead(stream, chunk.vertSize);
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mesh vert usage
|
||||
chunk.meshVertUsage.resize(chunk.vertSize);
|
||||
for (uint32_t i = 0; i < chunk.vertSize; ++i) {
|
||||
BinaryIO::BinaryRead(stream, chunk.meshVertUsage[i]);
|
||||
}
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only continue with mesh data if we have vertex usage data
|
||||
if (chunk.vertSize == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Mesh vert size (16 elements)
|
||||
chunk.meshVertSize.resize(16);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
BinaryIO::BinaryRead(stream, chunk.meshVertSize[i]);
|
||||
}
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mesh triangles (16 elements)
|
||||
chunk.meshTri.resize(16);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if (!ReadMeshTri(stream, chunk.meshTri[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (const std::exception&) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ReadRaw(std::istream& stream, Raw& outRaw) {
|
||||
// Get stream size
|
||||
stream.seekg(0, std::ios::end);
|
||||
auto streamSize = stream.tellg();
|
||||
stream.seekg(0, std::ios::beg);
|
||||
|
||||
if (streamSize <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// Read header
|
||||
BinaryIO::BinaryRead(stream, outRaw.version);
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BinaryIO::BinaryRead(stream, outRaw.dev);
|
||||
|
||||
if (stream.fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only read chunks if dev == 0
|
||||
if (outRaw.dev == 0) {
|
||||
BinaryIO::BinaryRead(stream, outRaw.numChunks);
|
||||
BinaryIO::BinaryRead(stream, outRaw.numChunksWidth);
|
||||
BinaryIO::BinaryRead(stream, outRaw.numChunksHeight);
|
||||
|
||||
// Read all chunks
|
||||
outRaw.chunks.resize(outRaw.numChunks);
|
||||
for (uint32_t i = 0; i < outRaw.numChunks; ++i) {
|
||||
if (!ReadChunk(stream, outRaw.chunks[i], outRaw.version)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (const std::exception&) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateTerrainMesh(const Raw& raw, TerrainMesh& outMesh) {
|
||||
outMesh.vertices.clear();
|
||||
outMesh.triangles.clear();
|
||||
|
||||
if (raw.chunks.empty() || raw.version < 32) {
|
||||
return; // No scene data available
|
||||
}
|
||||
|
||||
LOG("GenerateTerrainMesh: Processing %u chunks", raw.chunks.size());
|
||||
|
||||
uint32_t vertexOffset = 0;
|
||||
|
||||
for (const auto& chunk : raw.chunks) {
|
||||
// Skip chunks without scene maps
|
||||
if (chunk.sceneMap.empty() || chunk.colorMapResolution == 0 || chunk.heightMap.empty()) {
|
||||
LOG("Skipping chunk %u (sceneMap: %zu, colorMapRes: %u, heightMap: %zu)",
|
||||
chunk.id, chunk.sceneMap.size(), chunk.colorMapResolution, chunk.heightMap.size());
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG("Processing chunk %u: width=%u, height=%u, colorMapRes=%u, sceneMapSize=%zu",
|
||||
chunk.id, chunk.width, chunk.height, chunk.colorMapResolution, chunk.sceneMap.size());
|
||||
|
||||
// Generate vertices for this chunk
|
||||
for (uint32_t i = 0; i < chunk.width; ++i) {
|
||||
for (uint32_t j = 0; j < chunk.height; ++j) {
|
||||
// Get height at this position
|
||||
const uint32_t heightIndex = chunk.width * i + j;
|
||||
if (heightIndex >= chunk.heightMap.size()) continue;
|
||||
|
||||
const float y = chunk.heightMap[heightIndex];
|
||||
|
||||
// Calculate world position
|
||||
// Based on RawFile::GenerateFinalMeshFromChunks in dTerrain:
|
||||
// tempVert.SetX(tempVert.GetX() + (chunk->m_X / chunk->m_HeightMap->m_ScaleFactor));
|
||||
// tempVert.SetY(tempVert.GetY() / chunk->m_HeightMap->m_ScaleFactor);
|
||||
// tempVert.SetZ(tempVert.GetZ() + (chunk->m_Z / chunk->m_HeightMap->m_ScaleFactor));
|
||||
// tempVert *= chunk->m_HeightMap->m_ScaleFactor;
|
||||
|
||||
float worldX = (static_cast<float>(i) + (chunk.offsetWorldX / chunk.scaleFactor)) * chunk.scaleFactor;
|
||||
float worldY = (y / chunk.scaleFactor) * chunk.scaleFactor;
|
||||
float worldZ = (static_cast<float>(j) + (chunk.offsetWorldZ / chunk.scaleFactor)) * chunk.scaleFactor;
|
||||
|
||||
NiPoint3 worldPos(worldX, worldY, worldZ);
|
||||
|
||||
// Get scene ID at this position
|
||||
// Map heightmap position to scene map position
|
||||
// The scene map is colorMapResolution x colorMapResolution
|
||||
// We need to map from heightmap coordinates (i, j) to scene map coordinates
|
||||
const float sceneMapI = (static_cast<float>(i) / static_cast<float>(chunk.width - 1)) * static_cast<float>(chunk.colorMapResolution - 1);
|
||||
const float sceneMapJ = (static_cast<float>(j) / static_cast<float>(chunk.height - 1)) * static_cast<float>(chunk.colorMapResolution - 1);
|
||||
|
||||
const uint32_t sceneI = std::min(static_cast<uint32_t>(sceneMapI), chunk.colorMapResolution - 1);
|
||||
const uint32_t sceneJ = std::min(static_cast<uint32_t>(sceneMapJ), chunk.colorMapResolution - 1);
|
||||
// Scene map uses the same indexing pattern as heightmap: row * width + col
|
||||
const uint32_t sceneIndex = sceneI * chunk.colorMapResolution + sceneJ;
|
||||
|
||||
uint8_t sceneID = 0;
|
||||
if (sceneIndex < chunk.sceneMap.size()) {
|
||||
sceneID = chunk.sceneMap[sceneIndex];
|
||||
} outMesh.vertices.emplace_back(worldPos, sceneID);
|
||||
|
||||
// Generate triangles (same pattern as dTerrain)
|
||||
if (i > 0 && j > 0) {
|
||||
const uint32_t currentVert = vertexOffset + chunk.width * i + j;
|
||||
const uint32_t leftVert = currentVert - 1;
|
||||
const uint32_t bottomLeftVert = vertexOffset + chunk.width * (i - 1) + j - 1;
|
||||
const uint32_t bottomVert = vertexOffset + chunk.width * (i - 1) + j;
|
||||
|
||||
// First triangle
|
||||
outMesh.triangles.push_back(currentVert);
|
||||
outMesh.triangles.push_back(leftVert);
|
||||
outMesh.triangles.push_back(bottomLeftVert);
|
||||
|
||||
// Second triangle
|
||||
outMesh.triangles.push_back(bottomLeftVert);
|
||||
outMesh.triangles.push_back(bottomVert);
|
||||
outMesh.triangles.push_back(currentVert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vertexOffset += chunk.width * chunk.height;
|
||||
}
|
||||
}
|
||||
|
||||
bool WriteTerrainMeshToOBJ(const TerrainMesh& mesh, const std::string& path) {
|
||||
try {
|
||||
std::ofstream file(path);
|
||||
if (!file.is_open()) {
|
||||
LOG("Failed to open OBJ file for writing: %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create instance of SceneColor for color lookup
|
||||
SceneColor sceneColor;
|
||||
|
||||
// Write vertices with colors
|
||||
// OBJ format supports vertex colors as: v x y z r g b
|
||||
for (const auto& v : mesh.vertices) {
|
||||
file << "v " << v.position.x << ' ' << v.position.y << ' ' << v.position.z;
|
||||
|
||||
uint8_t sceneID = v.sceneID;
|
||||
|
||||
const NiColor& color = sceneColor.Get(sceneID);
|
||||
file << ' ' << color.m_Red << ' ' << color.m_Green << ' ' << color.m_Blue;
|
||||
file << '\n';
|
||||
}
|
||||
|
||||
// Write faces (triangles)
|
||||
for (size_t i = 0; i < mesh.triangles.size(); i += 3) {
|
||||
// OBJ indices are 1-based
|
||||
file << "f " << (mesh.triangles[i] + 1) << ' '
|
||||
<< (mesh.triangles[i + 1] + 1) << ' '
|
||||
<< (mesh.triangles[i + 2] + 1) << '\n';
|
||||
}
|
||||
|
||||
file.close();
|
||||
LOG("Successfully wrote terrain mesh to OBJ: %s (%zu vertices, %zu triangles)",
|
||||
path.c_str(), mesh.vertices.size(), mesh.triangles.size() / 3);
|
||||
return true;
|
||||
} catch (const std::exception& e) {
|
||||
LOG("Exception while writing OBJ file: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Raw
|
||||
@@ -102,3 +102,7 @@ hardcore_disabled_worlds=
|
||||
|
||||
# Keeps this percentage of a players' coins on death in hardcore
|
||||
hardcore_coin_keep=
|
||||
|
||||
# Export terrain meshes to OBJ files when zones load
|
||||
# OBJ files will be saved as terrain_<zoneID>.obj in the server directory
|
||||
export_terrain_to_obj=0
|
||||
|
||||
Reference in New Issue
Block a user