Skip to content
Permalink
Browse files

Add dxDrawWiredSphere function (#1052)

  • Loading branch information...
CrosRoad95 authored and qaisjp committed Oct 22, 2019
1 parent 60df598 commit 40ed8b59f58a499e7ff2d8baedf9cd30b93a69ee
@@ -2354,3 +2354,134 @@ bool CGraphics::CopyDataFromSurface(IDirect3DSurface9* pSurface, CBuffer& outBuf

return true;
}


namespace
{
//
// CClientColSphere helpers
//

// Used in CreateSphereFaces
struct SFace
{
SFace(const CVector& a, const CVector& b, const CVector& c) : a(a), b(b), c(c) {}
CVector a, b, c;
};

//
// Create faces for a sphere
//
void CreateSphereFaces(std::vector<SFace>& faceList, int iIterations)
{
int numFaces = (int)(pow(4.0, iIterations) * 8);
faceList.clear();
faceList.reserve(numFaces);

// Initial octahedron
static SFixedArray<CVector, 6> vecPoints = {CVector(0, 0, 1), CVector(0, 0, -1), CVector(-1, -1, 0),
CVector(1, -1, 0), CVector(1, 1, 0), CVector(-1, 1, 0)};
static const SFixedArray<WORD, 24> indices = {0, 3, 4, 0, 4, 5, 0, 5, 2, 0, 2, 3, 1, 4, 3, 1, 5, 4, 1, 2, 5, 1, 3, 2};

for (uint i = 0; i < NUMELMS(vecPoints); i++)
vecPoints[i].Normalize();

for (uint i = 0; i < NUMELMS(indices); i += 3)
faceList.push_back(SFace(vecPoints[indices[i]], vecPoints[indices[i + 1]], vecPoints[indices[i + 2]]));

// For each iteration
while (iIterations--)
{
// Divide each face into 4
for (int i = faceList.size() - 1; i >= 0; i--)
{
// Get the three face points
CVector a = faceList[i].a;
CVector b = faceList[i].b;
CVector c = faceList[i].c;

// Make three inner points
CVector a2 = (a + b) * 0.5f;
CVector b2 = (b + c) * 0.5f;
CVector c2 = (c + a) * 0.5f;

// Keep points to the edge of the unit sphere
a2.Normalize();
b2.Normalize();
c2.Normalize();

// Replace the original face with the first sub-face
faceList[i] = SFace(a2, b2, c2);

// Add the three other sub-faces to the end of the list
faceList.push_back(SFace(a, a2, c2));
faceList.push_back(SFace(b, a2, b2));
faceList.push_back(SFace(c, b2, c2));
}
}
}

//
// For holding the lines of an optimized wireframe sphere
//
struct SWireModel
{
std::vector<CVector> vertexList;

// Add a line if it is unique
void AddLine(const CVector& from, const CVector& to)
{
// Conform order
if (from.fX > to.fX || (from.fX == to.fX && from.fY > to.fY || (from.fY == to.fY && from.fZ > to.fZ)))
return AddLine(to, from);

// Find existing line
for (int i = 0; i < (int)vertexList.size() - 1; i += 2)
if ((from - vertexList[i]).LengthSquared() < 0.00001f)
if ((to - vertexList[i + 1]).LengthSquared() < 0.00001f)
return; // Duplicated

// Add new line
vertexList.push_back(from);
vertexList.push_back(to);
}
};

const SWireModel& GetSphereWireModel(int iterations)
{
static std::map<uint, SWireModel> wireModelMap;

// Find existing
SWireModel* pWireModel = MapFind(wireModelMap, iterations);
if (pWireModel)
return *pWireModel;

// Add new
MapSet(wireModelMap, iterations, SWireModel());
SWireModel& wireModel = *MapFind(wireModelMap, iterations);

std::vector<SFace> faceList;
CreateSphereFaces(faceList, iterations);

// Create big vertex/line list
for (uint i = 0; i < faceList.size(); i++)
{
wireModel.AddLine(faceList[i].a, faceList[i].b);
wireModel.AddLine(faceList[i].b, faceList[i].c);
wireModel.AddLine(faceList[i].c, faceList[i].a);
}
return wireModel;
}
} // namespace WireShpere

void CGraphics::DrawWiredSphere(CVector vecPosition, float fRadius, SColorARGB color, float fLineWidth, int iterations)
{
const SWireModel& model = GetSphereWireModel(iterations);

for (uint i = 0; i < model.vertexList.size(); i += 2)
{
const CVector& vecBegin = model.vertexList[i] * fRadius + vecPosition;
const CVector& vecEnd = model.vertexList[i + 1] * fRadius + vecPosition;
DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false);
}
}
@@ -157,6 +157,9 @@ class CGraphics : public CGraphicsInterface, public CSingleton<CGraphics>
void DrawCircleQueued(float fX, float fY, float fRadius, float fStartAngle, float fStopAngle, unsigned long ulColor, unsigned long ulColorCenter,
short siSegments, float fRatio, bool bPostGUI);

void DrawWiredSphere(CVector vecPosition, float radius, SColorARGB color, float fLineWidth, int iterations);


bool IsValidPrimitiveSize (int iNumVertives, D3DPRIMITIVETYPE eType);

void OnChangingRenderTarget(uint uiNewViewportSizeX, uint uiNewViewportSizeY);
@@ -10,124 +10,6 @@

#include <StdInc.h>

namespace
{
//
// CClientColSphere helpers
//

// Used in CreateSphereFaces
struct SFace
{
SFace(const CVector& a, const CVector& b, const CVector& c) : a(a), b(b), c(c) {}
CVector a, b, c;
};

//
// Create faces for a sphere
//
void CreateSphereFaces(std::vector<SFace>& faceList, int iIterations)
{
int numFaces = (int)(pow(4.0, iIterations) * 8);
faceList.clear();
faceList.reserve(numFaces);

// Initial octahedron
static SFixedArray<CVector, 6> vecPoints = {CVector(0, 0, 1), CVector(0, 0, -1), CVector(-1, -1, 0),
CVector(1, -1, 0), CVector(1, 1, 0), CVector(-1, 1, 0)};
static const SFixedArray<WORD, 24> indices = {0, 3, 4, 0, 4, 5, 0, 5, 2, 0, 2, 3, 1, 4, 3, 1, 5, 4, 1, 2, 5, 1, 3, 2};

for (uint i = 0; i < NUMELMS(vecPoints); i++)
vecPoints[i].Normalize();

for (uint i = 0; i < NUMELMS(indices); i += 3)
faceList.push_back(SFace(vecPoints[indices[i]], vecPoints[indices[i + 1]], vecPoints[indices[i + 2]]));

// For each iteration
while (iIterations--)
{
// Divide each face into 4
for (int i = faceList.size() - 1; i >= 0; i--)
{
// Get the three face points
CVector a = faceList[i].a;
CVector b = faceList[i].b;
CVector c = faceList[i].c;

// Make three inner points
CVector a2 = (a + b) * 0.5f;
CVector b2 = (b + c) * 0.5f;
CVector c2 = (c + a) * 0.5f;

// Keep points to the edge of the unit sphere
a2.Normalize();
b2.Normalize();
c2.Normalize();

// Replace the original face with the first sub-face
faceList[i] = SFace(a2, b2, c2);

// Add the three other sub-faces to the end of the list
faceList.push_back(SFace(a, a2, c2));
faceList.push_back(SFace(b, a2, b2));
faceList.push_back(SFace(c, b2, c2));
}
}
}

//
// For holding the lines of an optimized wireframe sphere
//
struct SWireModel
{
std::vector<CVector> vertexList;

// Add a line if it is unique
void AddLine(const CVector& from, const CVector& to)
{
// Conform order
if (from.fX > to.fX || (from.fX == to.fX && from.fY > to.fY || (from.fY == to.fY && from.fZ > to.fZ)))
return AddLine(to, from);

// Find existing line
for (int i = 0; i < (int)vertexList.size() - 1; i += 2)
if ((from - vertexList[i]).LengthSquared() < 0.00001f)
if ((to - vertexList[i + 1]).LengthSquared() < 0.00001f)
return; // Duplicated

// Add new line
vertexList.push_back(from);
vertexList.push_back(to);
}
};

const SWireModel& GetSphereWireModel(int iterations)
{
static std::map<uint, SWireModel> wireModelMap;

// Find existing
SWireModel* pWireModel = MapFind(wireModelMap, iterations);
if (pWireModel)
return *pWireModel;

// Add new
MapSet(wireModelMap, iterations, SWireModel());
SWireModel& wireModel = *MapFind(wireModelMap, iterations);

std::vector<SFace> faceList;
CreateSphereFaces(faceList, iterations);

// Create big vertex/line list
for (uint i = 0; i < faceList.size(); i++)
{
wireModel.AddLine(faceList[i].a, faceList[i].b);
wireModel.AddLine(faceList[i].b, faceList[i].c);
wireModel.AddLine(faceList[i].c, faceList[i].a);
}
return wireModel;
}
} // namespace

CClientColSphere::CClientColSphere(CClientManager* pManager, ElementID ID, const CVector& vecPosition, float fRadius)
: ClassInit(this), CClientColShape(pManager, ID)
{
@@ -158,12 +40,5 @@ void CClientColSphere::DebugRender(const CVector& vecPosition, float fDrawRadius

uint iterations = Clamp(1, Round(pow(m_fRadius, 0.25f) * 0.75f), 4);

const SWireModel& model = GetSphereWireModel(iterations);

for (uint i = 0; i < model.vertexList.size(); i += 2)
{
const CVector& vecBegin = model.vertexList[i] * m_fRadius + m_vecPosition;
const CVector& vecEnd = model.vertexList[i + 1] * m_fRadius + m_vecPosition;
pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false);
}
pGraphics->DrawWiredSphere(m_vecPosition, m_fRadius, color, fLineWidth, iterations);
}
@@ -29,6 +29,7 @@ void CLuaDrawingDefs::LoadFunctions()
{"dxDrawPrimitive3D", DxDrawPrimitive3D},
{"dxDrawMaterialPrimitive", DxDrawMaterialPrimitive},
{"dxDrawMaterialPrimitive3D", DxDrawMaterialPrimitive3D},
{"dxDrawWiredSphere", DxDrawWiredSphere},
{"dxGetTextWidth", DxGetTextWidth},
{"dxGetFontHeight", DxGetFontHeight},
{"dxCreateFont", DxCreateFont},
@@ -1972,3 +1973,42 @@ int CLuaDrawingDefs::DxSetTextureEdge(lua_State* luaVM)
lua_pushboolean(luaVM, false);
return 1;
}

int CLuaDrawingDefs::DxDrawWiredSphere(lua_State* luaVM)
{
// bool dxDrawWiredSphere( float x, float y, float z, float radius, color theColor, float fLineWidth, uint iterations )
CVector vecPosition;
float fRadius;
SColorARGB color(64, 255, 0, 0);
float fLineWidth = 1;
uint uiIterations = 1;
CScriptArgReader argStream(luaVM);

CGraphicsInterface* pGraphics = g_pCore->GetGraphics();

argStream.ReadVector3D(vecPosition);
argStream.ReadNumber(fRadius);
argStream.ReadColor(color, SColorARGB(64, 255, 0, 0));
argStream.ReadNumber(fLineWidth, 1);
argStream.ReadNumber(uiIterations, 1);

if (!argStream.HasErrors())
{
// Greater than 4, crash the game
if (uiIterations >= 1 && uiIterations <= 4)
{
pGraphics->DrawWiredSphere(vecPosition, fRadius, color, fLineWidth, uiIterations);
lua_pushboolean(luaVM, true);
return 1;
}

argStream.SetCustomError("Iterations must be between 1 and 4");
m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage());
}
else
m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage());

// Failed
lua_pushboolean(luaVM, false);
return 1;
}
@@ -31,6 +31,7 @@ class CLuaDrawingDefs : public CLuaDefs
LUA_DECLARE(DxDrawMaterialPrimitive);
LUA_DECLARE(DxDrawPrimitive3D);
LUA_DECLARE(DxDrawMaterialPrimitive3D);
LUA_DECLARE(DxDrawWiredSphere);
LUA_DECLARE_OOP(DxGetTextWidth);
LUA_DECLARE_OOP(DxGetFontHeight);
LUA_DECLARE(DxCreateFont);
@@ -169,6 +169,8 @@ class CGraphicsInterface
virtual void DrawCircleQueued(float fX, float fY, float fRadius, float fStartAngle, float fStopAngle, unsigned long ulColor, unsigned long ulColorCenter,
short siSegments, float fRatio, bool bPostGUI) = 0;

virtual void DrawWiredSphere(CVector vecPosition, float fRadius, SColorARGB color, float fLineWidth, int iterations) = 0;

virtual bool IsValidPrimitiveSize (int iNumVertives, D3DPRIMITIVETYPE eType) = 0;

// Subsystems

0 comments on commit 40ed8b5

Please sign in to comment.
You can’t perform that action at this time.