pioneer/src/GeoPatchJobs.h

307 lines
8.7 KiB
C++

// Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
#ifndef _GEOPATCHJOBS_H
#define _GEOPATCHJOBS_H
#include <SDL_stdinc.h>
#include "Color.h"
#include "GeoPatchID.h"
#include "JobQueue.h"
#include "vector3.h"
#include "terrain/Terrain.h"
class GeoSphere;
#define BORDER_SIZE 1
class SBaseRequest {
public:
SBaseRequest(const vector3d &v0_, const vector3d &v1_, const vector3d &v2_, const vector3d &v3_, const vector3d &cn,
const uint32_t depth_, const SystemPath &sysPath_, const GeoPatchID &patchID_, const int edgeLen_, const double fracStep_,
Terrain *pTerrain_) :
v0(v0_),
v1(v1_),
v2(v2_),
v3(v3_),
centroid(cn),
depth(depth_),
sysPath(sysPath_),
patchID(patchID_),
edgeLen(edgeLen_),
fracStep(fracStep_),
pTerrain(pTerrain_)
{
}
inline int NUMVERTICES(const int el) const { return el * el; }
const vector3d v0, v1, v2, v3;
const vector3d centroid;
const uint32_t depth;
const SystemPath sysPath;
const GeoPatchID patchID;
const int edgeLen;
const double fracStep;
RefCountedPtr<Terrain> pTerrain;
protected:
// deliberately prevent copy constructor access
SBaseRequest(const SBaseRequest &r) = delete;
};
class SQuadSplitRequest : public SBaseRequest {
public:
SQuadSplitRequest(const vector3d &v0_, const vector3d &v1_, const vector3d &v2_, const vector3d &v3_, const vector3d &cn,
const uint32_t depth_, const SystemPath &sysPath_, const GeoPatchID &patchID_, const int edgeLen_, const double fracStep_,
Terrain *pTerrain_) :
SBaseRequest(v0_, v1_, v2_, v3_, cn, depth_, sysPath_, patchID_, edgeLen_, fracStep_, pTerrain_)
{
const int numVerts = NUMVERTICES(edgeLen_);
for (int i = 0; i < 4; ++i) {
heights[i] = new double[numVerts];
normals[i] = new vector3f[numVerts];
colors[i] = new Color3ub[numVerts];
}
const int numBorderedVerts = NUMVERTICES((edgeLen_ * 2) + (BORDER_SIZE * 2) - 1);
borderHeights.reset(new double[numBorderedVerts]);
borderVertexs.reset(new vector3d[numBorderedVerts]);
}
// Generates full-detail vertices, and also non-edge normals and colors
void GenerateBorderedData() const;
void GenerateSubPatchData(const int quadrantIndex,
const vector3d &v0, const vector3d &v1, const vector3d &v2, const vector3d &v3,
const int edgeLen, const int xoff, const int yoff, const int borderedEdgeLen) const;
// these are created with the request and are given to the resulting patches
vector3f *normals[4];
Color3ub *colors[4];
double *heights[4];
// these are created with the request but are destroyed when the request is finished
std::unique_ptr<double[]> borderHeights;
std::unique_ptr<vector3d[]> borderVertexs;
protected:
// deliberately prevent copy constructor access
SQuadSplitRequest(const SQuadSplitRequest &r) = delete;
};
class SSingleSplitRequest : public SBaseRequest {
public:
SSingleSplitRequest(const vector3d &v0_, const vector3d &v1_, const vector3d &v2_, const vector3d &v3_, const vector3d &cn,
const uint32_t depth_, const SystemPath &sysPath_, const GeoPatchID &patchID_, const int edgeLen_, const double fracStep_,
Terrain *pTerrain_) :
SBaseRequest(v0_, v1_, v2_, v3_, cn, depth_, sysPath_, patchID_, edgeLen_, fracStep_, pTerrain_)
{
const int numVerts = NUMVERTICES(edgeLen_);
heights = new double[numVerts];
normals = new vector3f[numVerts];
colors = new Color3ub[numVerts];
const int numBorderedVerts = NUMVERTICES(edgeLen_ + (BORDER_SIZE * 2));
borderHeights.reset(new double[numBorderedVerts]);
borderVertexs.reset(new vector3d[numBorderedVerts]);
}
// Generates full-detail vertices, and also non-edge normals and colors
void GenerateMesh() const;
// these are created with the request and are given to the resulting patches
vector3f *normals;
Color3ub *colors;
double *heights;
// these are created with the request but are destroyed when the request is finished
std::unique_ptr<double[]> borderHeights;
std::unique_ptr<vector3d[]> borderVertexs;
protected:
// deliberately prevent copy constructor access
SSingleSplitRequest(const SSingleSplitRequest &r) = delete;
};
class SBaseSplitResult {
public:
struct SSplitResultData {
SSplitResultData() :
patchID(0) {}
SSplitResultData(double *heights_, vector3f *n_, Color3ub *c_, const vector3d &v0_, const vector3d &v1_, const vector3d &v2_, const vector3d &v3_, const GeoPatchID &patchID_) :
heights(heights_),
normals(n_),
colors(c_),
v0(v0_),
v1(v1_),
v2(v2_),
v3(v3_),
patchID(patchID_)
{}
double *heights;
vector3f *normals;
Color3ub *colors;
vector3d v0, v1, v2, v3;
GeoPatchID patchID;
};
SBaseSplitResult(const int32_t face_, const int32_t depth_) :
mFace(face_),
mDepth(depth_) {}
virtual ~SBaseSplitResult() {}
inline int32_t face() const { return mFace; }
inline int32_t depth() const { return mDepth; }
virtual void OnCancel() = 0;
protected:
// deliberately prevent copy constructor access
SBaseSplitResult(const SBaseSplitResult &r) :
mFace(0),
mDepth(0) {}
const int32_t mFace;
const int32_t mDepth;
};
class SQuadSplitResult : public SBaseSplitResult {
static const int NUM_RESULT_DATA = 4;
public:
SQuadSplitResult(const int32_t face_, const int32_t depth_) :
SBaseSplitResult(face_, depth_)
{
}
void addResult(const int kidIdx, double *h_, vector3f *n_, Color3ub *c_, const vector3d &v0_, const vector3d &v1_, const vector3d &v2_, const vector3d &v3_, const GeoPatchID &patchID_)
{
assert(kidIdx >= 0 && kidIdx < NUM_RESULT_DATA);
mData[kidIdx] = (SSplitResultData(h_, n_, c_, v0_, v1_, v2_, v3_, patchID_));
}
inline const SSplitResultData &data(const int32_t idx) const { return mData[idx]; }
virtual void OnCancel()
{
for (int i = 0; i < NUM_RESULT_DATA; ++i) {
if (mData[i].heights) {
delete[] mData[i].heights;
mData[i].heights = NULL;
}
if (mData[i].normals) {
delete[] mData[i].normals;
mData[i].normals = NULL;
}
if (mData[i].colors) {
delete[] mData[i].colors;
mData[i].colors = NULL;
}
}
}
protected:
// deliberately prevent copy constructor access
SQuadSplitResult(const SQuadSplitResult &r) :
SBaseSplitResult(r) {}
SSplitResultData mData[NUM_RESULT_DATA];
};
class SSingleSplitResult : public SBaseSplitResult {
public:
SSingleSplitResult(const int32_t face_, const int32_t depth_) :
SBaseSplitResult(face_, depth_)
{
}
void addResult(double *h_, vector3f *n_, Color3ub *c_, const vector3d &v0_, const vector3d &v1_, const vector3d &v2_, const vector3d &v3_, const GeoPatchID &patchID_)
{
mData = (SSplitResultData(h_, n_, c_, v0_, v1_, v2_, v3_, patchID_));
}
inline const SSplitResultData &data() const { return mData; }
virtual void OnCancel()
{
{
if (mData.heights) {
delete[] mData.heights;
mData.heights = NULL;
}
if (mData.normals) {
delete[] mData.normals;
mData.normals = NULL;
}
if (mData.colors) {
delete[] mData.colors;
mData.colors = NULL;
}
}
}
protected:
// deliberately prevent copy constructor access
SSingleSplitResult(const SSingleSplitResult &r) :
SBaseSplitResult(r) {}
SSplitResultData mData;
};
class GeoPatch;
// ********************************************************************************
// Overloaded PureJob class to handle generating the mesh for each patch
// ********************************************************************************
class BasePatchJob : public Job {
public:
BasePatchJob() {}
virtual void OnRun() {} // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
virtual void OnFinish() {}
virtual void OnCancel() {}
};
// ********************************************************************************
// Overloaded PureJob class to handle generating the mesh for each patch
// ********************************************************************************
class SinglePatchJob : public BasePatchJob {
public:
SinglePatchJob(SSingleSplitRequest *data) :
mData(data),
mpResults(NULL)
{ /* empty */
}
~SinglePatchJob();
virtual void OnRun(); // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
virtual void OnFinish(); // runs in primary thread of the context
private:
std::unique_ptr<SSingleSplitRequest> mData;
SSingleSplitResult *mpResults;
};
// ********************************************************************************
// Overloaded PureJob class to handle generating the mesh for each patch
// ********************************************************************************
class QuadPatchJob : public BasePatchJob {
public:
QuadPatchJob(SQuadSplitRequest *data) :
mData(data),
mpResults(NULL)
{ /* empty */
}
~QuadPatchJob();
virtual void OnRun(); // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
virtual void OnFinish(); // runs in primary thread of the context
private:
std::unique_ptr<SQuadSplitRequest> mData;
SQuadSplitResult *mpResults;
};
#endif /* _GEOPATCHJOBS_H */