Simple dx render example.

This commit is contained in:
jmsgrogan 2023-01-05 16:40:27 +00:00
parent 36515556b8
commit e0cad34d55
22 changed files with 339 additions and 60 deletions

View file

@ -19,12 +19,12 @@ public:
AbstractApp* getMainApplication() const override; AbstractApp* getMainApplication() const override;
void run();
AbstractUIInterface* getUiInterface() const override; AbstractUIInterface* getUiInterface() const override;
void setUiInterfaceBackend(UiInterfaceFactory::Backend backend); void setUiInterfaceBackend(UiInterfaceFactory::Backend backend);
void run();
protected: protected:
virtual void initializeViews(); virtual void initializeViews();

View file

@ -48,15 +48,18 @@ void MainApplication::initialize(CommandLineArgsUPtr commandLineArgs, std::uniqu
FileLogger::GetInstance().Open(); FileLogger::GetInstance().Open();
MLOG_INFO("Launched"); MLOG_INFO("Launched");
mDatabaseManager = DatabaseManager::Create(); if (false)
mDatabaseManager->openDatabase(launch_path + "/database.db"); {
MLOG_INFO("Created DB"); mDatabaseManager = DatabaseManager::Create();
mDatabaseManager->openDatabase(launch_path + "/database.db");
MLOG_INFO("Created DB");
mNetworkManager = NetworkManager::Create(); mNetworkManager = NetworkManager::Create();
MLOG_INFO("Created Network Manager"); MLOG_INFO("Created Network Manager");
mAudioManager = AudioManager::Create(); mAudioManager = AudioManager::Create();
MLOG_INFO("Created Audio Manager"); MLOG_INFO("Created Audio Manager");
}
} }
void MainApplication::run() void MainApplication::run()
@ -141,8 +144,16 @@ CommandLineArgs* MainApplication::getCommandLineArgs() const
void MainApplication::shutDown() void MainApplication::shutDown()
{ {
mDatabaseManager->onShutDown(); if (mDatabaseManager)
mNetworkManager->ShutDown(); {
mDatabaseManager->onShutDown();
}
if (mNetworkManager)
{
mNetworkManager->ShutDown();
}
MLOG_INFO("Shut down"); MLOG_INFO("Shut down");
FileLogger::GetInstance().Close(); FileLogger::GetInstance().Close();
} }

View file

@ -7,6 +7,8 @@ list(APPEND geometry_LIB_INCLUDES
Grid.h Grid.h
Grid.cpp Grid.cpp
Line.h Line.h
Linalg.h
Linalg.cpp
Line.cpp Line.cpp
LineSegment.cpp LineSegment.cpp
Path.h Path.h
@ -18,7 +20,9 @@ list(APPEND geometry_LIB_INCLUDES
Rectangle.cpp Rectangle.cpp
Triangle.h Triangle.h
Triangle.cpp Triangle.cpp
Transform.cpp) Transform.cpp
Vector.h
Vector.cpp)
# add the library # add the library

11
src/geometry/Linalg.cpp Normal file
View file

@ -0,0 +1,11 @@
#include "Linalg.h"
double Linalg::dotProduct(const Vector& v0, const Vector& v1)
{
return v0.dotProduct(v1);
}
Vector Linalg::crossProduct(const Vector& v0, const Vector& v1)
{
return v0.crossProduct(v1);
}

10
src/geometry/Linalg.h Normal file
View file

@ -0,0 +1,10 @@
#pragma once
#include "Vector.h"
class Linalg
{
static double dotProduct(const Vector& v0, const Vector& v1);
static Vector crossProduct(const Vector& v0, const Vector& v1);
};

View file

@ -49,12 +49,15 @@ double Point::getZ() const
double Point::getDistance(const Point& point) const double Point::getDistance(const Point& point) const
{ {
return std::sqrt(mX*point.getX() + mY*point.getY() + mZ*point.getZ()); const auto deltaX = getDeltaX(point);
const auto deltaY = getDeltaY(point);
const auto deltaZ = getDeltaZ(point);
return std::sqrt(deltaX* deltaX + deltaY* deltaY + deltaZ* deltaZ);
} }
double Point::getDistance(Point* point) const Vector Point::getDelta(const Point& point) const
{ {
return std::sqrt(mX*point->getX() + mY*point->getY() + mZ*point->getZ()); return Vector(point.mX - mX, point.mY - mY, point.mZ - mZ);
} }
double Point::getDeltaX(const Point& point) const double Point::getDeltaX(const Point& point) const
@ -66,3 +69,22 @@ double Point::getDeltaY(const Point& point) const
{ {
return point.getY() - mY; return point.getY() - mY;
} }
double Point::getDeltaZ(const Point& point) const
{
return point.getZ() - mZ;
}
void Point::scale(double x, double y, double z)
{
mX = x * mX;
mY = y * mY;
mZ = z * mZ;
}
void Point::translate(double x, double y, double z)
{
mX += x;
mY += y;
mZ += z;
}

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "DiscretePoint.h" #include "DiscretePoint.h"
#include "Vector.h"
#include <memory> #include <memory>
#include <cmath> #include <cmath>
@ -27,25 +28,17 @@ public:
double getDistance(const Point& point) const; double getDistance(const Point& point) const;
double getDistance(Point* point) const;
double getDeltaX(const Point& point) const; double getDeltaX(const Point& point) const;
double getDeltaY(const Point& point) const; double getDeltaY(const Point& point) const;
void scale(double x, double y, double z = 1.0) double getDeltaZ(const Point& point) const;
{
mX = x*mX;
mY = y*mY;
mZ = z*mZ;
}
void translate(double x, double y, double z = 0.0) Vector getDelta(const Point& point) const;
{
mX += x; void scale(double x, double y, double z = 1.0);
mY += y;
mZ += z; void translate(double x, double y, double z = 0.0);
}
bool operator==(const Point& rhs) const bool operator==(const Point& rhs) const
{ {

61
src/geometry/Vector.cpp Normal file
View file

@ -0,0 +1,61 @@
#include "Vector.h"
Vector::Vector(double x, double y, double z)
: mX(x),
mY(y),
mZ(z)
{
updateLength();
}
Vector::~Vector()
{
};
double Vector::getX() const
{
return mX;
}
double Vector::getY() const
{
return mY;
}
double Vector::getZ() const
{
return mZ;
}
double Vector::getLength() const
{
return mLength;
}
double Vector::dotProduct(const Vector& v) const
{
return mX * v.mX + mY * v.mY + mZ * v.mZ;
}
Vector Vector::crossProduct(const Vector& v) const
{
return Vector(v.mY * mZ - v.mZ * mY, v.mZ * mX - v.mX * mZ, v.mX * mY - v.mY * mX);
}
Vector Vector::getNormalized() const
{
return Vector(mX / mLength, mY / mLength, mZ / mLength);
}
void Vector::scale(double x, double y, double z)
{
mX = x * mX;
mY = y * mY;
mZ = z * mZ;
updateLength();
}
void Vector::updateLength()
{
mLength = std::sqrt(mX * mX + mY * mY + mZ * mZ);
}

48
src/geometry/Vector.h Normal file
View file

@ -0,0 +1,48 @@
#pragma once
#include <memory>
#include <cmath>
class Vector
{
public:
Vector(double x = 0, double y = 0, double z = 0);
~Vector();
double getX() const;
double getY() const;
double getZ() const;
double getLength() const;
Vector getNormalized() const;
void scale(double x, double y, double z = 1.0);
double dotProduct(const Vector& v) const;
Vector crossProduct(const Vector& v) const;
bool operator==(const Vector& rhs) const
{
return (mX == rhs.mX)
&& (mY == rhs.mY)
&& (mZ == rhs.mZ);
}
bool operator!=(const Vector& rhs) const
{
return !operator==(rhs);
}
private:
void updateLength();
double mLength{ 0 };
double mX{ 0 };
double mY{ 0 };
double mZ{ 0 };
};

View file

@ -5,6 +5,8 @@
#include "DrawingSurface.h" #include "DrawingSurface.h"
#include "TriMesh.h" #include "TriMesh.h"
#include "TriFace.h"
#include "FileLogger.h"
#include <directx/d3dx12.h> #include <directx/d3dx12.h>
@ -26,18 +28,45 @@ void DirectXMesh::update(DrawingContext* context, ID3D12Device* device)
std::vector<float> color = { float(model_color[0]), float(model_color[1]), float(model_color[2]), float(model_color[3]) }; std::vector<float> color = { float(model_color[0]), float(model_color[1]), float(model_color[2]), float(model_color[3]) };
auto transform = mModel->getTransform(); auto transform = mModel->getTransform();
for (const auto& face : dynamic_cast<TriMesh*>(mModel->getMesh())->getFaces())
{
for (const auto& loc : face->getNodeLocations(AbstractFace::Orientation::CW))
{
auto x = loc.getX() * transform.getScaleX() + transform.getLocation().getX();
auto y = loc.getY() * transform.getScaleY() + transform.getLocation().getY();
x = 2 * x - 1;
y = 2 * y - 1;
Vertex vert;
vert.position = DirectX::XMFLOAT3(x, y, 0.0);
vert.color = DirectX::XMFLOAT4(color[0], color[1], color[2], color[3]);
MLOG_INFO("Adding vert: " << x << " | " << y);
mVertexBuffer.push_back(vert);
}
}
/*
for (const auto& node : mModel->getMesh()->getNodes()) for (const auto& node : mModel->getMesh()->getNodes())
{ {
auto x = node->getPoint().getX() * transform.getScaleX() + transform.getLocation().getX(); auto x = node->getPoint().getX() * transform.getScaleX() + transform.getLocation().getX();
x = 2 * x / width - 1.0; //x = 2 * x / width - 1.0;
auto y = node->getPoint().getY() * transform.getScaleY() + transform.getLocation().getY(); auto y = node->getPoint().getY() * transform.getScaleY() + transform.getLocation().getY();
y = 2 * y / height; //y = 2 * y / height;
Vertex vert; Vertex vert;
vert.position = DirectX::XMFLOAT3(x, y, 0.0); vert.position = DirectX::XMFLOAT3(x, y, 0.0);
vert.color = DirectX::XMFLOAT4(color[0], color[1], color[2], color[3]); vert.color = DirectX::XMFLOAT4(color[0], color[1], color[2], color[3]);
MLOG_INFO("Adding vert: " << x << " | " << y);
mVertexBuffer.push_back(vert); mVertexBuffer.push_back(vert);
} }
mIndexBuffer = dynamic_cast<TriMesh*>(mModel->getMesh())->getFaceNodeIds(); */
//mIndexBuffer = dynamic_cast<TriMesh*>(mModel->getMesh())->getFaceNodeIds();
mIndexBuffer = { 0, 1, 2 };
for (auto id : mIndexBuffer)
{
MLOG_INFO("Adding id: " << id);
}
createD3dVertexBuffer(device); createD3dVertexBuffer(device);
createD3dIndexBuffer(device); createD3dIndexBuffer(device);
@ -88,6 +117,7 @@ void DirectXMesh::createD3dIndexBuffer(ID3D12Device* device)
mIndexBufferView.BufferLocation = mD3dIndexBuffer->GetGPUVirtualAddress(); mIndexBufferView.BufferLocation = mD3dIndexBuffer->GetGPUVirtualAddress();
mIndexBufferView.SizeInBytes = buffer_size; mIndexBufferView.SizeInBytes = buffer_size;
mIndexBufferView.Format = DXGI_FORMAT_R16_UINT;
} }
void DirectXMesh::uploadIndexBuffer(unsigned char* pBuffer) const void DirectXMesh::uploadIndexBuffer(unsigned char* pBuffer) const

View file

@ -89,9 +89,10 @@ void DirectXMeshPainter::updateCommandList(ID3D12GraphicsCommandList* commandLis
for (const auto& mesh : mDxMeshes) for (const auto& mesh : mDxMeshes)
{ {
commandList->IASetVertexBuffers(0, 1, &mesh->getVertBufferView());
commandList->IASetIndexBuffer(&mesh->getIndexBufferView()); commandList->IASetIndexBuffer(&mesh->getIndexBufferView());
commandList->DrawInstanced(3, 1, 0, 0); commandList->IASetVertexBuffers(0, 1, &mesh->getVertBufferView());
commandList->DrawInstanced(mesh->getVertBufferView().SizeInBytes/ mesh->getVertBufferView().StrideInBytes, 1, 0, 0);
//commandList->DrawIndexedInstanced(3, 1, 0, 0, 0);
} }
} }

View file

@ -12,6 +12,13 @@ class Edge;
class AbstractFace class AbstractFace
{ {
public: public:
enum class Orientation
{
CW,
CCW
};
AbstractFace(unsigned id=0); AbstractFace(unsigned id=0);
virtual ~AbstractFace(); virtual ~AbstractFace();
@ -32,7 +39,7 @@ public:
virtual std::vector<unsigned> getEdgeIds() const = 0; virtual std::vector<unsigned> getEdgeIds() const = 0;
virtual std::vector<Point> getNodeLocations() const = 0; virtual std::vector<Point> getNodeLocations(Orientation orientation = Orientation::CCW) const = 0;
protected: protected:
unsigned mId{0}; unsigned mId{0};

View file

@ -1,16 +1,29 @@
list(APPEND mesh_LIB_INCLUDES list(APPEND mesh_LIB_INCLUDES
AbstractMesh.cpp AbstractMesh.cpp
AbstractMesh.h
Edge.cpp Edge.cpp
Edge.h
AbstractFace.cpp AbstractFace.cpp
AbstractFace.h
QuadFace.cpp QuadFace.cpp
QuadFace.h
TriFace.cpp TriFace.cpp
TriFace.h
Node.cpp Node.cpp
Node.h
QuadMesh.cpp QuadMesh.cpp
QuadMesh.h
TriMesh.cpp TriMesh.cpp
TriMesh.h
FaceMesh.cpp FaceMesh.cpp
FaceMesh.h
LineMesh.cpp LineMesh.cpp
LineMesh.h
MeshPrimitives.cpp MeshPrimitives.cpp
MeshBuilder.cpp) MeshPrimitives.h
MeshBuilder.cpp
MeshBuilder.h
)
# add the library # add the library

View file

@ -75,7 +75,34 @@ void TriFace::associateWidthEdges()
mEdge2->associateFace(mId); mEdge2->associateFace(mId);
} }
std::vector<Point> TriFace::getNodeLocations() const std::vector<Point> TriFace::getNodeLocations(Orientation orientation) const
{ {
return {mEdge0->getNode0()->getPoint(), mEdge0->getNode1()->getPoint(), mEdge1->getNode1()->getPoint()}; if (orientation != getOrientation())
{
return { mEdge0->getNode0()->getPoint(), mEdge0->getNode1()->getPoint(), mEdge1->getNode1()->getPoint() };
}
else
{
return { mEdge0->getNode0()->getPoint(), mEdge1->getNode1()->getPoint(), mEdge0->getNode1()->getPoint() };
}
}
Vector TriFace::getNormal() const
{
auto v0 = mEdge0->getNode0()->getPoint().getDelta(mEdge0->getNode1()->getPoint());
auto v1 = mEdge0->getNode0()->getPoint().getDelta(mEdge1->getNode1()->getPoint());
return v0.crossProduct(v1).getNormalized();
}
AbstractFace::Orientation TriFace::getOrientation() const
{
Vector z_norm(0, 0, 1);
if (z_norm.dotProduct(getNormal()) < 0.0)
{
return Orientation::CW;
}
else
{
return Orientation::CCW;
}
} }

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "AbstractFace.h" #include "AbstractFace.h"
#include "Vector.h"
class Edge; class Edge;
@ -26,7 +27,11 @@ public:
unsigned getEdge2Id () const; unsigned getEdge2Id () const;
std::vector<unsigned> getEdgeIds() const override; std::vector<unsigned> getEdgeIds() const override;
std::vector<Point> getNodeLocations() const override; std::vector<Point> getNodeLocations(Orientation orientation = Orientation::CCW) const override;
Vector getNormal() const;
AbstractFace::Orientation getOrientation() const;
private: private:
Edge* mEdge0{nullptr}; Edge* mEdge0{nullptr};

View file

@ -1,11 +1,16 @@
#include "TestCase.h" #include "TestCase.h"
#include "TestCaseRunner.h" #include "TestCaseRunner.h"
#include "MainApplication.h" #include "TestUiApplication.h"
#include "GuiApplication.h"
#include "TestFramework.h" #include "TestFramework.h"
#include "DesktopManager.h"
#include "MeshPrimitives.h"
#include "MeshNode.h"
#include "Scene.h"
#include "Widget.h"
#include <memory> #include <memory>
#include <string> #include <string>
#include <iostream> #include <iostream>
@ -14,5 +19,16 @@ TEST_CASE(TestDirectXRendering, "graphics")
{ {
auto gui_app = TestCaseRunner::getInstance().getTestApplication(); auto gui_app = TestCaseRunner::getInstance().getTestApplication();
auto drawing_context = gui_app->getDesktopManager()->getWindowManager()->getMainWindow();
auto scene = drawing_context->getScene();
auto mesh = MeshPrimitives::buildRectangleAsTriMesh();
auto mesh_node = std::make_unique<MeshNode>(DiscretePoint(0, 0));
mesh_node->setMesh(mesh.get());
scene->addNode(mesh_node.get());
scene->update(nullptr);
gui_app->run(); gui_app->run();
}; };

View file

@ -4,10 +4,12 @@ add_library(test_utils STATIC
TestCaseRunner.h TestCaseRunner.h
TestFramework.h TestFramework.h
TestCaseRunner.cpp TestCaseRunner.cpp
TestUiApplication.h
TestUiApplication.cpp
) )
target_include_directories(test_utils PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(test_utils PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(test_utils core) target_link_libraries(test_utils core client)
set_property(TARGET test_utils PROPERTY FOLDER test) set_property(TARGET test_utils PROPERTY FOLDER test)
configure_file(TestDataLocations.h.in TestDataLocations.h) configure_file(TestDataLocations.h.in TestDataLocations.h)

View file

@ -1,6 +1,7 @@
#include "TestCaseRunner.h" #include "TestCaseRunner.h"
#include "FileLogger.h" #include "FileLogger.h"
#include "TestUiApplication.h"
#include <vector> #include <vector>
#include <iostream> #include <iostream>
@ -18,12 +19,12 @@ TestCaseRunner::~TestCaseRunner()
} }
GuiApplication* TestCaseRunner::getTestApplication() TestUiApplication* TestCaseRunner::getTestApplication()
{ {
return mTestApplication; return mTestApplication;
} }
void TestCaseRunner::setTestApplication(GuiApplication* app) void TestCaseRunner::setTestApplication(TestUiApplication* app)
{ {
mTestApplication = app; mTestApplication = app;
} }

View file

@ -5,7 +5,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
class GuiApplication; class TestUiApplication;
class TestCaseRunner class TestCaseRunner
{ {
@ -16,7 +16,7 @@ public:
~TestCaseRunner(); ~TestCaseRunner();
GuiApplication* getTestApplication(); TestUiApplication* getTestApplication();
void addTestCase(const std::string& label, const std::string& tag, TestCase::TestCaseFunction func); void addTestCase(const std::string& label, const std::string& tag, TestCase::TestCaseFunction func);
@ -24,10 +24,10 @@ public:
bool run(const std::vector<std::string>& args); bool run(const std::vector<std::string>& args);
void setTestApplication(GuiApplication* app); void setTestApplication(TestUiApplication* app);
private: private:
GuiApplication* mTestApplication{ nullptr }; TestUiApplication* mTestApplication{ nullptr };
std::vector<std::string> mFailingTests; std::vector<std::string> mFailingTests;
static bool sLastTestFailed; static bool sLastTestFailed;
static std::string sFailureLine; static std::string sFailureLine;

View file

@ -0,0 +1,14 @@
#include "TestUiApplication.h"
#include "MainApplication.h"
TestUiApplication::TestUiApplication(std::unique_ptr<CommandLineArgs> args, std::unique_ptr<MainApplication> mainApp)
: GuiApplication(std::move(args), std::move(mainApp))
{
}
DesktopManager* TestUiApplication::getDesktopManager() const
{
return mDesktopManager.get();
}

View file

@ -0,0 +1,13 @@
#pragma once
#include "GuiApplication.h"
#include <memory>
class TestUiApplication : public GuiApplication
{
public:
TestUiApplication(std::unique_ptr<CommandLineArgs> args = nullptr, std::unique_ptr<MainApplication> mainApp = nullptr);
DesktopManager* getDesktopManager() const;
};

View file

@ -2,7 +2,7 @@
#include "CommandLineArgs.h" #include "CommandLineArgs.h"
#include "MainApplication.h" #include "MainApplication.h"
#include "GuiApplication.h" #include "TestUiApplication.h"
#include "Widget.h" #include "Widget.h"
#ifdef _WIN32 #ifdef _WIN32
@ -12,16 +12,6 @@
#include <iostream> #include <iostream>
class TestApp : public GuiApplication
{
public:
TestApp(std::unique_ptr<CommandLineArgs> args = nullptr, std::unique_ptr<MainApplication> mainApp = nullptr)
: GuiApplication(std::move(args), std::move(mainApp))
{
}
};
#ifdef _WIN32 #ifdef _WIN32
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{ {
@ -41,7 +31,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine
main_app->initialize(std::move(args), std::move(applicationContext)); main_app->initialize(std::move(args), std::move(applicationContext));
auto gui_app = std::make_unique<TestApp>(nullptr, std::move(main_app)); auto gui_app = std::make_unique<TestUiApplication>(nullptr, std::move(main_app));
#else #else
int main(int argc, char *argv[]) int main(int argc, char *argv[])