응애맘마조
230721 강의 본문
임의의 노드에 노드를 위치시키고 간선으로 연결시키는 것을 강의했습니다. 동시에 과제였습니다.
#pragma once
class DiNode
{
friend class Di;
private:
int id;
bool find; //검색한적 있는가?
int prev; //내가 갱신된 노드
public:
unordered_map< int, float> linkedList;
Vector3 pos;
float cost; //현재까지 비용
DiNode(int id)
{
this->id = id;
}
void Link(int node, float cost)
{
linkedList[node] = cost;
}
void Reset()
{
prev = -1;
cost = FLT_MAX;
find = false;
}
};
class DiNodeCompare
{
public:
bool operator()(DiNode*& a, DiNode*& b)
{
return a->cost > b->cost;
}
};
class Di
{
public:
unordered_map< int, DiNode*> list;
string file = " ";
int GetNode(Vector3 pos)
{
for (auto it = list.begin(); it != list.end(); it++)
{
if ((it->second->pos - pos).Length() < 4)
{
return it->first;
}
}
return 0;
}
DiNode*& AddNode(Vector3 pos)
{
int number = 1;
for (auto it = list.begin(); it != list.end(); it++)
{
if (list.find(number) == list.end())
{
break;
}
number++;
}
DiNode* temp = new DiNode(number);
temp->pos = pos;
list[number] = temp;
return temp;
}
bool PopNode(int str)
{
auto it = list.find(str);
if (it != list.end())
{
for (auto it2 = it->second->linkedList.begin();
it2 != it->second->linkedList.end(); it2++)
{
list[it2->first]->linkedList.erase(str);
}
delete it->second;
list.erase(str);
return true;
}
return false;
}
void LinkNode(int str1, int str2)
{
if (str1 == str2) return;
Vector3 temp = list[str1]->pos - list[str2]->pos;
float dis = temp.Length();
list[str1]->Link(str2, dis);
list[str2]->Link(str1, dis);
}
std::list<Vector3> PathFinding(int from, int to)
{
//노드비용을 초기화
for (auto it = list.begin(); it != list.end(); it++)
{
it->second->Reset();
}
//우선순위큐
priority_queue<DiNode*, vector<DiNode*>, DiNodeCompare>
Searchlist;
Searchlist.push(list[from]);
list[from]->cost = 0;
list[from]->find = true;
while (not Searchlist.empty())
{
DiNode* top = Searchlist.top();
Searchlist.pop();
for (auto it = top->linkedList.begin();
it != top->linkedList.end(); it++)
{
//기존노드의 비용 갱신
if (list[it->first]->cost > top->cost + it->second)
{
list[it->first]->cost = top->cost + it->second;
list[it->first]->prev = top->id;
if (not list[it->first]->find)
{
Searchlist.push(list[it->first]);
list[it->first]->find = true;
}
}
}
}
std::list<Vector3> way;
DiNode* iter = list[to];
way.push_back(iter->pos);
while (1)
{
iter = list[iter->prev];
way.push_back(iter->pos);
if (iter->id == from)
{
break;
}
}
return way;
}
};
class Terrain : public Actor
{
struct InputDesc
{
UINT index;
Vector3 v0, v1, v2;
};
struct OutputDesc
{
int picked;
float u, v, distance;
};
struct RayDesc
{
Vector3 position;
float size;
Vector3 direction;
float padding;
};
static ID3D11ComputeShader* computeShader;
static class Actor* Node; //구 모양
static class Actor* Line; //선 모양
public:
static void CreateStaticMember();
static void DeleteStaticMember();
static Terrain* Create(string Name = "Terrain", int terrainSize = 257, float uvScale = 1.0f);
private:
//compute Input
InputDesc* inputArray;
ID3D11Resource* input;
ID3D11ShaderResourceView* srv = nullptr;
//compute Output
OutputDesc* outputArray;
ID3D11Resource* output;
ID3D11UnorderedAccessView* uav;
//copy용
ID3D11Resource* result;
//ray
RayDesc ray;
ID3D11Buffer* rayBuffer;
public:
Di di;
Terrain(string Name);
float uvScale;
int triSize;
bool showNode;
void RenderDetail();
void UpdateMeshUv();
void UpdateMeshNormal();
void CreateMesh(int Size = 257);
//CS
void CreateStructuredBuffer();
void DeleteStructuredBuffer();
bool ComPutePicking(Ray WRay, OUT Vector3& HitPoint);
void Render() override;
std::list<Vector3> PathFinding(int from, int to);
};
#include "framework.h"
ID3D11ComputeShader* Terrain::computeShader = nullptr;
Actor* Terrain::Node = nullptr;
Actor* Terrain::Line = nullptr;
void Terrain::CreateStaticMember()
{
Node = Actor::Create();
Node->LoadFile("Sphere.xml");
Line = Actor::Create();
Line->LoadFile("Line.xml");
ID3D10Blob* CsBlob;
wstring path = L"../Shaders/ComputeShader.hlsl";
DWORD flags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_DEBUG;
D3DCompileFromFile(path.c_str(), nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
"CS", "cs_5_0", flags, 0, &CsBlob, nullptr);
D3D->GetDevice()->CreateComputeShader(CsBlob->GetBufferPointer(), CsBlob->GetBufferSize(),
nullptr, &computeShader);
}
void Terrain::DeleteStaticMember()
{
SafeRelease(computeShader);
}
Terrain* Terrain::Create(string Name, int terrainSize, float uvScale)
{
Terrain* result = new Terrain(Name);
result->uvScale = uvScale;
result->triSize = (terrainSize - 1) * (terrainSize - 1) * 2;
result->shader = RESOURCE->shaders.Load("5.Cube.hlsl");
result->CreateMesh(terrainSize);
result->material = new Material();
result->material->normalMap = RESOURCE->textures.Load("20000001.png");
result->material->ambient.w = 1.0f;
return result;
}
Terrain::Terrain(string Name)
: Actor()
{
type = ObType::Terrain;
name = Name;
uvScale = 1.0f;
showNode = false;
}
void Terrain::CreateMesh(int Size)
{
VertexTerrain* vertices;
UINT* indices;
UINT vertexCount;
UINT indexCount;
vector<VertexTerrain> VecVertex;
vector<UINT> Vecindex;
triSize = (Size - 1) * (Size - 1) * 2;
float half = Size * 0.5f;
for (int z = 0; z < Size; z++)
{
for (int x = 0; x < Size; x++)
{
//배열에 들어갈 인덱스
int Index = (z * Size) + x;
float _x = x - half;
float _z = -z + half;
float _y = 0.0f;
float _u = float(x) * uvScale / float(Size - 1);
float _v = float(z) * uvScale / float(Size - 1);
VertexTerrain temp;
temp.uv = Vector2(_u, _v);
temp.position = Vector3(_x, _y, _z);
temp.weights.x = 1.0f;
temp.normal = Vector3(0, 1, 0);
VecVertex.push_back(temp);
}
}
vertexCount = (UINT)VecVertex.size();
vertices = new VertexTerrain[vertexCount];
for (int z = 0; z < Size - 1; z++)
{
for (int x = 0; x < Size - 1; x++)
{
//Vecindex.push_back(z* MaxZ + x);
UINT Index = z * Size + x;
//0
Vecindex.push_back(Index);
//1
Vecindex.push_back(Index + 1);
//2
Vecindex.push_back(Index + Size + 1);
//0
Vecindex.push_back(Index);
//1
Vecindex.push_back(Index + Size + 1);
//2
Vecindex.push_back(Index + Size);
}
}
indexCount = (UINT)Vecindex.size();
indices = new UINT[indexCount];
copy(VecVertex.begin(), VecVertex.end(),
stdext::checked_array_iterator<VertexTerrain*>(vertices, vertexCount));
copy(Vecindex.begin(), Vecindex.end(),
stdext::checked_array_iterator<UINT*>(indices, indexCount));
SafeReset(mesh);
mesh = make_shared<Mesh>(vertices, vertexCount, indices,
indexCount, VertexType::TERRAIN);
if (srv)
{
DeleteStructuredBuffer();
CreateStructuredBuffer();
}
}
void Terrain::UpdateMeshUv()
{
VertexTerrain* vertices = (VertexTerrain*)mesh->vertices;
int terrainSize = (int)sqrt(mesh->vertexCount);
for (int z = 0; z < terrainSize; z++)
{
for (int x = 0; x < terrainSize; x++)
{
//배열에 들어갈 인덱스
float _u = float(x) * uvScale / float(terrainSize - 1);
float _v = float(z) * uvScale / float(terrainSize - 1);
vertices[z * terrainSize + x].uv = Vector2(_u, _v);
}
}
mesh->Update();
}
void Terrain::UpdateMeshNormal()
{
VertexTerrain* vertices = (VertexTerrain*)mesh->vertices;
for (UINT i = 0; i < mesh->vertexCount; i++)
{
vertices[i].normal = Vector3();
}
//삼각형 갯수만큼 반복
for (UINT i = 0; i < mesh->indexCount / 3; i++)
{
//하나의 삼각형
UINT index0 = mesh->indices[i * 3 + 0];
UINT index1 = mesh->indices[i * 3 + 1];
UINT index2 = mesh->indices[i * 3 + 2];
Vector3 v0 = vertices[index0].position;
Vector3 v1 = vertices[index1].position;
Vector3 v2 = vertices[index2].position;
Vector3 A = v1 - v0;
Vector3 B = v2 - v0;
Vector3 normal = A.Cross(B);
vertices[index0].normal += normal;
vertices[index1].normal += normal;
vertices[index2].normal += normal;
}
mesh->Update();
}
void Terrain::CreateStructuredBuffer()
{
//삼각형 단위
inputArray = new InputDesc[triSize];
for (UINT i = 0; i < triSize; i++)
{
UINT index0 = mesh->indices[i * 3 + 0];
UINT index1 = mesh->indices[i * 3 + 1];
UINT index2 = mesh->indices[i * 3 + 2];
inputArray[i].v0 = ((VertexTerrain*)(mesh->vertices))[index0].position;
inputArray[i].v1 = ((VertexTerrain*)(mesh->vertices))[index1].position;
inputArray[i].v2 = ((VertexTerrain*)(mesh->vertices))[index2].position;
inputArray[i].index = i;
}
//삼각형 단위
outputArray = new OutputDesc[triSize];
//input
{
ID3D11Buffer* buffer;
D3D11_BUFFER_DESC desc = {};
desc.Usage = D3D11_USAGE_DEFAULT;
desc.ByteWidth = sizeof(InputDesc) * triSize;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
desc.StructureByteStride = sizeof(InputDesc);
D3D11_SUBRESOURCE_DATA initData = {};
initData.pSysMem = inputArray;
D3D->GetDevice()->CreateBuffer(&desc, &initData, &buffer);
input = (ID3D11Resource*)buffer;
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
srvDesc.BufferEx.FirstElement = 0;
srvDesc.BufferEx.NumElements = triSize;
//srv
D3D->GetDevice()->CreateShaderResourceView(buffer, &srvDesc, &srv);
}
//output
{
ID3D11Buffer* buffer;
D3D11_BUFFER_DESC desc = {};
desc.Usage = D3D11_USAGE_DEFAULT;
desc.ByteWidth = sizeof(OutputDesc) * triSize;
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS;
desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
desc.StructureByteStride = sizeof(OutputDesc);
D3D->GetDevice()->CreateBuffer(&desc, nullptr, &buffer);
//ID3D11Resource
output = (ID3D11Resource*)buffer;
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
uavDesc.Buffer.FirstElement = 0;
uavDesc.Buffer.NumElements = triSize;
//uav
D3D->GetDevice()->CreateUnorderedAccessView(buffer, &uavDesc, &uav);
}
//result read
{
ID3D11Buffer* buffer;
D3D11_BUFFER_DESC desc = {};
((ID3D11Buffer*)output)->GetDesc(&desc);
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.MiscFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
D3D->GetDevice()->CreateBuffer(&desc, nullptr, &buffer);
result = (ID3D11Resource*)buffer;
}
{
D3D11_BUFFER_DESC desc = { 0 };
desc.Usage = D3D11_USAGE_DEFAULT;
desc.ByteWidth = sizeof(RayDesc);
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
HRESULT hr = D3D->GetDevice()->CreateBuffer(&desc, NULL, &rayBuffer);
assert(SUCCEEDED(hr));
}
}
void Terrain::DeleteStructuredBuffer()
{
input->Release();
srv->Release();
output->Release();
uav->Release();
result->Release();
rayBuffer->Release();
delete[] inputArray;
delete[] outputArray;
}
bool Terrain::ComPutePicking(Ray WRay, OUT Vector3& HitPoint)
{
//쉐이더부터 준비
D3D->GetDC()->CSSetShader(computeShader, 0, 0);
//raybuffer binding
ray.position = WRay.position;
ray.direction = WRay.direction;
ray.size = (float)triSize;//삼각형갯수
Matrix inverse = W.Invert();
ray.direction = Vector3::TransformNormal(ray.direction, inverse);
ray.direction.Normalize();
ray.position = Vector3::Transform(ray.position, inverse);
//트랜스폼한 Ray를 상수버퍼로 바인딩
D3D->GetDC()->UpdateSubresource(rayBuffer, 0, NULL, &ray, 0, 0);
D3D->GetDC()->CSSetConstantBuffers(0, 1, &rayBuffer);
//input binding
D3D->GetDC()->CSSetShaderResources(0, 1, &srv);
//output binding
D3D->GetDC()->CSSetUnorderedAccessViews(0, 1, &uav, nullptr);
UINT x = (UINT)ceil((float)triSize / 1024.0f);
D3D->GetDC()->Dispatch(x, 1, 1);
//동기화
//gpu -> cpu 복사
D3D->GetDC()->CopyResource(result, output);
D3D11_MAPPED_SUBRESOURCE subResource;
D3D->GetDC()->Map(result, 0, D3D11_MAP_READ, 0, &subResource);
memcpy(outputArray, subResource.pData, sizeof(OutputDesc) * triSize);
D3D->GetDC()->Unmap(result, 0);
float minDistance = FLT_MAX;
int minIndex = -1;
for (int i = 0; i < triSize; i++)
{
OutputDesc temp = outputArray[i];
if (temp.picked)
{
if (minDistance > temp.distance)
{
minDistance = temp.distance;
minIndex = i;
}
}
}
if (minIndex >= 0)
{
HitPoint = ray.position + ray.direction
* minDistance;
HitPoint = Vector3::Transform(HitPoint, W);
return true;
}
return false;
}
void Terrain::Render()
{
Actor::Render();
//다익스트라 노드 렌더링
if (showNode)
{
DEPTH->Set(false);
for (auto it = di.list.begin(); it != di.list.end(); it++)
{
Node->SetLocalPos(it->second->pos);
Node->Update();
//local * srt;
Node->W *= W;
Node->W = S.Invert() * Node->W;
Node->Render();
for (auto it2 = it->second->linkedList.begin();
it2 != it->second->linkedList.end(); it2++)
{
Line->mesh->SetVertexPosition(0) = it->second->pos;
Line->mesh->SetVertexPosition(1) = di.list[it2->first]->pos;
Line->mesh->Update();
Line->W = W;
Line->Render();
}
}
DEPTH->Set(true);
}
}
std::list<Vector3> Terrain::PathFinding(int from, int to)
{
std::list<Vector3> way = di.PathFinding(from, to);
for (auto it = way.begin(); it != way.end(); it++)
{
*it = Vector3::Transform(*it, W);
}
return way;
}
터레인의 클래스입니다. 노드를 배치하고 간선으로 연결하기 위해 수정했습니다.
#pragma once
struct Brush
{
int shape = 0;
int texture = 1;
int type = 0;
float range = 10.0f;
float YScale = 3.0f;
};
class Main : public Scene
{
private:
Camera* Cam;
Terrain* terrain;
bool textureBrush = false;
bool nodeEdit = false;
Actor* mousePoint;
int brushIdx;
Brush brush[3];
struct Brush
{
Vector3 point;
float range = 2.0f;
float shape;
float type;
Vector2 padding;
} _brush;
ID3D11Buffer* brushBuffer;
int nodeState;
int firstLink;
int secondLink;
public:
Main();
~Main();
virtual void Init() override;
virtual void Release() override;
virtual void Update() override;
virtual void LateUpdate() override;
virtual void Render() override;
virtual void PreRender() override;
virtual void ResizeScreen() override;
void NormalizeWeight(Vector4& in);
};
#include "stdafx.h"
#include "Main.h"
Main::Main()
{
D3D11_BUFFER_DESC desc = { 0 };
desc.ByteWidth = sizeof(Brush);
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;//상수버퍼
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
HRESULT hr = D3D->GetDevice()->CreateBuffer(&desc, NULL, &brushBuffer);
assert(SUCCEEDED(hr));
D3D->GetDC()->PSSetConstantBuffers(10, 1, &brushBuffer);
}
Main::~Main()
{
}
void Main::Init()
{
Cam = Camera::Create();
Cam->LoadFile("Cam.xml");
Camera::main = Cam;
Cam->width = App.GetWidth();
Cam->height = App.GetHeight();
Cam->viewport.width = App.GetWidth();
Cam->viewport.height = App.GetHeight();
terrain = Terrain::Create();
terrain->LoadFile("Terrain.xml");
terrain->CreateStructuredBuffer();
mousePoint = Actor::Create();
mousePoint->LoadFile("Deadpool.xml");
terrain->showNode = true;
brushIdx = 0;
nodeState = 0;
firstLink = 0;
secondLink = 0;
}
void Main::Release()
{
}
void Main::Update()
{
ImGui::Checkbox("nodeEdit", &nodeEdit);
if (nodeEdit)
{
ImGui::Text("firstLink: %d secondLink: %d", firstLink, secondLink);
if (ImGui::Button("AddNode"))
{
nodeState = 0;
}
ImGui::SameLine();
if (ImGui::Button("DeleteNode"))
{
nodeState = 1;
}
ImGui::SameLine();
if (ImGui::Button("LinkNode"))
{
nodeState = 2;
}
}
else
{
if (GUI->FileImGui("Load", "LoadRawFile",
".raw,.RAW", "../Contents/Raw"))
{
string path = ImGuiFileDialog::Instance()->GetCurrentPath();
Util::Replace(&path, "\\", "/");
if (path.find("/Raw/") != -1)
{
size_t tok = path.find("/Raw/") + 5;
path = path.substr(tok, path.length())
+ "/" + ImGuiFileDialog::Instance()->GetCurrentFileName();
}
else
{
path = ImGuiFileDialog::Instance()->GetCurrentFileName();
}
string file = "../Contents/Raw/" + path;
FILE* fp;
//파일 열기
fopen_s(&fp, file.c_str(), "rb");
fseek(fp, 0, SEEK_END);
int Size = ftell(fp);
fseek(fp, 0, SEEK_SET);
BYTE* Height = new BYTE[Size];
for (int i = 0; i < Size; i++)
{
char c = fgetc(fp);
Height[i] = c;
}
int terrainSize = (int)sqrt(Size);
int triSize = (terrainSize - 1) * (terrainSize - 1) * 2;
float half = terrainSize * 0.5f;
VertexTerrain* vertices = new VertexTerrain[Size];
for (int z = 0; z < terrainSize; z++)
{
for (int x = 0; x < terrainSize; x++)
{
int Index = (z * terrainSize) + x;
float _x = x - half;
float _z = -z + half;
float _y = Height[Index] / 255.0f * (float)terrainSize;
float _u = float(x) / float(terrainSize - 1);
float _v = float(z) / float(terrainSize - 1);
vertices[Index].uv = Vector2(_u, _v);
vertices[Index].position = Vector3(_x, _y, _z);
vertices[Index].normal = Vector3(0, 1, 0);
}
}
UINT* indices = new UINT[triSize * 3];
int Idx = 0;
for (int z = 0; z < terrainSize - 1; z++)
{
for (int x = 0; x < terrainSize - 1; x++)
{
UINT Index = z * terrainSize + x;
indices[Idx] = Index;
Idx++;
indices[Idx] = Index + 1;
Idx++;
indices[Idx] = Index + terrainSize + 1;
Idx++;
indices[Idx] = Index;
Idx++;
indices[Idx] = Index + terrainSize + 1;
Idx++;
indices[Idx] = Index + terrainSize;
Idx++;
}
}
terrain->mesh = make_shared<Mesh>(vertices, Size, indices, Idx,
VertexType::TERRAIN);
terrain->UpdateMeshNormal();
//파일 닫기
fclose(fp);
}
ImGui::Text("Select Brush");
ImGui::Checkbox("textureBrush", &textureBrush);
for (int i = 0; i < 3; i++)
{
string temp = "Brush" + to_string(i);
if (ImGui::Button(temp.c_str()))
{
brushIdx = i;
}
if (i < 2)
ImGui::SameLine();
}
ImGui::SliderFloat("brushRange", &brush[brushIdx].range, 1.0f, 100.0f);
ImGui::SliderFloat("brushYScale", &brush[brushIdx].YScale, -100.0f, 100.0f);
ImGui::SliderInt("brushType", &brush[brushIdx].type, 0, 2);
if (ImGui::Button("[]"))
{
brush[brushIdx].shape = 1;
}
ImGui::SameLine();
if (ImGui::Button("()"))
{
brush[brushIdx].shape = 0;
}
if (terrain->material->ambient.w)
{
ImVec2 size;
size.x = 20; size.y = 20;
if (ImGui::ImageButton((void*)terrain->material->normalMap->srv, size))
{
brush[brushIdx].texture = 0;
}
ImGui::SameLine();
}
if (terrain->material->diffuse.w)
{
ImVec2 size;
size.x = 20; size.y = 20;
if (ImGui::ImageButton((void*)terrain->material->diffuseMap->srv, size))
{
brush[brushIdx].texture = 1;
}
ImGui::SameLine();
}
if (terrain->material->specular.w)
{
ImVec2 size;
size.x = 20; size.y = 20;
if (ImGui::ImageButton((void*)terrain->material->specularMap->srv, size))
{
brush[brushIdx].texture = 2;
}
ImGui::SameLine();
}
if (terrain->material->emissive.w)
{
ImVec2 size;
size.x = 20; size.y = 20;
if (ImGui::ImageButton((void*)terrain->material->emissiveMap->srv, size))
{
brush[brushIdx].texture = 3;
}
}
}
Camera::ControlMainCam();
//ImGui::SliderFloat3("dirLight", (float*)(&LIGHT->dirLight.direction), -1, 1);
ImGui::Text("FPS: %d", TIMER->GetFramePerSecond());
ImGui::Begin("Hierarchy");
Cam->RenderHierarchy();
terrain->RenderHierarchy();
mousePoint->RenderHierarchy();
//Cam->RenderHierarchy();
ImGui::End();
Cam->Update();
terrain->Update();
mousePoint->Update();
}
void Main::LateUpdate()
{
Vector3 Hit;
if (terrain->ComPutePicking(Util::MouseToRay(), Hit))
{
_brush.point = Hit;
mousePoint->SetWorldPos(Hit);
if (nodeEdit)
{
if (INPUT->KeyDown(VK_MBUTTON))
{
Matrix inverse = terrain->W.Invert();
Vector3 localPos = Vector3::Transform(Hit, inverse);
if (nodeState == 0)
{
terrain->di.AddNode(localPos);
}
if (nodeState == 1)
{
int temp = terrain->di.GetNode(localPos);
if (temp)
{
terrain->di.PopNode(temp);
}
}
if (nodeState == 2)
{
if (not firstLink)
{
firstLink = terrain->di.GetNode(localPos);
}
else
{
secondLink = terrain->di.GetNode(localPos);
terrain->di.LinkNode(firstLink, secondLink);
secondLink = 0;
firstLink = 0;
}
}
}
}
else
{
if (INPUT->KeyPress(VK_MBUTTON))
{
VertexTerrain* vertices = (VertexTerrain*)terrain->mesh->vertices;
Matrix Inverse = terrain->W.Invert();
Hit = Vector3::Transform(Hit, Inverse);
float YScale = brush[brushIdx].YScale / terrain->S._22;
float Range = brush[brushIdx].range / terrain->S._11;
for (UINT i = 0; i < terrain->mesh->vertexCount; i++)
{
Vector3 v1 = Vector3(Hit.x, 0.0f, Hit.z);
Vector3 v2 = Vector3(vertices[i].position.x,
0.0f, vertices[i].position.z);
float w;
Vector3 temp = v2 - v1;
float Dis = temp.Length();
if (brush[brushIdx].shape == 1)
{
if (fabs(v1.x - v2.x) < brush[brushIdx].range and
fabs(v1.z - v2.z) < brush[brushIdx].range)
{
//nomalize
w = Dis / (Range * 1.414f);
// 0 ~ 1
w = Util::Saturate(w);
w = (1.0f - w);
}
else
{
w = 0.0f;
}
}
if (brush[brushIdx].shape == 0)
{
//nomalize
w = Dis / Range;
// 0 ~ 1
w = Util::Saturate(w);
w = (1.0f - w);
}
if (brush[brushIdx].type == 1)
w = sin(w * PI * 0.5f);
if (brush[brushIdx].type == 2)
w = w ? 1 : 0;
if (textureBrush)
{
if (brush[brushIdx].texture == 0)
{
vertices[i].weights.x += w * YScale * DELTA;
vertices[i].weights.y -= w * YScale * DELTA;
vertices[i].weights.z -= w * YScale * DELTA;
vertices[i].weights.w -= w * YScale * DELTA;
}
if (brush[brushIdx].texture == 1)
{
vertices[i].weights.x -= w * YScale * DELTA;
vertices[i].weights.y += w * YScale * DELTA;
vertices[i].weights.z -= w * YScale * DELTA;
vertices[i].weights.w -= w * YScale * DELTA;
}
if (brush[brushIdx].texture == 2)
{
vertices[i].weights.x -= w * YScale * DELTA;
vertices[i].weights.y -= w * YScale * DELTA;
vertices[i].weights.z += w * YScale * DELTA;
vertices[i].weights.w -= w * YScale * DELTA;
}
if (brush[brushIdx].texture == 3)
{
vertices[i].weights.x -= w * YScale * DELTA;
vertices[i].weights.y -= w * YScale * DELTA;
vertices[i].weights.z -= w * YScale * DELTA;
vertices[i].weights.w += w * YScale * DELTA;
}
NormalizeWeight(vertices[i].weights);
}
else
vertices[i].position.y += w * YScale * DELTA;
}
terrain->mesh->Update();
}
}
}
if (INPUT->KeyUp(VK_MBUTTON))
{
terrain->UpdateMeshNormal();
terrain->DeleteStructuredBuffer();
terrain->CreateStructuredBuffer();
}
}
void Main::PreRender()
{
}
void Main::Render()
{
_brush.range = brush[brushIdx].range;
_brush.shape = brush[brushIdx].shape;
_brush.type = brush[brushIdx].type;
D3D11_MAPPED_SUBRESOURCE mappedResource;
D3D->GetDC()->Map(brushBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
memcpy_s(mappedResource.pData, sizeof(Brush), &_brush, sizeof(Brush));
D3D->GetDC()->Unmap(brushBuffer, 0);
Cam->Set();
terrain->Render();
mousePoint->Render();
}
void Main::ResizeScreen()
{
Cam->width = App.GetWidth();
Cam->height = App.GetHeight();
Cam->viewport.width = App.GetWidth();
Cam->viewport.height = App.GetHeight();
}
void Main::NormalizeWeight(Vector4& in)
{
float* weight = (float*)∈
float sum = 0;
for (int i = 0; i < 4; i++)
{
weight[i] = Util::Saturate(weight[i]);
sum += weight[i];
}
for (int i = 0; i < 4; i++)
{
weight[i] /= sum;
}
}
int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR param, int command)
{
App.SetAppName(L"Game1");
App.SetInstance(instance);
WIN->Create();
D3D->Create();
Main * main = new Main();
main->Init();
int wParam = (int)WIN->Run(main);
main->Release();
SafeDelete(main);
D3D->DeleteSingleton();
WIN->DeleteSingleton();
return wParam;
}
그렇게 만든 것을 런타임 중에 확인하기 위해 ImGui를 사용하여 원하는 위치에 노드를 배치하고 연결할 수 있도록 했습니다.
읽어주셔서 감사합니다.