port from perforce

This commit is contained in:
2026-04-18 22:31:51 +02:00
commit 8d0ab5b7cc
8409 changed files with 3972376 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
#if _DEBUG
#include "ObjExporter.h"
#include <iostream>
#include <fstream>
void ObjExporter::Export(mt::Mesh* mesh, const std::string& filePath)
{
ObjExporter exporter(mesh);
exporter.Export(filePath);
}
ObjExporter::ObjExporter(mt::Mesh* mesh)
: mesh{mesh}
{
}
void ObjExporter::Export(const std::string& filePath)
{
std::ostringstream builder;
std::ostringstream mtlBuilder;
builder << "mtllib " + replace(filePath, ".obj", ".mtl") << std::endl;
WritePositions(builder);
WriteNormals(builder);
WriteUVs(builder);
WriteFaceGroups(builder, mtlBuilder);
std::ofstream objFile(filePath);
objFile << builder.str();
objFile.close();
std::ofstream mtlFile(replace(filePath, ".obj", ".mtl"));
mtlFile << mtlBuilder.str();
mtlFile.close();
}
void ObjExporter::WriteFaceGroups(std::ostringstream& builder, std::ostringstream& mtlBuilder)
{
auto groups = mesh->GetSubMeshs();
for(const auto& group : groups)
{
auto materialId = group->Key;
builder << "usemtl " << materialId << std::endl;
builder << "g " << materialId << std::endl;
WriteFaces(builder, group->Value);
mtlBuilder << "newmtl " << materialId << std::endl;
mtlBuilder << "Ka 0.0 0.0 0.0" << std::endl;
mtlBuilder << "Kd 1.0 1.0 1.0" << std::endl;
mtlBuilder << "Ks 1.0 1.0 1.0" << std::endl;
mtlBuilder << "Ns 16.0" << std::endl;
mtlBuilder << "illum 0" << std::endl;
mtlBuilder << "map_Kd " << materialId << ".png" << std::endl;
}
}
void ObjExporter::WriteFaces(std::ostringstream& builder, const mt::FaceList& faces)
{
for (auto face : faces)
{
auto indices = face->GetIndices(true);
builder << "f";
for (int i = 0; i < indices.Count(); ++i)
{
builder << " ";
auto index = indices[i] + 1;
builder << index << "/" << index << "/" << index;
}
builder << std::endl;
}
}
void ObjExporter::WritePositions(std::ostringstream& builder)
{
for (const auto& v : mesh->GetVertices())
{
builder << "v " << v->Position.x << " " << v->Position.y << " " << v->Position.z << std::endl;
}
}
void ObjExporter::WriteNormals(std::ostringstream& builder)
{
for (const auto& v : mesh->GetVertices())
{
auto normal = v->GetNormal();
builder << "vn " << normal.x << " " << normal.y << " " << normal.z << std::endl;
}
}
void ObjExporter::WriteUVs(std::ostringstream& builder)
{
for (const auto& v : mesh->GetVertices())
{
builder << "vt " << v->UV[0] << " " << v->UV[1] << std::endl;
}
}
#endif

View File

@@ -0,0 +1,44 @@
#pragma once
#if _DEBUG
#include "../src/Lib/mt/mt.h"
#include <sstream>
#include <string>
class Mesh;
class ObjExporter
{
public:
static void Export(mt::Mesh* mesh, const std::string& filePath);
ObjExporter(mt::Mesh* mesh);
void Export(const std::string& filePath);
void WriteFaceGroups(std::ostringstream& builder, std::ostringstream& mtlBuilder);
void WriteFaces(std::ostringstream& builder, const mt::FaceList& faces);
void WritePositions(std::ostringstream& builder);
void WriteNormals(std::ostringstream& builder);
void WriteUVs(std::ostringstream& builder);
private:
std::string replace(const std::string &input, const std::string &search, const std::string &replace)
{
auto s = input;
for (size_t pos = 0;; pos += replace.length())
{
// Locate the substring to replace
pos = s.find(search, pos);
if (pos == std::string::npos) break;
// Replace by erasing and inserting
s.erase(pos, search.length());
s.insert(pos, replace);
}
return s;
}
private:
mt::Mesh* mesh;
};
#endif

View File

@@ -0,0 +1,40 @@
========================================================================
CONSOLE APPLICATION : TestApp Project Overview
========================================================================
AppWizard has created this TestApp application for you.
This file contains a summary of what you will find in each of the files that
make up your TestApp application.
TestApp.vcxproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.
TestApp.vcxproj.filters
This is the filters file for VC++ projects generated using an Application Wizard.
It contains information about the association between the files in your project
and the filters. This association is used in the IDE to show grouping of files with
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
"Source Files" filter).
TestApp.cpp
This is the main application source file.
/////////////////////////////////////////////////////////////////////////////
Other standard files:
StdAfx.h, StdAfx.cpp
These files are used to build a precompiled header (PCH) file
named TestApp.pch and a precompiled types file named StdAfx.obj.
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" comments to indicate parts of the source code you
should add to or customize.
/////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,161 @@
// TestApp.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "../src/Lib/mt/mt.h"
#include "ObjExporter.h"
int main()
{
auto mesh = mt::CreateSphere(2);
const int FFD_X = 2;
const int FFD_Y = 5;
const int FFD_Z = 5;
auto ffd = new mt::FFD(mesh->GetFaces(), FFD_X, FFD_Y, FFD_Z, mt::FFD::FFDControlPointMode::Surface);
// Bring the skull shape in form for the top view [DONE]
auto selection = ffd->SelectPoints(0, FFD_X, 0, FFD_Y, 0, FFD_Z); // Select all FFD Points
for (const auto& v : selection)
{
v->x *= 1 + (0.3f * (v->z + 0.5f));
v->z *= 1.5f;
}
// Shape the back view [DONE]
selection = ffd->SelectPoints(0, FFD_X, 0, 0, 0, FFD_Z); // Select all bottom Points
for (const auto& v : selection)
{
v->x *= 1.75f;
}
// Shape the side view (Cheek) [DONE]
selection = ffd->SelectPoints(0, FFD_X, 0, 2, 2, 2);
for (const auto& v : selection)
{
v->y = v->y * 0.5f + 0.5f;
}
// Shape the side view (Nose) [Done]
selection = ffd->SelectPoints(1, 1, 0, 2, 0, 0);
//selection.Add(&ffd->ControlPoints[1][0][1]);
for (const auto& v : selection)
{
v->y -= 0.75f;
}
// Generell vertical upscale
selection = ffd->SelectPoints(0, FFD_X, 0, FFD_Y, 0, FFD_Z);
for (const auto& v : selection)
{
v->y *= 1.25f;
}
// Fix the back part of the head which is really high above [Done]
selection = ffd->SelectPoints(0, FFD_X, 5, 5, FFD_Z, FFD_Z);
for (const auto& v : selection)
{
v->y += 0.4f;
v->z += 0.4f;
}
// Descale the length of the head [Done]
selection = ffd->SelectPoints(0, FFD_X, 0, FFD_Y, 0, 2);
for (const auto& v : selection)
{
v->z *= 0.9f;
}
//ffd->DrawFFDGrid(mesh, 0.025f, &selection);
//ffd->DumpFFDGridPositions();
ffd->Apply();
// Despike the chin [Done]
auto chinVertex = mesh->GetVertices()[38];
// chinVertex->Position.y += 0.1f;
// Dechamfer chin
int chinIndices[] = { 51, 53, 55 }; // 3
auto chinVertices = mesh->GetVertices().GetSubset(chinIndices, 3);
/*auto chinVertices = mt::GetVerticesOnPositivePlane(mesh->GetVertices(), mt::Plane(mt::vec3::back, mt::vec3::zero));
chinVertices = mt::GetVerticesOnPositivePlane(chinVertices, mt::Plane(mt::vec3::forward, mt::vec3::back * 0.25f));
chinVertices = mt::GetVerticesOnPositivePlane(chinVertices, mt::Plane(mt::vec3::down, mt::vec3::down * 0.2f));
mt::DumpIndicies(chinVertices, mesh->GetVertices());
mt::DisplayVertices(chinVertices, 0.1f, mesh);*/
for (const auto& v : chinVertices)
v->Position.z -= 0.05f;
auto faceSelection = mt::GetFacesOnPositivePlane(mesh->GetFaces(), { mt::vec3::down, mt::vec3::zero });
faceSelection = mt::GetFacesOnPositivePlane(faceSelection, { mt::vec3::forward, mt::vec3::back * 0.25f });
//faceSelection = mt::GetFacesOnPositivePlane(faceSelection, { mt::vec3::back, mt::vec3::forward * 0.25f });
ffd = new mt::FFD(faceSelection, 1, 1, 1, mt::FFD::FFDControlPointMode::Surface);
selection = ffd->SelectPoints(0, 1, 0, 0, 0, 0);
for (const auto& v : selection)
{
v->x *= 0.5f;
}
//ffd->DrawFFDGrid(mesh, 0.025f, &selection);
//ffd->DumpFFDGridPositions();
ffd->Apply();
faceSelection = mt::GetFacesOnPositivePlane(mesh->GetFaces(), { mt::vec3::left, mt::vec3::zero });
mt::Delete(faceSelection);
//faceSelection.Clear();
//faceSelection.Add(mesh->GetFaces()[2]);
//faceSelection.Add(mesh->GetFaces()[6]);
//mt::Split(faceSelection, {mt::vec3::up, mt::vec3::zero});
// Dat eye socket
mt::vec3 eyeCenter = { 0.22f, -0.05f, -0.5f };
auto eyeBall = mt::CreateSphere(1, eyeCenter, 0.35f);
mt::Scale(eyeBall->GetVertices(), { 1, 0.7f, 2.0f });
mt::Rotate(eyeBall->GetVertices(), eyeCenter, mt::vec3::forward, -0.3f);
// De noze
mt::vec3 nostrilCenter = { 0.2f, -0.25f, -0.5f };
auto nostril = mt::CreateSphere(1, nostrilCenter, 0.45f);
ffd = new mt::FFD(nostril->GetFaces(), 1, 1, 1, mt::FFD::FFDControlPointMode::Surface);
selection = ffd->SelectPoints(0, 1, 1, 1, 0, 1);
for (const auto& v : selection)
{
v->x *= 0.8f;
}
selection = ffd->SelectPoints(0, 1, 0, 1, 0, 1);
for (const auto& v : selection)
{
v->x = v->x * 0.5f - 0.1f;
v->y *= 0.65f;
}
selection = ffd->SelectPoints(1, 1, 0, 0, 0, 1);
for (const auto& v : selection)
{
v->y -= 0.05f;
}
ffd->Apply();
for (const auto& v : nostril->GetVertices())
v->Position.x = v->Position.x < 0.004f ? 0.004f : v->Position.x;
mt::CloneToMesh(nostril->GetFaces(), eyeBall);
mesh = mt::CsgSubtract(mesh->GetFaces(), eyeBall->GetFaces());
auto vertices = mesh->GetVertices();
mt::Weld(vertices);
faceSelection = mt::Clone(mesh->GetFaces());
mt::Mirror(faceSelection, { mt::vec3::right, mt::vec3::zero });
//mt::Subdivide(mesh->GetFaces(), true);
ObjExporter::Export(mesh, "mesh.obj");
return 0;
}

View File

@@ -0,0 +1,163 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{0E9C6FB6-B6ED-407B-A868-3157BC58EC02}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>TestApp</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>D:\Repositories\blu-flame.org\meshToolsV5\lib\Debug;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Lib.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ObjExporter.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ObjExporter.cpp" />
<ClCompile Include="stdafx.cpp" />
<ClCompile Include="TestApp.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ObjExporter.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TestApp.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ObjExporter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// TestApp.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

View File

@@ -0,0 +1,15 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here

View File

@@ -0,0 +1,8 @@
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>

View File

@@ -0,0 +1,59 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29920.165
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Editor", "src\Editor\Editor.csproj", "{8AF5E6D2-4E9C-4D08-9189-1FBD6F1334AD}"
ProjectSection(ProjectDependencies) = postProject
{FDEBD01E-0317-4400-9208-58D7DD7CEE44} = {FDEBD01E-0317-4400-9208-58D7DD7CEE44}
{EB7F77A5-EBA2-4EF4-BDD2-02E961B0E256} = {EB7F77A5-EBA2-4EF4-BDD2-02E961B0E256}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Lib", "src\Lib\Lib.vcxproj", "{FDEBD01E-0317-4400-9208-58D7DD7CEE44}"
ProjectSection(ProjectDependencies) = postProject
{EB7F77A5-EBA2-4EF4-BDD2-02E961B0E256} = {EB7F77A5-EBA2-4EF4-BDD2-02E961B0E256}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Interop", "src\Interop\Interop.vcxproj", "{306104A5-EEEE-4789-847A-07869D715550}"
ProjectSection(ProjectDependencies) = postProject
{FDEBD01E-0317-4400-9208-58D7DD7CEE44} = {FDEBD01E-0317-4400-9208-58D7DD7CEE44}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Codegen", "src\Codegen\Codegen.csproj", "{EB7F77A5-EBA2-4EF4-BDD2-02E961B0E256}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Editor.Operators", "src\Editor.Operators\Editor.Operators.shproj", "{01F4EA18-A795-416A-AE63-7680E87C0931}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Editor.Operators\Editor.Operators.projitems*{01f4ea18-a795-416a-ae63-7680e87c0931}*SharedItemsImports = 13
src\Editor.Operators\Editor.Operators.projitems*{8af5e6d2-4e9c-4d08-9189-1fbd6f1334ad}*SharedItemsImports = 4
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8AF5E6D2-4E9C-4D08-9189-1FBD6F1334AD}.Debug|Win32.ActiveCfg = Debug|x86
{8AF5E6D2-4E9C-4D08-9189-1FBD6F1334AD}.Debug|Win32.Build.0 = Debug|x86
{8AF5E6D2-4E9C-4D08-9189-1FBD6F1334AD}.Release|Win32.ActiveCfg = Release|x86
{8AF5E6D2-4E9C-4D08-9189-1FBD6F1334AD}.Release|Win32.Build.0 = Release|x86
{FDEBD01E-0317-4400-9208-58D7DD7CEE44}.Debug|Win32.ActiveCfg = Debug|Win32
{FDEBD01E-0317-4400-9208-58D7DD7CEE44}.Debug|Win32.Build.0 = Debug|Win32
{FDEBD01E-0317-4400-9208-58D7DD7CEE44}.Release|Win32.ActiveCfg = Release|Win32
{FDEBD01E-0317-4400-9208-58D7DD7CEE44}.Release|Win32.Build.0 = Release|Win32
{306104A5-EEEE-4789-847A-07869D715550}.Debug|Win32.ActiveCfg = Debug|Win32
{306104A5-EEEE-4789-847A-07869D715550}.Debug|Win32.Build.0 = Debug|Win32
{306104A5-EEEE-4789-847A-07869D715550}.Release|Win32.ActiveCfg = Release|Win32
{306104A5-EEEE-4789-847A-07869D715550}.Release|Win32.Build.0 = Release|Win32
{EB7F77A5-EBA2-4EF4-BDD2-02E961B0E256}.Debug|Win32.ActiveCfg = Debug|x86
{EB7F77A5-EBA2-4EF4-BDD2-02E961B0E256}.Debug|Win32.Build.0 = Debug|x86
{EB7F77A5-EBA2-4EF4-BDD2-02E961B0E256}.Release|Win32.ActiveCfg = Release|x86
{EB7F77A5-EBA2-4EF4-BDD2-02E961B0E256}.Release|Win32.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {46C9A196-4DC8-4282-885E-B2258D00D4CC}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{EB7F77A5-EBA2-4EF4-BDD2-02E961B0E256}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Codegen</RootNamespace>
<AssemblyName>Codegen</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\bin\Debug\</OutputPath>
<BaseIntermediateOutputPath>..\..\obj\Debug\Codegen\</BaseIntermediateOutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\..\bin\Release\</OutputPath>
<BaseIntermediateOutputPath>..\..\obj\Release\Codegen\</BaseIntermediateOutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,504 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Codegen
{
class Program
{
class OpParam
{
public OpParam(string sTypeName, string sParamName, string sDefaultValue)
{
TypeName = sTypeName;
ParamName = sParamName;
DefaultValue = sDefaultValue;
}
public string Min;
public string Max;
public string Step;
public string Description;
public string DisplayName;
public string DefaultValue;
public string ParamName;
public string TypeName;
public string CleanType;
public bool NeedsIndex;
public bool IsConst;
public bool IsPtr;
}
class OpLines
{
public List<string> MetaData;
public string Definition;
public string Name;
public Dictionary<string, OpParam> Parameters;
public string ToolTip;
public int Index;
public virtual void WriteOp(StreamWriter _opWriter)
{
_opWriter.WriteLine("\t\t\tcase " + Index + ":");
_opWriter.WriteLine("\t\t\t\t{");
var paramList = new List<string>();
foreach (var kvp in Parameters)
{
var sName = kvp.Key;
var param = kvp.Value;
paramList.Add(sName);
if (param.NeedsIndex)
{
_opWriter.WriteLine("\t\t\t\t\tauto " + sName + "Index = *((unsigned short*)data); data += sizeof(unsigned short);");
string sPtr = !param.IsPtr ? "*" : "";
if (param.IsConst)
{
_opWriter.WriteLine("\t\t\t\t\t" + param.TypeName + " " + sName + " = " + sPtr + "(" + param.CleanType + "*)r[" + sName + "Index];");
}
else
{
_opWriter.WriteLine("\t\t\t\t\t" + param.TypeName + " " + sName + " = " + sPtr + "(" + param.CleanType + "*)(r[" + sName + "Index] = new " + param.CleanType + "());");
}
}
else if (param.TypeName == "bool")
{
_opWriter.WriteLine("\t\t\t\t\tbool " + sName + " = *((unsigned char*)data) == 1; data += sizeof(unsigned char);");
}
else
{
_opWriter.WriteLine("\t\t\t\t\t" + param.TypeName + " " + sName + " = *((" + param.CleanType + "*)data); data += sizeof(" + param.CleanType + ");");
}
}
_opWriter.WriteLine("\t\t\t\t\top::" + Name + "(" + string.Join(", ", paramList) + ");");
_opWriter.WriteLine("\t\t\t\t}");
_opWriter.WriteLine("\t\t\t\tbreak;");
}
public virtual void ParseMetaData()
{
var defTokens = Definition.Split(' ', '(');
Name = defTokens[1];
var start = Definition.IndexOf('(');
var end = Definition.IndexOf(')');
var args = Definition.Substring(start + 1, end - start - 1).Split(',').Select(a => a.Trim());
Parameters = new Dictionary<string, OpParam>();
foreach (var arg in args)
{
var argTokens = arg.Split(' ');
int i = 0;
string sTypeName = "";
string sCleanType = "";
bool bConst = false;
if (argTokens[i] == "const")
{
sTypeName = "const ";
bConst = true;
++i;
}
sCleanType = argTokens[i++];
sTypeName += sCleanType;
sCleanType = sCleanType.Replace("&", "").Replace("*", "");
bool bNeedsIndex = sCleanType == "OpMesh" || (sTypeName.Contains("*") || sTypeName.Contains("&"));
bool bIsPtr = sTypeName.Contains("*");
var sParamName = argTokens[i++];
string sDefaultValue = "";
if (argTokens.Length > i && argTokens[i++] == "=")
sDefaultValue = argTokens[i];
Parameters[sParamName] = new OpParam(sTypeName, sParamName, sDefaultValue) { NeedsIndex = bNeedsIndex, CleanType = sCleanType, IsConst = bConst, IsPtr = bIsPtr };
}
foreach (var data in MetaData)
{
start = data.IndexOf('[');
end = data.IndexOf(']');
if (start == -1)
continue;
var mdName = data.Substring(start + 1, end - start - 1);
if (mdName == "toolTip")
{
ToolTip = data.Substring(end + 1).Trim();
}
else if (Parameters.ContainsKey(mdName))
{
var opParam = Parameters[mdName];
var props = data.Substring(end + 1).Trim();
while (true)
{
start = props.IndexOf('"');
if (start == -1)
break;
end = props.Substring(start + 1).IndexOf('"') + start + 2;
var property = props.Substring(0, end);
var propTokens = property.Split('=');
var propName = propTokens[0];
var propValue = propTokens[1].Substring(1, propTokens[1].Length - 2);
switch (propTokens[0])
{
case "DisplayName": opParam.DisplayName = propValue; break;
case "Min": opParam.Min = propValue; break;
case "Max": opParam.Max = propValue; break;
case "Step": opParam.Step = propValue; break;
case "Description": opParam.Description = propValue; break;
}
props = props.Substring(end).Trim();
}
}
}
}
}
class OpLoop : OpLines
{
public override void ParseMetaData()
{
Name = "Loop";
ToolTip = "Simple operator for iterating integer values";
Parameters = new Dictionary<string, OpParam>();
Parameters["From"] = new OpParam("ushort", "From", "0") { DisplayName = "From", Description = "Initial value for the iteration integer", CleanType = "ushort" };
Parameters["To"] = new OpParam("ushort", "To", "0") { DisplayName = "To", Description = "Upper bound (exclusive) for the iteration integer", CleanType = "ushort" };
Parameters["GroupId"] = new OpParam("ushort", "GroupId", "0") { DisplayName = "Group ID", Description = "Group to execute during every iteration", CleanType = "ushort" };
Parameters["LoopVarIndex"] = new OpParam("ushort", "LoopVarIndex", "0") { DisplayName = "Loop variable ID", Description = "Index where to store the loop integer", CleanType = "ushort" };
}
public override void WriteOp(StreamWriter _opWriter)
{
_opWriter.WriteLine("\t\t\tcase " + Index + ": // Loop");
_opWriter.WriteLine("\t\t\t\t{");
_opWriter.WriteLine("\t\t\t\t\tauto iFrom = *((unsigned short*)data); data += sizeof(unsigned short); ");
_opWriter.WriteLine("\t\t\t\t\tauto iTo = *((unsigned short*)data); data += sizeof(unsigned short); ");
_opWriter.WriteLine("\t\t\t\t\tauto iGroupId = *((unsigned short*)data); data += sizeof(unsigned short); ");
_opWriter.WriteLine("\t\t\t\t\tauto iLoopVarIndex = *((unsigned short*)data); data += sizeof(unsigned short); ");
_opWriter.WriteLine("\t\t\t\t\tauto loopVar = new int[1]; r[iLoopVarIndex] = new int(); ");
_opWriter.WriteLine("\t\t\t\t\tfor (*loopVar = iFrom; *loopVar < iTo; (*loopVar)++)");
_opWriter.WriteLine("\t\t\t\t\t{");
_opWriter.WriteLine("\t\t\t\t\t\tauto groupData = (unsigned char*)r[iGroupId]; ");
_opWriter.WriteLine("\t\t\t\t\t\tauto iOpCount = *((unsigned short*)groupData); groupData += sizeof(unsigned short); ");
_opWriter.WriteLine("\t\t\t\t\t\tfor (auto i = 0u; i < iOpCount; ++i) ");
_opWriter.WriteLine("\t\t\t\t\t\t{");
_opWriter.WriteLine("\t\t\t\t\t\t\tmt::ParseOp(r, &groupData); ");
_opWriter.WriteLine("\t\t\t\t\t\t}");
_opWriter.WriteLine("\t\t\t\t\t}");
_opWriter.WriteLine("\t\t\t\t\tdelete [] loopVar;");
_opWriter.WriteLine("\t\t\t\t}");
_opWriter.WriteLine("\t\t\t\tbreak;");
}
}
class OpGroup : OpLines
{
public override void ParseMetaData()
{
Name = "Group";
ToolTip = "Simple operator for grouping operators";
Parameters = new Dictionary<string, OpParam>();
Parameters["GroupId"] = new OpParam("ushort", "GroupId", "0") { DisplayName = "Group ID", Description = "Index of this group", CleanType = "ushort" };
}
public override void WriteOp(StreamWriter _opWriter)
{
_opWriter.WriteLine("\t\t\tcase " + Index + ": // Grouping");
_opWriter.WriteLine("\t\t\t\t{");
_opWriter.WriteLine("\t\t\t\t\tauto iGroupId = *((unsigned short*)data); data += sizeof(unsigned short);");
_opWriter.WriteLine("\t\t\t\t\tauto groupData = (unsigned char*)r[iGroupId];");
_opWriter.WriteLine("\t\t\t\t\tauto iOpCount = *((unsigned short*)groupData); groupData += sizeof(unsigned short);");
_opWriter.WriteLine("\t\t\t\t\tfor (auto i = 0u; i < iOpCount; ++i)");
_opWriter.WriteLine("\t\t\t\t\t{");
_opWriter.WriteLine("\t\t\t\t\t\tmt::ParseOp(r, &groupData);");
_opWriter.WriteLine("\t\t\t\t\t}");
_opWriter.WriteLine("\t\t\t\t}");
_opWriter.WriteLine("\t\t\t\tbreak;");
}
}
static void Main(string[] args)
{
var sDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var iIndex = sDir.IndexOf("meshToolsV5");
sDir = sDir.Substring(0, iIndex + 11);
var sInputFile = Path.Combine(sDir, "src\\Lib\\mt\\operators\\operators.h");
var sOpsFile = Path.Combine(sDir, "src\\Lib\\mt\\parser\\ops.h");
var sEditDir = Path.Combine(sDir, "src\\Editor.Operators");
var sOpsProjectFile = Path.Combine(sEditDir, "Editor.Operators.projitems");
var lines = File.ReadAllLines(sInputFile);
int i = 0;
while (!lines[i++].Trim().StartsWith("namespace op"));
while (lines[i++].Trim() != "{");
int index = 0;
var ops = new List<OpLines>();
var groupOp = new OpGroup() { Index = index++ };
groupOp.ParseMetaData();
ops.Add(groupOp);
var loopOp = new OpLoop() { Index = index++ };
loopOp.ParseMetaData();
ops.Add(loopOp);
while (i < lines.Length) // All ops
{
if (lines[i].Trim() == "}")
break;
var op = new OpLines() { MetaData = new List<string>() };
while (i < lines.Length) // One op
{
var head = lines[i++].Trim();
if (head.StartsWith("//"))
{
op.MetaData.Add(head.Substring(2));
}
else if (head.StartsWith("void"))
{
op.Definition = head;
break;
}
}
if (!string.IsNullOrEmpty(op.Definition))
{
op.ParseMetaData();
op.Index = index++;
ops.Add(op);
}
}
using (var opStream = new FileStream(sOpsFile, FileMode.Create))
{
using (var opWriter = new StreamWriter(opStream))
{
opWriter.WriteLine("// Autogenerated file");
opWriter.WriteLine("#pragma once\n");
opWriter.WriteLine("namespace mt");
opWriter.WriteLine("{");
opWriter.WriteLine("\tvoid ParseOp(void** r, unsigned char** dataPtr)");
opWriter.WriteLine("\t{");
opWriter.WriteLine("\t\tauto data = *dataPtr;\n");
opWriter.WriteLine("\t\tauto opId = *((unsigned short*)data); data += sizeof(unsigned short);");
opWriter.WriteLine("\t\tswitch (opId)");
opWriter.WriteLine("\t\t{");
foreach (var op in ops)
{
op.WriteOp(opWriter);
WriteOpClass(sEditDir, op);
}
opWriter.WriteLine("\t\t}\n");
opWriter.WriteLine("\t\t*dataPtr = data; ");
opWriter.WriteLine("\t}");
opWriter.WriteLine("}\n");
}
}
var sTempFile = Path.GetTempFileName();
using (var stream = new FileStream(sTempFile, FileMode.Create))
{
using (var writer = new StreamWriter(stream))
{
writer.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
writer.WriteLine("<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">");
writer.WriteLine(" <PropertyGroup>");
writer.WriteLine(" <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>");
writer.WriteLine(" <SharedGUID>01f4ea18-a795-416a-ae63-7680e87c0931</SharedGUID>");
writer.WriteLine(" </PropertyGroup>");
writer.WriteLine(" <PropertyGroup Label=\"Configuration\">");
writer.WriteLine(" <Import_RootNamespace>Editor.Operators</Import_RootNamespace>");
writer.WriteLine(" </PropertyGroup>");
writer.WriteLine(" <ItemGroup>");
foreach (var op in ops)
{
writer.WriteLine(" <Compile Include=\"$(MSBuildThisFileDirectory)" + op.Name + ".cs\" />");
}
writer.WriteLine(" </ItemGroup>");
writer.WriteLine("</Project>");
}
}
if (File.ReadAllText(sTempFile) != File.ReadAllText(sOpsProjectFile))
{
File.Copy(sTempFile, sOpsProjectFile, true);
}
File.Delete(sTempFile);
}
private static void WriteOpClass(string sEditDir, OpLines op)
{
var sPath = Path.Combine(sEditDir, op.Name + ".cs");
using (var stream = new FileStream(sPath, FileMode.Create))
{
using (var writer = new StreamWriter(stream))
{
writer.WriteLine("using System.ComponentModel;");
writer.WriteLine("using System.IO;");
writer.WriteLine("using Editor.Attributes;\n");
writer.WriteLine("namespace Editor.Operators");
writer.WriteLine("{");
writer.WriteLine("\tpublic class " + op.Name + " : OperatorBase");
writer.WriteLine("\t{");
writer.WriteLine("\t\tpublic override ushort OpId { get { return " + op.Index + "; } }\n");
var parameters = new List<Tuple<string, string>>();
foreach (var kvp in op.Parameters)
{
var sName = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(kvp.Key);
var param = kvp.Value;
var sType = param.CleanType;
if (param.NeedsIndex)
{
writer.WriteLine("\t\t[IndexedType(\"" + sType + "\")]");
sName += "Index";
sType = "ushort";
}
parameters.Add(Tuple.Create(sName, sType));
if (!string.IsNullOrEmpty(param.DefaultValue))
{
if (!param.CleanType.StartsWith("vec"))
{
writer.WriteLine("\t\t[DefaultValue(" + param.DefaultValue + ")]");
}
}
if (!string.IsNullOrEmpty(param.Description))
{
writer.WriteLine("\t\t[Description(\"" + param.Description + "\")]");
}
if (!string.IsNullOrEmpty(param.DisplayName))
{
writer.WriteLine("\t\t[DisplayName(\"" + param.DisplayName + "\")]");
}
if (!string.IsNullOrEmpty(param.Max))
{
writer.WriteLine("\t\t[Max(\"" + param.Max + "\")]");
}
if (!string.IsNullOrEmpty(param.Min))
{
writer.WriteLine("\t\t[Min(\"" + param.Min + "\")]");
}
if (!string.IsNullOrEmpty(param.Step))
{
writer.WriteLine("\t\t[Step(\"" + param.Step + "\")]");
}
writer.WriteLine("\t\tpublic " + sType + " " + sName);
writer.WriteLine("\t\t{");
writer.WriteLine("\t\t\tget");
writer.WriteLine("\t\t\t{");
writer.WriteLine("\t\t\t\treturn m_" + sName + ";");
writer.WriteLine("\t\t\t}");
writer.WriteLine("\t\t\tset");
writer.WriteLine("\t\t\t{");
writer.WriteLine("\t\t\t\tm_" + sName + " = value;");
writer.WriteLine("\t\t\t\tRaisePropertyChanged();");
writer.WriteLine("\t\t\t}");
writer.WriteLine("\t\t}");
writer.WriteLine("\t\tprivate " + sType + " m_" + sName + ";\n");
}
writer.WriteLine("\t\tpublic " + op.Name + "()");
writer.WriteLine("\t\t{");
foreach (var param in op.Parameters)
{
var defaultValue = param.Value.DefaultValue;
if (string.IsNullOrEmpty(defaultValue))
continue;
var sName = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(param.Key);
// TODO
if (param.Value.CleanType == "vec2")
{
//writer.WriteLine("\t\t\tm_" + sName + ".x = " + defaultValue + ";");
//writer.WriteLine("\t\t\tm_" + sName + ".y = " + defaultValue + ";");
}
else if (param.Value.CleanType == "vec3")
{
//writer.WriteLine("\t\t\tm_" + sName + ".x = " + defaultValue + ";");
//writer.WriteLine("\t\t\tm_" + sName + ".y = " + defaultValue + ";");
//writer.WriteLine("\t\t\tm_" + sName + ".z = " + defaultValue + ";");
}
else if (param.Value.CleanType == "vec4")
{
//writer.WriteLine("\t\t\tm_" + sName + ".x = " + defaultValue + ";");
//writer.WriteLine("\t\t\tm_" + sName + ".y = " + defaultValue + ";");
//writer.WriteLine("\t\t\tm_" + sName + ".z = " + defaultValue + ";");
//writer.WriteLine("\t\t\tm_" + sName + ".w = " + defaultValue + ";");
}
else
{
writer.WriteLine("\t\t\tm_" + sName + " = " + defaultValue + ";");
}
}
writer.WriteLine("\t\t}\n");
writer.WriteLine("\t\tpublic override byte[] Serialize()");
writer.WriteLine("\t\t{");
writer.WriteLine("\t\t\tusing (var stream = new MemoryStream())");
writer.WriteLine("\t\t\t{");
writer.WriteLine("\t\t\t\tusing (var writer = new BinaryWriter(stream))");
writer.WriteLine("\t\t\t\t{");
writer.WriteLine("\t\t\t\t\twriter.Write(OpId);");
foreach (var param in parameters)
{
if (param.Item2 == "vec2")
{
writer.WriteLine("\t\t\t\t\twriter.Write(m_" + param.Item1 + ".x);");
writer.WriteLine("\t\t\t\t\twriter.Write(m_" + param.Item1 + ".y);");
}
else if (param.Item2 == "vec3")
{
writer.WriteLine("\t\t\t\t\twriter.Write(m_" + param.Item1 + ".x);");
writer.WriteLine("\t\t\t\t\twriter.Write(m_" + param.Item1 + ".y);");
writer.WriteLine("\t\t\t\t\twriter.Write(m_" + param.Item1 + ".z);");
}
else if (param.Item2 == "vec4")
{
writer.WriteLine("\t\t\t\t\twriter.Write(m_" + param.Item1 + ".x);");
writer.WriteLine("\t\t\t\t\twriter.Write(m_" + param.Item1 + ".y);");
writer.WriteLine("\t\t\t\t\twriter.Write(m_" + param.Item1 + ".z);");
writer.WriteLine("\t\t\t\t\twriter.Write(m_" + param.Item1 + ".w);");
}
else if (param.Item2 == "bool")
{
writer.WriteLine("\t\t\t\t\twriter.Write(m_" + param.Item1 + " ? (byte)1 : (byte)0);");
}
else
{
writer.WriteLine("\t\t\t\t\twriter.Write(m_" + param.Item1 + ");");
}
}
writer.WriteLine("\t\t\t\t\treturn stream.ToArray();");
writer.WriteLine("\t\t\t\t}");
writer.WriteLine("\t\t\t}");
writer.WriteLine("\t\t}");
writer.WriteLine("\t}");
writer.WriteLine("}");
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Codegen")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Codegen")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("eb7f77a5-eba2-4ef4-bdd2-02e961b0e256")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<SharedGUID>01f4ea18-a795-416a-ae63-7680e87c0931</SharedGUID>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<Import_RootNamespace>Editor.Operators</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)Group.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Loop.cs" />
<Compile Include="$(MSBuildThisFileDirectory)CreateCube.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Subdivide.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Delete.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SelectAllFaces.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SelectFacesByDirection.cs" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>01f4ea18-a795-416a-ae63-7680e87c0931</ProjectGuid>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
<PropertyGroup />
<Import Project="Editor.Operators.projitems" Label="Shared" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,43 @@
using System.ComponentModel;
using System.IO;
using Editor.Attributes;
namespace Editor.Operators
{
public class Foo : OperatorBase
{
public override ushort OpId { get { return 5; } }
[IndexedType("OpMesh")]
public ushort OutputIndex
{
get
{
return m_OutputIndex;
}
set
{
m_OutputIndex = value;
RaisePropertyChanged();
}
}
private ushort m_OutputIndex;
public Foo()
{
}
public override byte[] Serialize()
{
using (var stream = new MemoryStream())
{
using (var writer = new BinaryWriter(stream))
{
writer.Write(OpId);
writer.Write(m_OutputIndex);
return stream.ToArray();
}
}
}
}
}

View File

@@ -0,0 +1,57 @@
using System.ComponentModel;
using System.IO;
using Editor.Attributes;
namespace Editor.Operators
{
public class Load : OperatorBase
{
public override ushort OpId { get { return 6; } }
public int &Output
{
get
{
return m_&Output;
}
set
{
m_&Output = value;
RaisePropertyChanged();
}
}
private int m_&Output;
public int Intput
{
get
{
return m_Intput;
}
set
{
m_Intput = value;
RaisePropertyChanged();
}
}
private int m_Intput;
public Load()
{
}
public override byte[] Serialize()
{
using (var stream = new MemoryStream())
{
using (var writer = new BinaryWriter(stream))
{
writer.Write(OpId);
writer.Write(m_&Output);
writer.Write(m_Intput);
return stream.ToArray();
}
}
}
}
}

View File

@@ -0,0 +1,57 @@
using System.ComponentModel;
using System.IO;
using Editor.Attributes;
namespace Editor.Operators
{
public class Store : OperatorBase
{
public override ushort OpId { get { return 5; } }
public int Output
{
get
{
return m_Output;
}
set
{
m_Output = value;
RaisePropertyChanged();
}
}
private int m_Output;
public int Value
{
get
{
return m_Value;
}
set
{
m_Value = value;
RaisePropertyChanged();
}
}
private int m_Value;
public Store()
{
}
public override byte[] Serialize()
{
using (var stream = new MemoryStream())
{
using (var writer = new BinaryWriter(stream))
{
writer.Write(OpId);
writer.Write(m_Output);
writer.Write(m_Value);
return stream.ToArray();
}
}
}
}
}

View File

@@ -0,0 +1,59 @@
using System.ComponentModel;
using System.IO;
using Editor.Attributes;
namespace Editor.Operators
{
public class Test : OperatorBase
{
public override ushort OpId { get { return 7; } }
[IndexedType("int")]
public ushort OutputIndex
{
get
{
return m_OutputIndex;
}
set
{
m_OutputIndex = value;
RaisePropertyChanged();
}
}
private ushort m_OutputIndex;
[IndexedType("int")]
public ushort ValueIndex
{
get
{
return m_ValueIndex;
}
set
{
m_ValueIndex = value;
RaisePropertyChanged();
}
}
private ushort m_ValueIndex;
public Test()
{
}
public override byte[] Serialize()
{
using (var stream = new MemoryStream())
{
using (var writer = new BinaryWriter(stream))
{
writer.Write(OpId);
writer.Write(m_OutputIndex);
writer.Write(m_ValueIndex);
return stream.ToArray();
}
}
}
}
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
</startup>
</configuration>

View File

@@ -0,0 +1,8 @@
<Application x:Class="Editor.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace Editor
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Editor.Attributes
{
public class IndexedTypeAttribute : Attribute
{
public IndexedTypeAttribute(string _sTypeName)
{
TypeName = _sTypeName;
}
public string TypeName { get; private set; }
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Editor.Attributes
{
public class MaxAttribute : Attribute
{
public MaxAttribute(string _sValue)
{
Value = int.Parse(_sValue);
}
public int Value { get; private set; }
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Editor.Attributes
{
public class MinAttribute : Attribute
{
public MinAttribute(string _sValue)
{
Value = int.Parse(_sValue);
}
public int Value { get; private set; }
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Editor.Attributes
{
public class StepAttribute : Attribute
{
public StepAttribute(string _sValue)
{
Value = float.Parse(_sValue);
}
public float Value { get; private set; }
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Editor
{
public class Document
{
public ushort RegisterCount { get; set; }
public ObservableCollection<OperatorGroup> Groups { get; private set; } = new ObservableCollection<OperatorGroup>();
public ushort ResultIndex { get; set; }
public byte[] Serialize()
{
using (var stream = new MemoryStream())
{
using (var writer = new BinaryWriter(stream))
{
writer.Write((ushort)RegisterCount);
writer.Write((ushort)Groups.Count);
foreach (var group in Groups)
{
writer.Write(group.Serialize());
}
writer.Write((ushort)ResultIndex);
return stream.ToArray();
}
}
}
}
}

View File

@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="..\Editor.Operators\Editor.Operators.projitems" Label="Shared" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8AF5E6D2-4E9C-4D08-9189-1FBD6F1334AD}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Editor</RootNamespace>
<AssemblyName>Editor</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<BaseIntermediateOutputPath>..\..\obj\Debug\Editor\</BaseIntermediateOutputPath>
<Prefer32Bit>true</Prefer32Bit>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<BaseIntermediateOutputPath>..\..\obj\Release\Editor\</BaseIntermediateOutputPath>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="WindowsFormsIntegration" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Attributes\IndexedType.cs" />
<Compile Include="Attributes\Max.cs" />
<Compile Include="Attributes\Min.cs" />
<Compile Include="Attributes\Step.cs" />
<Compile Include="Document.cs" />
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Math.cs" />
<Compile Include="OperatorBase.cs" />
<Compile Include="OperatorGroup.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Interop\Interop.vcxproj">
<Project>{306104a5-eeee-4789-847a-07869d715550}</Project>
<Name>Interop</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<EnableUnmanagedDebugging>true</EnableUnmanagedDebugging>
</PropertyGroup>
<PropertyGroup>
<ProjectView>ProjectFiles</ProjectView>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,21 @@
<Window x:Class="Editor.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
Title="MainWindow" Height="350" Width="525" PreviewKeyDown="Window_PreviewKeyDown">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ToolBar>
<ToggleButton x:Name="btnWireframe" Width="22" Height="22" Checked="btnWireframe_Checked" Unchecked="btnWireframe_Checked">W</ToggleButton>
<ToggleButton x:Name="btnBackFaceCulling" Width="22" Height="22" Checked="btnBackFaceCulling_Checked" Unchecked="btnBackFaceCulling_Checked">B</ToggleButton>
</ToolBar>
<WindowsFormsHost HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="1">
<wf:Panel x:Name="winForms" SizeChanged="winForms_LayoutUpdated" MouseDown="winForms_MouseDown" MouseMove="winForms_MouseMove" MouseUp="winForms_MouseUp" />
</WindowsFormsHost>
<Button Grid.Row="2" x:Name="btnCapture" Click="btnCapture_Click">Capture</Button>
</Grid>
</Window>

View File

@@ -0,0 +1,114 @@
using Editor.Operators;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Editor
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
CompositionTarget.Rendering += CompositionTarget_Rendering;
}
void CompositionTarget_Rendering(object sender, EventArgs e)
{
if (m_bInitialized)
{
Interop.Viewer.Instance.Render();
}
}
private void btnCapture_Click(object sender, RoutedEventArgs e)
{
Interop.Viewer.Instance.CaptureFrame();
}
private void winForms_LayoutUpdated(object sender, EventArgs e)
{
var iWidth = (int)winForms.Width;
var iHeight = (int)winForms.Height;
if (m_bInitialized)
{
Interop.Viewer.Instance.Resize(iWidth, iHeight);
}
else if (iWidth != 0 && iHeight != 0)
{
Interop.Viewer.Instance.Init(winForms.Handle, iWidth, iHeight);
var doc = new Document();
doc.RegisterCount = 2;
doc.ResultIndex = 1;
var group = new OperatorGroup();
doc.Groups.Add(group);
group.Operators.Add(new CreateCube() { OutputIndex = 0 });
//group.Operators.Add(new SelectAllFaces() { OutputIndex = 1, InputIndex = 0 });
//group.Operators.Add(new SelectFacesByDirection() { OutputIndex = 0, InputIndex = 1, Direction = new vec3() { y = 1 } });
//group.Operators.Add(new Subdivide() { OutputIndex = 1, InputIndex = 0 });
//group.Operators.Add(new SelectAllFaces() { OutputIndex = 0, InputIndex = 1 });
//group.Operators.Add(new SelectFacesByDirection() { OutputIndex = 1, InputIndex = 0, Direction = new vec3() { x = 1 }, Threshold = 0.5f });
Interop.Viewer.Instance.LoadDocument(doc.Serialize());
m_bInitialized = true;
}
}
private void winForms_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
Interop.Viewer.Instance.MouseDown(e.Button == System.Windows.Forms.MouseButtons.Left, e.X, e.Y);
}
private void winForms_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
Interop.Viewer.Instance.MouseMove(e.X, e.Y);
}
private void winForms_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
Interop.Viewer.Instance.MouseUp(e.X, e.Y);
}
private bool m_bInitialized = false;
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.A)
{
Interop.Viewer.Instance.FrameAll();
}
else if (e.Key == Key.F)
{
Interop.Viewer.Instance.FrameSelection();
}
}
private void btnWireframe_Checked(object sender, RoutedEventArgs e)
{
Interop.Viewer.Instance.Wireframe = btnWireframe.IsChecked ?? false;
}
private void btnBackFaceCulling_Checked(object sender, RoutedEventArgs e)
{
Interop.Viewer.Instance.BackFaceCulling = btnBackFaceCulling.IsChecked ?? false;
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Editor
{
public struct vec3
{
public float x;
public float y;
public float z;
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace Editor
{
public abstract class OperatorBase : INotifyPropertyChanged
{
public double Left
{
get
{
return m_Left;
}
set
{
m_Left = value;
RaisePropertyChanged();
}
}
public double Top
{
get
{
return m_Top;
}
set
{
m_Top = value;
RaisePropertyChanged();
}
}
public abstract ushort OpId { get; }
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged([CallerMemberName] string _sPropertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(_sPropertyName));
}
public abstract byte[] Serialize();
private double m_Left;
private double m_Top;
}
}

View File

@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Editor
{
public class OperatorGroup
{
public ObservableCollection<OperatorBase> Operators { get; private set; } = new ObservableCollection<OperatorBase>();
public byte[] Serialize()
{
using (var stream = new MemoryStream())
{
using (var writer = new BinaryWriter(stream))
{
writer.Write((ushort)Operators.Count);
foreach (var op in Operators)
{
var opBytes = op.Serialize();
stream.Write(opBytes, 0, opBytes.Length);
}
return stream.GetBuffer();
}
}
}
}
}

View File

@@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Editor")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Editor")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Editor.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Editor.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Editor.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -0,0 +1,87 @@
#include "Stdafx.hpp"
#include "ArcBall.hpp"
ArcBall::ArcBall()
{
Reset();
}
void ArcBall::Reset()
{
m_Down = mt::Quaternion::identity;
m_Now = mt::Quaternion::identity;
m_bDrag = false;
m_fRadius = 1.0f;
}
void ArcBall::SetWindow(float _fWidth, float _fHeight, float _fRadius)
{
m_fWidth = _fWidth;
m_fHeight = _fHeight;
m_fRadius = _fRadius;
}
void ArcBall::OnBegin(float _fX, float _fY)
{
// Only enter the drag state if the click falls inside the click rectangle.
if (_fX >= 0 &&
_fX < m_fWidth &&
_fY >= 0 &&
_fY < m_fHeight)
{
m_bDrag = true;
m_Down = m_Now;
m_DownPoint = ScreenToVector(_fX, _fY);
}
}
void ArcBall::OnMove(float _fX, float _fY)
{
if (m_bDrag)
{
m_CurrentPoint = ScreenToVector(_fX, _fY);
m_Now = mt::Quaternion::FromTo(m_DownPoint, m_CurrentPoint) * m_Down;
}
}
void ArcBall::OnEnd()
{
m_bDrag = false;
}
mt::Matrix ArcBall::GetRotationMatrix()
{
return mt::Matrix::FromQuaternion(m_Now);
}
mt::vec3 ArcBall::ScreenToVector(float _fX, float _fY)
{
// Scale to screen
float x = -(_fX - m_fWidth / 2.0f) / (m_fRadius * m_fWidth / 2.0f);
float y = (_fY - m_fHeight / 2.0f) / (m_fRadius * m_fHeight / 2.0f);
float z = 0.0f;
float fMag = x * x + y * y;
if (fMag > 1.0f)
{
float fScale = 1.0f / sqrtf(fMag);
x *= fScale;
y *= fScale;
}
else
{
z = sqrtf(1.0f - fMag);
}
// Return vector
return mt::vec3(x, y, z);
}

View File

@@ -0,0 +1,32 @@
#pragma once
class ArcBall
{
public:
void Reset();
void SetWindow(float _fWidth, float _fHeight, float _fRadius = 1.0f);
void OnBegin(float _fX, float _fY);
void OnMove(float _fX, float _fY);
void OnEnd();
mt::Matrix GetRotationMatrix();
public:
ArcBall();
private:
mt::vec3 ScreenToVector(float _fX, float _fY);
private:
float m_fWidth; // arc ball's window width
float m_fHeight; // arc ball's window height
float m_fRadius; // arc ball's radius in screen coords
mt::Quaternion m_Down; // Quaternion before button down
mt::Quaternion m_Now; // Composite quaternion for current drag
bool m_bDrag; // Whether user is dragging arc ball
mt::vec3 m_DownPoint; // starting point of rotation arc
mt::vec3 m_CurrentPoint; // current point of rotation arc
};

View File

@@ -0,0 +1,38 @@
#include "Stdafx.hpp"
using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly:AssemblyTitleAttribute(L"Interop")];
[assembly:AssemblyDescriptionAttribute(L"")];
[assembly:AssemblyConfigurationAttribute(L"")];
[assembly:AssemblyCompanyAttribute(L"")];
[assembly:AssemblyProductAttribute(L"Interop")];
[assembly:AssemblyCopyrightAttribute(L"Copyright (c) 2016")];
[assembly:AssemblyTrademarkAttribute(L"")];
[assembly:AssemblyCultureAttribute(L"")];
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly:AssemblyVersionAttribute("1.0.*")];
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{306104A5-EEEE-4789-847A-07869D715550}</ProjectGuid>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<Keyword>ManagedCProj</Keyword>
<RootNamespace>Interop</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(ProjectName)\</IntDir>
<IncludePath>$(SolutionDir)src\Lib;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)lib\$(Configuration)\;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(ProjectName)\</IntDir>
<IncludePath>$(SolutionDir)src\Lib;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)lib\$(Configuration)\;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.hpp</PrecompiledHeaderFile>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Lib.lib;d3d11.lib;DXGI.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.hpp</PrecompiledHeaderFile>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Lib.lib;d3d11.lib;DXGI.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ArcBall.hpp" />
<ClInclude Include="Viewer.hpp" />
<ClInclude Include="Stdafx.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ArcBall.cpp" />
<ClCompile Include="AssemblyInfo.cpp" />
<ClCompile Include="Viewer.cpp" />
<ClCompile Include="Stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Lib\Lib.vcxproj">
<Project>{fdebd01e-0317-4400-9208-58d7dd7cee44}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<FxCompile Include="MeshVertexShader.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType>
</FxCompile>
<FxCompile Include="MeshPixelShader.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
</FxCompile>
<FxCompile Include="SelectionPixelShader.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">5.0</ShaderModel>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">5.0</ShaderModel>
</FxCompile>
</ItemGroup>
<ItemGroup>
<Natvis Include="List.natvis">
<SubType>Designer</SubType>
</Natvis>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ArcBall.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Viewer.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Stdafx.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Viewer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ArcBall.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<FxCompile Include="MeshPixelShader.hlsl" />
<FxCompile Include="MeshVertexShader.hlsl" />
<FxCompile Include="SelectionPixelShader.hlsl" />
</ItemGroup>
<ItemGroup>
<Natvis Include="List.natvis" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="List&lt;*&gt;">
<DisplayString Condition="count == 0">empty</DisplayString>
<DisplayString>{{ size={count} }}</DisplayString>
<Expand>
<ArrayItems>
<Size>count</Size>
<ValuePointer>data</ValuePointer>
</ArrayItems>
<Item Name="[size]" ExcludeView="simple">count</Item>
<Item Name="[capacity]" ExcludeView="simple">capacity</Item>
</Expand>
</Type>
</AutoVisualizer>

View File

@@ -0,0 +1,5 @@
float4 main(in float4 result : SV_POSITION, in float3 normal : NORMAL, in float4 uv : TEXCOORD) : SV_TARGET
{
float l = dot(normal, normalize(float3(1, 0.5, 0.25))) * 0.5 + 0.5;
return float4(l, l, l, 1.0f);
}

View File

@@ -0,0 +1,35 @@
cbuffer cb0 : register (b0)
{
float aspectRatio;
float distanceToCenter;
float dummy2;
float dummy3;
float4x4 modelRotation;
float4 pivot;
}
float4x4 getProjMatrix()
{
float yScale = 2.4142135623730950488016887242097;//cot(fovY/2)
float xScale = yScale / aspectRatio;
float n = 0.1f;
float f = 100.0f;
float4x4 proj =
{
xScale, 0, 0, 0,
0, yScale, 0, 0,
0, 0, f/(f-n), 1,
0, 0, -n*f/(f-n), 0
};
return proj;
}
void main(in float3 pos : POSITION, out float4 result : SV_POSITION, inout float3 normal : NORMAL, inout float4 uv : TEXCOORD)
{
float4 v = float4(pos, 1);
v.xyz -= pivot.xyz;
v = mul(v, modelRotation);
v.z += distanceToCenter;
v = mul(v, getProjMatrix());
result = v;
}

View File

@@ -0,0 +1,6 @@
float4 main(in float4 result : SV_POSITION, in float3 normal : NORMAL, in float4 uv : TEXCOORD) : SV_TARGET
{
int2 wuv = result.xy;
float l = (wuv.x ^ wuv.y) % 4;
return float4(0.25, 0.5, 0.75, l * 0.5f);
}

View File

@@ -0,0 +1,5 @@
// stdafx.cpp : source file that includes just the standard includes
// Interop.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.hpp"

View File

@@ -0,0 +1,8 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently
#pragma once
#include <mt\mt.h>
#include "ArcBall.hpp"

View File

@@ -0,0 +1,642 @@
#include "Stdafx.hpp"
#include "Viewer.hpp"
#include "../Lib/mt/operators/OpDocument.h"
#include <DXGItype.h>
#include <dxgi1_2.h>
#include <dxgi1_3.h>
#include <DXProgrammableCapture.h>
using namespace System::Linq;
static D3D11_RASTERIZER_DESC rsSolidCullBackDesc =
{
D3D11_FILL_SOLID,
D3D11_CULL_BACK,
FALSE,
0,
0,
0,
TRUE,
FALSE,
FALSE,
FALSE
};
static D3D11_RASTERIZER_DESC rsWireframeCullBackDesc =
{
D3D11_FILL_WIREFRAME,
D3D11_CULL_BACK,
FALSE,
0,
0,
0,
TRUE,
FALSE,
FALSE,
FALSE
};
static D3D11_RASTERIZER_DESC rsSolidCullNoneDesc =
{
D3D11_FILL_SOLID,
D3D11_CULL_NONE,
FALSE,
0,
0,
0,
TRUE,
FALSE,
FALSE,
FALSE
};
static D3D11_RASTERIZER_DESC rsWireframeCullNoneDesc =
{
D3D11_FILL_WIREFRAME,
D3D11_CULL_NONE,
FALSE,
0,
0,
0,
TRUE,
FALSE,
FALSE,
FALSE
};
static D3D11_DEPTH_STENCIL_DESC depthStencilDesc =
{
TRUE,
D3D11_DEPTH_WRITE_MASK_ALL,
D3D11_COMPARISON_LESS_EQUAL,
FALSE,
D3D11_DEFAULT_STENCIL_READ_MASK,
D3D11_DEFAULT_STENCIL_WRITE_MASK,
{
D3D11_STENCIL_OP_KEEP,
D3D11_STENCIL_OP_KEEP,
D3D11_STENCIL_OP_KEEP,
D3D11_COMPARISON_ALWAYS
},
{
D3D11_STENCIL_OP_KEEP,
D3D11_STENCIL_OP_KEEP,
D3D11_STENCIL_OP_KEEP,
D3D11_COMPARISON_ALWAYS
}
};
static D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc =
{
DXGI_FORMAT_D32_FLOAT,
D3D11_DSV_DIMENSION_TEXTURE2DMS,
0
};
static D3D11_RENDER_TARGET_VIEW_DESC backBufferRTVdesc =
{
DXGI_FORMAT_B8G8R8A8_UNORM,
D3D11_RTV_DIMENSION_TEXTURE2DMS,
{ 0 }
};
static D3D11_BLEND_DESC alphaBlendDesc =
{
FALSE,
FALSE,
{
TRUE,
D3D11_BLEND_SRC_ALPHA,
D3D11_BLEND_INV_SRC_ALPHA,
D3D11_BLEND_OP_ADD,
D3D11_BLEND_ZERO,
D3D11_BLEND_ZERO,
D3D11_BLEND_OP_ADD,
0x0F
}
};
static D3D11_VIEWPORT viewPort =
{
0, 0, 0, 0, 0, 1
};
static D3D_FEATURE_LEVEL featureLevel[] = { D3D_FEATURE_LEVEL_11_0 };
static D3D11_INPUT_ELEMENT_DESC inputElementDescs[] =
{
{
"POSITION", 0,
DXGI_FORMAT_R32G32B32_FLOAT,
0,
0, //AlignedByteOffset;
D3D11_INPUT_PER_VERTEX_DATA,
0
},
{
"NORMAL", 0,
DXGI_FORMAT_R32G32B32_FLOAT,
0,
12, //AlignedByteOffset;
D3D11_INPUT_PER_VERTEX_DATA,
0
},
{
"TEXCOORD", 0,
DXGI_FORMAT_R32G32B32A32_FLOAT,
0,
24, //AlignedByteOffset;
D3D11_INPUT_PER_VERTEX_DATA,
0
}
};
static DXGI_SWAP_CHAIN_DESC swapChainDesc =
{
{
0,
0,
{ 60, 1 },
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
DXGI_MODE_SCALING_UNSPECIFIED
},
{
8,
(UINT)-1
},
DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_RENDER_TARGET_OUTPUT,
1,
0,
TRUE,
DXGI_SWAP_EFFECT_DISCARD,
0
};
static D3D11_BUFFER_DESC constantBufferDesc =
{
(
4 + // float aspectRatio + 3 dummies
(4 * 4) + // float4 modelRotation
4 // pivot
) * sizeof(float),
D3D11_USAGE_DYNAMIC,
D3D11_BIND_CONSTANT_BUFFER,
D3D11_CPU_ACCESS_WRITE,
0,
0
};
#ifdef _DEBUG
#define D3D_DEVICE_FLAGS D3D11_CREATE_DEVICE_DEBUG
#else
#define D3D_DEVICE_FLAGS 0
#endif
#pragma bss_seg(".bss")
ID3D11Device* device = nullptr;
ID3D11DeviceContext* context = nullptr;
IDXGISwapChain* swapChain = nullptr;
ID3D11Texture2D* backBufferTexture = nullptr;
ID3D11Texture2D* depthStencilBuffer = nullptr;
ID3D11InputLayout* inputLayout = nullptr;
ID3D11BlendState* alphaBlendState = nullptr;
ID3D11RenderTargetView* backBufferRTV = nullptr;
ID3D11RasterizerState* rsSolidCullBack = nullptr;
ID3D11RasterizerState* rsWireframeCullBack = nullptr;
ID3D11RasterizerState* rsSolidCullNone = nullptr;
ID3D11RasterizerState* rsWireframeCullNone = nullptr;
ID3D11DepthStencilState* depthStencilState = nullptr;
ID3D11DepthStencilView* depthStencilView = nullptr;
ID3D11VertexShader* vertexShader = nullptr;
ID3D11PixelShader* pixelShader = nullptr;
ID3D11PixelShader* selPixelShader = nullptr;
ID3D11Buffer* vertexBuffer = nullptr;
ID3D11Buffer* indexBuffer = nullptr;
ID3D11Buffer* selIndexBuffer = nullptr;
ID3D11Buffer* constantBuffer = nullptr;
unsigned int indexCount = 0;
unsigned int selIndexCount = 0;
bool drawWireframe = false;
bool backFaceCulling = false;
#pragma code_seg(".code")
IntPtr Interop::Viewer::DevicePtr::get()
{
return IntPtr::IntPtr(device);
}
bool Interop::Viewer::Wireframe::get()
{
return drawWireframe;
}
void Interop::Viewer::Wireframe::set(bool value)
{
drawWireframe = value;
}
bool Interop::Viewer::BackFaceCulling::get()
{
return backFaceCulling;
}
void Interop::Viewer::BackFaceCulling::set(bool value)
{
backFaceCulling = value;
}
Interop::Viewer::Viewer()
{
}
void Interop::Viewer::Init(IntPtr _hWnd, int _iWidth, int _iHeight)
{
m_ArcBall = new ArcBall();
swapChainDesc.OutputWindow = (HWND)_hWnd.ToPointer();
swapChainDesc.BufferDesc.Width = _iWidth;
swapChainDesc.BufferDesc.Height = _iHeight;
D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D_DEVICE_FLAGS, featureLevel, 1, D3D11_SDK_VERSION, &swapChainDesc, &swapChain, &device, NULL, &context);
swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&backBufferTexture);
device->CreateRenderTargetView(backBufferTexture, &backBufferRTVdesc, &backBufferRTV);
device->CreateBlendState(&alphaBlendDesc, &alphaBlendState);
device->CreateDepthStencilState(&depthStencilDesc, &depthStencilState);
device->CreateRasterizerState(&rsSolidCullBackDesc, &rsSolidCullBack);
device->CreateRasterizerState(&rsWireframeCullBackDesc, &rsWireframeCullBack);
device->CreateRasterizerState(&rsSolidCullNoneDesc, &rsSolidCullNone);
device->CreateRasterizerState(&rsWireframeCullNoneDesc, &rsWireframeCullNone);
auto vsCode = System::IO::File::ReadAllBytes("MeshVertexShader.cso");
pin_ptr<unsigned char> pVsCode = &vsCode[0];
device->CreateVertexShader(pVsCode, vsCode->Length, NULL, &vertexShader);
device->CreateInputLayout(inputElementDescs, 3, pVsCode, vsCode->Length, &inputLayout);
auto psCode = System::IO::File::ReadAllBytes("MeshPixelShader.cso");
pin_ptr<unsigned char> pPsCode = &psCode[0];
device->CreatePixelShader(pPsCode, psCode->Length, NULL, &pixelShader);
psCode = System::IO::File::ReadAllBytes("SelectionPixelShader.cso");
pPsCode = &psCode[0];
device->CreatePixelShader(pPsCode, psCode->Length, NULL, &selPixelShader);
device->CreateBuffer(&constantBufferDesc, NULL, &constantBuffer);
CreateTextures(_iWidth, _iHeight);
}
template <typename T>
void CreateVertexBuffer(ID3D11Buffer** _vertexBuffer, const List<T>& _data)
{
D3D11_BUFFER_DESC vertexBufferDesc =
{
sizeof(T) * _data.Count(),
D3D11_USAGE_DEFAULT,
D3D11_BIND_VERTEX_BUFFER,
0,
0,
0
};
static D3D11_SUBRESOURCE_DATA vertexData =
{
&_data[0],
sizeof(T),
vertexBufferDesc.ByteWidth
};
device->CreateBuffer(&vertexBufferDesc, &vertexData, _vertexBuffer);
}
void CreateIndexBuffer(ID3D11Buffer** _indexBuffer, const List<unsigned int>& _data)
{
D3D11_BUFFER_DESC indexBufferDesc =
{
sizeof(unsigned int) * _data.Count(),
D3D11_USAGE_DEFAULT,
D3D11_BIND_INDEX_BUFFER,
0,
0,
0
};
D3D11_SUBRESOURCE_DATA indexData =
{
&_data[0],
sizeof(unsigned int),
indexBufferDesc.ByteWidth
};
device->CreateBuffer(&indexBufferDesc, &indexData, _indexBuffer);
}
void Interop::Viewer::LoadDocument(array<System::Byte>^ _data)
{
auto parser = new mt::Parser();
pin_ptr<unsigned char> pData = &_data[0];
auto doc = parser->ParseDocument(pData);
LoadOpMesh(doc->GetMesh(1));
}
void Interop::Viewer::LoadOpMesh(mt::OpMesh* _mesh)
{
m_Mesh = _mesh;
auto vertices = m_Mesh->GetMesh()->GetRawVertices();
auto indicies = m_Mesh->GetMesh()->GetIndices(false);
::CreateVertexBuffer(&vertexBuffer, vertices);
::CreateIndexBuffer(&indexBuffer, indicies);
indexCount = indicies.Count();
auto selIndicies = m_Mesh->GetSelectedFaceIndices();
selIndexCount = selIndicies.Count();
if (selIndexCount)
{
::CreateIndexBuffer(&selIndexBuffer, selIndicies);
}
}
void Interop::Viewer::CreateTextures(int _iWidth, int _iHeight)
{
viewPort.Width = (float)_iWidth;
viewPort.Height = (float)_iHeight;
D3D11_TEXTURE2D_DESC depthStencilBufferDesc =
{
(UINT)_iWidth,
(UINT)_iHeight,
1u,
1u,
DXGI_FORMAT_R32_TYPELESS,
{
8,
(UINT)-1
},
D3D11_USAGE_DEFAULT,
D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE,
0,
0
};
device->CreateTexture2D(&depthStencilBufferDesc, NULL, &depthStencilBuffer);
device->CreateDepthStencilView(depthStencilBuffer, &depthStencilViewDesc, &depthStencilView);
m_ArcBall->SetWindow((float)_iWidth, (float)_iHeight);
UpdateConstantBuffer();
}
void Interop::Viewer::UpdateConstantBuffer()
{
mt::Matrix mat;
if (m_ArcBall != NULL)
mat = m_ArcBall->GetRotationMatrix();
D3D11_MAPPED_SUBRESOURCE mapped;
context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
float* data = (float*)mapped.pData;
int i = 0;
data[i++] = (float)viewPort.Width / (float)viewPort.Height; // aspectRatio;
data[i++] = m_fDistanceToCenter; // distanceToCenter
data[i++] = 0; // unused
data[i++] = 0; // unused
data[i++] = mat.M11; // rotation matrix
data[i++] = mat.M21;
data[i++] = mat.M31;
data[i++] = mat.M41;
data[i++] = mat.M12;
data[i++] = mat.M22;
data[i++] = mat.M32;
data[i++] = mat.M42;
data[i++] = mat.M13;
data[i++] = mat.M23;
data[i++] = mat.M33;
data[i++] = mat.M43;
data[i++] = mat.M14;
data[i++] = mat.M24;
data[i++] = mat.M34;
data[i++] = mat.M44;
data[i++] = m_fPivotX;
data[i++] = m_fPivotY;
data[i++] = m_fPivotZ;
data[i++] = 1; // pivot.w
context->Unmap(constantBuffer, 0);
}
void Interop::Viewer::DisposeTextures()
{
depthStencilBuffer->Release();
depthStencilView->Release();
}
void Interop::Viewer::Resize(int _iWidth, int _iHeight)
{
if (swapChain == nullptr)
return;
DisposeTextures();
backBufferTexture->Release();
backBufferRTV->Release();
swapChain->ResizeBuffers(1, _iWidth, _iHeight, DXGI_FORMAT_B8G8R8A8_UNORM, 0);
swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&backBufferTexture);
device->CreateRenderTargetView(backBufferTexture, &backBufferRTVdesc, &backBufferRTV);
CreateTextures(_iWidth, _iHeight);
}
void Interop::Viewer::CaptureFrame()
{
m_bCaptureFrame = true;
}
void Interop::Viewer::MouseDown(bool _bLeftButton, int _iX, int _iY)
{
m_bDragging = true;
if (_bLeftButton)
{
m_bLeftDrag = true;
m_ArcBall->OnBegin((float)_iX, (float)_iY);
}
else
{
m_iLastDragX = _iX;
m_iLastDragY = _iY;
m_bLeftDrag = false;
}
}
void Interop::Viewer::Frame(const List<mt::RawVertex>& _vertices)
{
mt::vec3 vmin = mt::vec3(FLT_MAX, FLT_MAX, FLT_MAX);
mt::vec3 vmax = mt::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
for (auto vertex : _vertices)
{
vmin = mt::vec3::Min(vmin, vertex.Position);
vmax = mt::vec3::Max(vmax, vertex.Position);
}
auto center = (vmin + vmax) / 2;
float fMaxDistance = 0.0f;
for (auto vertex : _vertices)
{
fMaxDistance = max(fMaxDistance, mt::vec3::Distance(center, vertex.Position));
}
m_fDistanceToCenter = fMaxDistance * 2.0f;
m_fPivotX = center.x;
m_fPivotY = center.y;
m_fPivotZ = center.z;
UpdateConstantBuffer();
}
void Interop::Viewer::FrameSelection()
{
auto vertices = m_Mesh->GetSelectedFaceVertices();
Frame(vertices);
}
void Interop::Viewer::FrameAll()
{
auto vertices = m_Mesh->GetMesh()->GetRawVertices();
Frame(vertices);
}
void Interop::Viewer::MouseMove(int _iX, int _iY)
{
if (!m_bDragging)
return;
if (m_bLeftDrag)
{
m_ArcBall->OnMove((float)_iX, (float)_iY);
}
else
{
auto iDeltaX = _iX - m_iLastDragX;
auto iDeltaY = m_iLastDragY - _iY;
float fDeltaX = (float)iDeltaX / viewPort.Width;
float fDeltaY = (float)iDeltaY / viewPort.Height;
float mag = fDeltaX + fDeltaY;
if (mag > 0)
{
m_fDistanceToCenter /= 1.0f + mag;
}
else
{
m_fDistanceToCenter *= 1.0f - mag;
}
m_iLastDragX = _iX;
m_iLastDragY = _iY;
}
UpdateConstantBuffer();
}
void Interop::Viewer::MouseUp(int _iX, int _iY)
{
m_bDragging = false;
if (m_bLeftDrag)
{
m_ArcBall->OnEnd();
}
}
void Interop::Viewer::Render()
{
IDXGraphicsAnalysis* pGraphicsAnalysis = nullptr;
if (m_bCaptureFrame)
{
HRESULT getAnalysis = DXGIGetDebugInterface1(0, __uuidof(pGraphicsAnalysis), reinterpret_cast<void**>(&pGraphicsAnalysis));
if (FAILED(getAnalysis))
{
pGraphicsAnalysis = nullptr;
}
if (pGraphicsAnalysis != nullptr)
{
pGraphicsAnalysis->BeginCapture();
m_bCaptureFrame = false;
}
}
static char zero[] = { 0, 0, 0, 0 };
static float color[] = { 0, 0, 1, 1 };
UINT stride = sizeof(mt::RawVertex);
UINT offset = 0;
context->ClearRenderTargetView(backBufferRTV, color);
context->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
context->IASetInputLayout(inputLayout);
context->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R32_UINT, 0);
context->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
context->VSSetConstantBuffers(0, 1, &constantBuffer);
context->VSSetShader(vertexShader, NULL, 0);
context->PSSetShader(pixelShader, NULL, 0);
context->RSSetViewports(1, &viewPort);
if (backFaceCulling)
{
context->RSSetState(drawWireframe ? rsWireframeCullBack : rsSolidCullBack);
}
else
{
context->RSSetState(drawWireframe ? rsWireframeCullNone : rsSolidCullNone);
}
context->OMSetBlendState(alphaBlendState, NULL, -1);
context->OMSetDepthStencilState(depthStencilState, 0);
context->OMSetRenderTargets(1, &backBufferRTV, depthStencilView);
context->DrawIndexed(indexCount, 0, 0);
context->RSSetState(backFaceCulling ? rsSolidCullBack : rsSolidCullNone);
context->IASetIndexBuffer(selIndexBuffer, DXGI_FORMAT_R32_UINT, 0);
context->PSSetShader(selPixelShader, NULL, 0);
context->DrawIndexed(selIndexCount, 0, 0);
context->IASetIndexBuffer(NULL, DXGI_FORMAT_R32_UINT, 0);
context->IASetVertexBuffers(0, 1, (ID3D11Buffer* const*)zero, (const UINT*)zero, (const UINT*)zero);
context->OMSetRenderTargets(1, (ID3D11RenderTargetView* const*)zero, NULL);
if (pGraphicsAnalysis != nullptr)
{
pGraphicsAnalysis->EndCapture();
pGraphicsAnalysis->Release();
pGraphicsAnalysis = nullptr;
}
swapChain->Present(1, 0);
}

View File

@@ -0,0 +1,81 @@
// Interop.h
#pragma once
#include <d3d11.h>
using namespace System;
namespace Interop
{
public ref class Viewer
{
public:
static property Viewer^ Instance
{
public:
Viewer^ get()
{
if (s_Instance == nullptr)
{
s_Instance = gcnew Viewer();
}
return s_Instance;
}
}
property IntPtr DevicePtr
{
public:
IntPtr get();
}
property bool Wireframe
{
public:
bool get();
void set(bool _value);
}
property bool BackFaceCulling
{
public:
bool get();
void set(bool _value);
}
void Init(IntPtr _hWnd, int _iWidth, int _iHeight);
void Resize(int _iWidth, int _iHeight);
void MouseDown(bool _bLeftButton, int _iX, int _iY);
void MouseMove(int _iX, int _iY);
void MouseUp(int _iX, int _iY);
void FrameSelection();
void FrameAll();
void Render();
void LoadDocument(array<System::Byte>^ _data);
void LoadOpMesh(mt::OpMesh* _mesh);
void CaptureFrame();
private:
void Frame(const List<mt::RawVertex>& _vertices);
void UpdateConstantBuffer();
void DisposeTextures();
void CreateTextures(int _iWidth, int _iHeight);
Viewer();
mt::OpMesh* m_Mesh;
bool m_bCaptureFrame = false;
bool m_bLeftDrag = false;
bool m_bDragging = false;
int m_iLastDragX = 0;
int m_iLastDragY = 0;
float m_fPivotX = 0.0f;
float m_fPivotY = 0.0f;
float m_fPivotZ = 0.0f;
float m_fDistanceToCenter = 5.0f;
ArcBall* m_ArcBall;
static Viewer^ s_Instance;
};
}

View File

@@ -0,0 +1,193 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{FDEBD01E-0317-4400-9208-58D7DD7CEE44}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Lib</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)lib\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(ProjectName)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)lib\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(ProjectName)\</IntDir>
<IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<PreBuildEvent>
<Command>$(SolutionDir)bin\$(ConfigurationName)\Codegen.exe</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>Generating operator code...</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PreBuildEvent>
<Command>$(SolutionDir)bin\$(ConfigurationName)\Codegen.exe</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>Generating operator code...</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="mt\common\common.h" />
<ClInclude Include="mt\common\Linq.h" />
<ClInclude Include="mt\common\List.h" />
<ClInclude Include="mt\common\Map.h" />
<ClInclude Include="mt\common\Performancer.h" />
<ClInclude Include="mt\core\core.h" />
<ClInclude Include="mt\core\edge.h" />
<ClInclude Include="mt\core\Element.h" />
<ClInclude Include="mt\core\Face.h" />
<ClInclude Include="mt\core\Mesh.h" />
<ClInclude Include="mt\core\Path.h" />
<ClInclude Include="mt\core\Triangle.h" />
<ClInclude Include="mt\core\typedefs.h" />
<ClInclude Include="mt\core\Vertex.h" />
<ClInclude Include="mt\math\Bounds.h" />
<ClInclude Include="mt\math\Matrix.h" />
<ClInclude Include="mt\math\math.h" />
<ClInclude Include="mt\math\Plane.h" />
<ClInclude Include="mt\math\Quaternion.h" />
<ClInclude Include="mt\math\vec3.h" />
<ClInclude Include="mt\mt.h" />
<ClInclude Include="mt\operators\OpDocument.h" />
<ClInclude Include="mt\operators\operators.h" />
<ClInclude Include="mt\operators\OpMesh.h" />
<ClInclude Include="mt\parser\ops.h" />
<ClInclude Include="mt\parser\parser.h" />
<ClInclude Include="mt\tools\Calculate.h" />
<ClInclude Include="mt\tools\convert.h" />
<ClInclude Include="mt\tools\Copy.h" />
<ClInclude Include="mt\tools\CSG.h" />
<ClInclude Include="mt\tools\CSGBase.h" />
<ClInclude Include="mt\tools\Delete.h" />
<ClInclude Include="mt\tools\Detach.h" />
<ClInclude Include="mt\tools\Extrude.h" />
<ClInclude Include="mt\tools\FFD.h" />
<ClInclude Include="mt\tools\Flip.h" />
<ClInclude Include="mt\tools\Group.h" />
<ClInclude Include="mt\tools\Prefab.h" />
<ClInclude Include="mt\tools\Project.h" />
<ClInclude Include="mt\tools\Select.h" />
<ClInclude Include="mt\tools\Split.h" />
<ClInclude Include="mt\tools\Subdivide.h" />
<ClInclude Include="mt\tools\Tags.h" />
<ClInclude Include="mt\tools\tools.h" />
<ClInclude Include="mt\tools\Transform.h" />
<ClInclude Include="mt\tools\Triangulate.h" />
<ClInclude Include="mt\tools\typedefs.h" />
<ClInclude Include="mt\tools\Weld.h" />
<ClInclude Include="mt\typedef.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="mt\common\Performancer.cpp" />
<ClCompile Include="mt\core\Edge.cpp" />
<ClCompile Include="mt\core\Face.cpp" />
<ClCompile Include="mt\core\Mesh.cpp" />
<ClCompile Include="mt\core\Path.cpp" />
<ClCompile Include="mt\core\Triangle.cpp" />
<ClCompile Include="mt\core\Vertex.cpp" />
<ClCompile Include="mt\math\Matrix.cpp" />
<ClCompile Include="mt\math\Math.cpp" />
<ClCompile Include="mt\math\Plane.cpp" />
<ClCompile Include="mt\math\Quaternion.cpp" />
<ClCompile Include="mt\math\vec3.cpp" />
<ClCompile Include="mt\operators\OpDocument.cpp" />
<ClCompile Include="mt\operators\operators.cpp" />
<ClCompile Include="mt\operators\OpMesh.cpp" />
<ClCompile Include="mt\parser\parser.cpp" />
<ClCompile Include="mt\tools\Calculate.cpp" />
<ClCompile Include="mt\tools\Copy.cpp" />
<ClCompile Include="mt\tools\CSG.cpp" />
<ClCompile Include="mt\tools\CSGBase.cpp" />
<ClCompile Include="mt\tools\Delete.cpp" />
<ClCompile Include="mt\tools\Detach.cpp" />
<ClCompile Include="mt\tools\Extrude.cpp" />
<ClCompile Include="mt\tools\FFD.cpp" />
<ClCompile Include="mt\tools\Flip.cpp" />
<ClCompile Include="mt\tools\Group.cpp" />
<ClCompile Include="mt\tools\Prefab.cpp" />
<ClCompile Include="mt\tools\Project.cpp" />
<ClCompile Include="mt\tools\Select.cpp" />
<ClCompile Include="mt\tools\Split.cpp" />
<ClCompile Include="mt\tools\Subdivide.cpp" />
<ClCompile Include="mt\tools\Tags.cpp" />
<ClCompile Include="mt\tools\Transform.cpp" />
<ClCompile Include="mt\tools\Triangulate.cpp" />
<ClCompile Include="mt\tools\Weld.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="List.natvis" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,285 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\mt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\common\common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\common\Linq.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\common\List.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\common\Map.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\common\Performancer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\core\Element.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\core\Face.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\core\Mesh.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\core\Vertex.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\math\Bounds.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\math\math.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\math\Plane.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\math\Quaternion.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\math\vec3.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Prefab.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\math\Matrix.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\operators\operators.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\parser\parser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\parser\ops.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Calculate.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Transform.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Select.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\core\edge.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\typedef.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Weld.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\core\Triangle.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\core\core.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\core\Path.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Copy.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\CSG.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\CSGBase.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Delete.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Detach.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Extrude.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\FFD.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Flip.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Group.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Project.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Split.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Subdivide.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Tags.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\tools.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\Triangulate.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\typedefs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\operators\OpMesh.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\core\typedefs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\tools\convert.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mt\operators\OpDocument.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="mt\common\Performancer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\core\Edge.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\core\Face.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\core\Mesh.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\core\Vertex.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\math\Math.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\math\Plane.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\math\Quaternion.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\math\vec3.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Prefab.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\math\Matrix.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\parser\parser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Calculate.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Transform.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Select.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Weld.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\core\Triangle.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\core\Path.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Copy.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\CSG.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\CSGBase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Delete.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Detach.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Extrude.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\FFD.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Flip.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Group.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Project.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Split.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Subdivide.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Tags.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\tools\Triangulate.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\operators\operators.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\operators\OpMesh.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mt\operators\OpDocument.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="List.natvis" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="List&lt;*&gt;">
<DisplayString Condition="count == 0">empty</DisplayString>
<DisplayString>{{ size={count} }}</DisplayString>
<Expand>
<ArrayItems>
<Size>count</Size>
<ValuePointer>data</ValuePointer>
</ArrayItems>
<Item Name="[size]" ExcludeView="simple">count</Item>
<Item Name="[capacity]" ExcludeView="simple">capacity</Item>
</Expand>
</Type>
</AutoVisualizer>

View File

@@ -0,0 +1,296 @@
#pragma once
template<class TKey, class TValue>
struct Pair
{
Pair()
{
}
Pair(TKey key, TValue value)
: Key{ key }
, Value{ value }
{
}
TKey Key;
TValue Value;
};
namespace Linq
{
template<class T>
Map<T, T> ToSet(const List<T>& what)
{
Map<T, T> result;
for (const auto& element : what)
result.Add(element, element);
return result;
}
template<class T>
List<T> ToList(const T& what)
{
List<T> result;
result.Add(what);
return result;
}
template<class T>
List<T> ToList(T array[], size_t size)
{
List<T> result;
for (int i = 0; i < size; ++i)
result.Add(array[i]);
return result;
}
template<class T>
List<T> Concat(const List<T>& a, const List<T>& b)
{
List<T> result(a.Count() + b.Count());
for (auto i = 0; i < a.Count(); ++i)
result.Add(a[i]);
for (auto i = 0; i < b.Count(); ++i)
result.Add(b[i]);
return result;
}
template<class T>
List<T> Reverse(const List<T>& what)
{
List<T> result;
for (auto i = what.Count() - 1; i >= 0; --i)
result.Add(what[i]);
return result;
}
template<class T>
List<T> Distinct(const List<T>& what)
{
List<T> result(what.Count());
Map<T, bool> map;
for (const auto& element : what)
if (!map.ContainsKey(element))
{
map.Add(element, false);
result.Add(element);
}
return result;
}
template<class T>
void AddRange(List<T>& destination, const List<T>& what)
{
for (const auto& element : what)
destination.Add(element);
}
template<class T>
List<T> Except(const List<T>& what, const List<T>& except)
{
List<T> result;
for (const auto& element : what)
if (except.IndexOf(element) == -1)
result.Add(element);
return result;
}
template<class T>
List<T> Union(const List<T>& what, const List<T>& other)
{
List<T> result = what;
Linq::AddRange(result, other);
result = Linq::Distinct(result);
return result;
}
template<class T>
List<T> Intersect(const List<T>& what, const List<T>& other)
{
List<T> result;
for (const auto& element : what)
if (other.IndexOf(element) != -1)
result.Add(element);
return result;
}
template<class T, class TGroupValue, typename Func>
void GroupBy(const List<T>& what, Map<TGroupValue, List<T>>& dest, Func groupByFunc)
{
for (const auto& element : what)
{
auto key = groupByFunc(element);
List<T>* values;
if (dest.TryGetValue(key, values))
values->Add(element);
else
{
List<T> value(1);
value.Add(element);
dest.Add(key, value);
}
}
}
template<class T>
Map<T, int> Group(const List<T>& what)
{
Map<T, int> result;
for (const auto& element : what)
{
int cnt;
if (result.TryGetValue(element, cnt))
result[element] = ++cnt;
else
result.Add(element, 1);
}
return result;
}
template<class T>
Map<T, int> GroupValues(const List<T>& what)
{
Map<T, int> result;
for (const auto& element : what)
{
int cnt;
if (result.TryGetValue(element, cnt))
result[element] = ++cnt;
else
result.Add(element, 1);
}
return result;
}
template<class T, class Func>
T Max(const List<T>& what, Func sortCallback)
{
List<Pair<T, float>> sortData;
int maxId = 0;
float maxSortValue = -Math::Infinity;
for (int i = 0; i < what.Count(); ++i)
{
auto sortValue = sortCallback(what[i]);
if (i == 0 || maxSortValue < sortValue)
{
maxId = i;
maxSortValue = sortValue;
}
}
return what[maxId];
}
template<class T, class Func>
T Min(const List<T>& what, Func sortCallback)
{
List<Pair<T, float>> sortData;
int index = 0;
float sortValue = Math::Infinity;
for (int i = 0; i < what.Count(); ++i)
{
auto currentSortValue = sortCallback(what[i]);
if (i == 0 || sortValue > currentSortValue)
{
index = i;
sortValue = currentSortValue;
}
}
return what[index];
}
template<class T, class Func>
List<T> OrderByDescending(const List<T>& what, Func sortCallback)
{
List<T> result;
List<T> tmp = what;
while (tmp.Count() > 0)
{
auto max = Linq::Max(tmp, sortCallback);
tmp.Remove(max);
result.Add(max);
}
return result;
}
template<class T, class Func>
List<T> Where(const List<T>& what, Func whereCallback)
{
List<T> result;
for (auto& element : what)
if (whereCallback(element))
result.Add(element);
return result;
}
template<class T2, class T, class Func>
List<T2> Select(const List<T>& what, Func selectCallback)
{
List<T2> result;
for (auto& element : what)
result.Add(selectCallback(element));
return result;
}
template<class TResult, class T, class Func>
List<TResult> SelectMany(const List<T>& what, Func selectCallback)
{
List<TResult> result;
for (auto& element : what)
Linq::AddRange<TResult>(result, selectCallback(element));
return result;
}
template<class TResult, class T, class Func>
List<TResult> SelectUniqueMany(const List<T>& what, Func selectCallback)
{
List<TResult> result(what.Count());
Map<TResult, bool> map;
for (auto& element : what)
{
auto subResult = selectCallback(element);
for (const auto& subElement : subResult)
{
if (!map.ContainsKey(subElement))
{
map.Add(subElement, false);
result.Add(subElement);
}
}
}
return result;
}
template<class T, class Func>
bool Any(const List<T>& what, Func callback)
{
for (auto& element : what)
if (callback(element))
return true;
return false;
}
};

View File

@@ -0,0 +1,202 @@
#pragma once
#if _DEBUG
//#include <assert.h>
#define assert(a) if (!(a)) { throw #a; }
#endif
template<class T>
class List;
template<typename TSrc, typename TDest>
struct convert
{
static TDest Convert(const TSrc& srx)
{
static_assert(false, "Conversion is not possible, implement a custom conversion method.");
}
};
template<class T>
class List
{
public:
List(int capacity = 1)
: capacity{ capacity }
, count{0}
, data{ new T[capacity] }
{
}
List(List<T>&& other)
: count{ other.count }
, capacity{ other.capacity }
, data{ other.data }
{
other.count = 0;
other.capacity = 0;
other.data = nullptr;
}
List(const List<T>& other)
: count{other.count}
, capacity{ other.count }
, data{ new T[other.count] }
{
for (int index = 0; index < count; ++index)
data[index] = other.data[index];
}
~List()
{
delete[] data;
data = nullptr;
}
List<T>& operator=(List<T>&& other)
{
if (this != &other)
{
delete[] data;
count = other.count;
capacity = other.capacity;
data = other.data;
other.count = 0;
other.capacity = 0;
other.data = nullptr;
}
return *this;
}
List<T>& operator=(const List<T>& other)
{
count = other.count;
capacity = other.count;
data = new T[other.count];
for (int index = 0; index < count; ++index)
data[index] = other.data[index];
return *this;
}
void Add(const T& value)
{
if (count == capacity)
Grow();
data[count] = value;
count++;
}
void Remove(const T& value)
{
auto index = IndexOf(value);
if (index == -1)
return;
RemoveAt(index);
}
void RemoveAt(int index)
{
#if _DEBUG
assert(index >= 0 && index < count);
#endif
//data[index++].~T();
index++;
for (; index < count; ++index)
data[index - 1] = data[index];
count--;
}
bool Contains(const T& value) const
{
return IndexOf(value) != -1;
}
int IndexOf(const T& value) const
{
int i = 0;
for (; i < count; ++i)
if (data[i] == value)
break;
if (i == count)
return -1;
return i;
}
int Count() const
{
return count;
}
void Clear()
{
/*for (int i = 0; i < count; ++i)
data[i].~T();*/
count = 0;
/*capacity = 1;
delete[] data;
data = new T[capacity];*/
}
T& operator[](int index)
{
#if _DEBUG
assert(index >= 0 && index < count);
#endif
return data[index];
}
const T& operator[](int index) const
{
#if _DEBUG
assert(index >= 0 && index < count);
#endif
return data[index];
}
T* Get() const
{
return data;
}
T* begin() const
{
return data;
}
T* end() const
{
return data + count;
}
template<typename TDest>
operator TDest() const
{
return convert<List<T>, TDest>::Convert(*this);
}
private:
void Grow()
{
auto newCapacity = capacity ? capacity * 2 : 1;
T* newData = new T[newCapacity];
for (int i = 0; i < count; ++i)
newData[i] = data[i]; //newData[i] = (T&&)data[i];
capacity = newCapacity;
delete[] data;
data = newData;
}
private:
T* data;
int count;
int capacity;
};

View File

@@ -0,0 +1,317 @@
#pragma once
#if _DEBUG
//#include <assert.h>
#define assert(a) if (!(a)) { throw #a; }
#endif
template<typename T>
struct equality { static bool Equals(T a, T b) { return a == b; } };
template<typename T>
struct hashing
{
static int Generate(T a)
{
return (int)a;
}
};
// Finetune this value for better performance.
#define MAXBUCKETSIZE 10
template<typename TKey, typename TValue>
class Map
{
public:
struct Pair
{
int Hash;
TKey Key;
TValue Value;
};
private:
class HashBucket
{
public:
HashBucket(const List<Pair*> pairs)
: left{ nullptr }
, right{ nullptr }
, pairs { pairs }
{
if (pairs.Count() > 0)
centerHash = pairs[0]->Hash;
}
HashBucket()
: left{ nullptr }
, right{ nullptr }
{
}
~HashBucket()
{
delete left;
delete right;
}
HashBucket* GetValue(const TKey& key, int hash, bool& success, TValue*& result) const
{
if ((hash == centerHash || left == nullptr) && pairs.Count() != 0)
{
for (const auto& pair : pairs)
if (equality<const TKey&>::Equals(pair->Key, key))
{
success = true;
result = &pair->Value;
return nullptr;
}
return nullptr;
}
else if (left != nullptr)
return hash < centerHash ? left : right;
else
return nullptr;
}
HashBucket* Remove(const TKey key, int hash, Pair*& pairResult)
{
if (left == nullptr || hash == centerHash)
{
for (int i = 0, iLength = pairs.Count(); i < iLength; ++i)
{
auto pair = pairs[i];
if (equality<const TKey&>::Equals(pair->Key, key))
{
pairs.RemoveAt(i);
pairResult = pair;
return nullptr;
}
}
return nullptr;
}
else if (left != nullptr)
return hash < centerHash ? left : right;
else
return nullptr;
}
HashBucket* Add(Pair* pair)
{
if (pairs.Count() == 0)
centerHash = pair->Hash;
if (centerHash == pair->Hash || (left == nullptr && pairs.Count() < MAXBUCKETSIZE))
{
#ifdef _DEBUG
for (const auto& oldPair : pairs)
if (equality<const TKey&>::Equals(oldPair->Key, pair->Key))
assert("Key already exists in map" && false);
#endif
pairs.Add(pair);
}
else if (left == nullptr)
{
centerHash = pairs[pairs.Count() / 2]->Hash;
List<Pair*> leftPairs;
List<Pair*> centerPairs;
List<Pair*> rightPairs;
for (const auto& oldPair : pairs)
{
if (oldPair->Hash < centerHash)
leftPairs.Add(oldPair);
if (oldPair->Hash > centerHash)
rightPairs.Add(oldPair);
else
centerPairs.Add(oldPair);
}
left = new HashBucket(leftPairs);
right = new HashBucket(rightPairs);
pairs = centerPairs;
return Add(pair);
}
else
return pair->Hash < centerHash ? left : right;
return nullptr;
}
private:
int centerHash;
HashBucket* left;
HashBucket* right;
List<Pair*> pairs;
};
public:
Map()
: rootBucket{ new HashBucket() }
{
}
Map(Map&& other)
: pairs{ other.pairs }
, rootBucket{ other.rootBucket }
{
other.rootBucket = nullptr;
other.pairs.Clear();
}
Map(const Map& other)
{
throw "Implement me bitch!";
}
~Map()
{
for (int i = 0, iLength = pairs.Count(); i < iLength; ++i)
delete pairs[i];
delete rootBucket;
}
Map& operator=(Map&& other)
{
if (this != &other)
{
delete rootBucket;
pairs = other.pairs;
rootBucket = other.rootBucket;
other.rootBucket = nullptr;
other.pairs.Clear();
}
return *this;
}
void Add(const TKey& key, const TValue& value)
{
auto pair = new Pair();
pair->Key = key;
pair->Value = value;
pair->Hash = hashing<const TKey&>::Generate(key);
auto bucket = rootBucket;
do
{
bucket = bucket->Add(pair);
} while (bucket != nullptr);
pairs.Add(pair);
}
bool TryGetValue(const TKey& key, TValue& value) const
{
bool success = false;
auto hash = hashing<const TKey&>::Generate(key);
TValue* result;
auto bucket = rootBucket;
do
{
bucket = bucket->GetValue(key, hash, success, result);
} while (bucket != nullptr);
if (success)
value = *result;
return success;
}
bool TryGetValue(const TKey& key, TValue*& value) const
{
bool success = false;
auto hash = hashing<const TKey&>::Generate(key);
TValue* result;
auto bucket = rootBucket;
do
{
bucket = bucket->GetValue(key, hash, success, result);
} while (bucket != nullptr);
if (success)
value = result;
return success;
}
void Remove(const TKey& key)
{
auto hash = hashing<const TKey&>::Generate(key);
auto bucket = rootBucket;
Pair* pair;
do
{
bucket = bucket->Remove(key, hash, pair);
} while (bucket != nullptr);
if (pair != nullptr)
{
pairs.Remove(pair);
}
}
TValue& GetValue(const TKey& key) const
{
TValue* result;
bool success = false;
auto hash = hashing<const TKey&>::Generate(key);
auto bucket = rootBucket;
do
{
bucket = bucket->GetValue(key, hash, success, result);
} while (bucket != nullptr);
#if _DEBUG
assert("No value found!" && success);
#endif
return *result;
}
Pair** begin() const
{
return pairs.begin();
}
Pair** end() const
{
return pairs.end();
}
int Count() const
{
return pairs.Count();
}
bool ContainsKey(const TKey& key) const
{
TValue tmp;
return TryGetValue(key, tmp);
}
TValue& operator[](const TKey& key)
{
return GetValue(key);
}
const TValue& operator[](const TKey& key) const
{
return GetValue(key);
}
List<TValue> GetValues() const
{
List<TValue> result;
for (const auto& pair : pairs)
result.Add(pair->Value);
return result;
}
private:
HashBucket* rootBucket;
List<Pair*> pairs;
};

View File

@@ -0,0 +1,162 @@
#include "stdafx.h"
#if _DEBUG
#include "Windows.h"
#include <iostream>
namespace
{
const long long g_Frequency = []() -> long long
{
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
return frequency.QuadPart;
}();
}
HighResClock::time_point HighResClock::now()
{
LARGE_INTEGER count;
QueryPerformanceCounter(&count);
return time_point(duration(count.QuadPart * static_cast<rep>(period::den) / g_Frequency));
}
Performancer Performancer::Instance;
int Performancer::RegisterMethod(const std::string& name, const std::string& fullName)
{
data.push_back({ name, fullName });
return data.size() - 1;
}
void Performancer::AddData(int index, long long duration)
{
data[index].Add(duration);
}
struct my_numpunct : std::numpunct<char> {
std::string do_grouping() const { return "\03"; }
};
void Performancer::Dump()
{
auto sorted = data;
std::sort(sorted.begin(), sorted.end(), [](const PerformancerData& lhs, const PerformancerData& rhs)
{
return lhs.Elapsed > rhs.Elapsed;
});
long long total = 0;
long long average = 0;
size_t maxNameLength = 0;
for (const auto& data : sorted)
{
maxNameLength = data.Name.size() > maxNameLength ? data.Name.size() : maxNameLength;
total += data.Elapsed;
average += data.Elapsed / data.Calls;
}
maxNameLength += 2;
const int usWidth = 20;
std::locale loc(std::cout.getloc(), new my_numpunct);
std::stringstream ss;
ss.imbue(loc);
ss << "Performancer summary:\n";
ss.width(10);
ss << std::left << "Rank";
ss.width(maxNameLength);
ss << std::left << "Name";
ss.width(usWidth);
ss << std::left << "Calls";
ss.width(usWidth);
ss << std::left << "Min (us)";
ss.width(usWidth);
ss << std::left << "Max (us)";
ss.width(usWidth);
ss << std::left << "Average (us)";
ss.width(usWidth);
ss << std::left << "Average (%)";
ss.width(usWidth);
ss << std::left << "Total (us)";
ss.width(usWidth);
ss << std::left << "Total (%)";
ss.width(usWidth);
ss << "Full Name";
ss << "\n";
int i = 0;
for (const auto& data : sorted)
{
i++;
ss.width(10);
ss << std::left << i;
ss.width(maxNameLength);
ss << std::left << data.Name;
ss.width(usWidth);
ss << std::left << data.Calls;
ss.width(usWidth);
ss << std::left << data.Min;
ss.width(usWidth);
ss << std::left << data.Max;
ss.width(usWidth);
ss << std::left << data.Elapsed / data.Calls;
ss.width(usWidth);
ss << std::left << (int)(((data.Elapsed / data.Calls) / (double)average) * 100);
ss.width(usWidth);
ss << std::left << data.Elapsed;
ss.width(usWidth);
ss << std::left << (int)((data.Elapsed / (double)total) * 100);
ss << data.FullName;
ss << "\n";
}
ss << "\n";
OutputDebugStringA(ss.str().c_str());
}
PerformancerEntry::PerformancerEntry(int index)
: index{ index }
, start{ HighResClock::now() }
{
}
PerformancerEntry::~PerformancerEntry()
{
auto end = HighResClock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
Performancer::Instance.AddData(index, duration);
}
PerformancerData::PerformancerData(const std::string& name, const std::string& fullName)
: Name(name)
, FullName(fullName)
, Calls{ 0 }
, Elapsed{ 0 }
, Max{ 0 }
, Min{ 0 }
{
}
void PerformancerData::Add(long long duration)
{
if (Calls == 0)
{
Min = duration;
Max = duration;
}
else
{
Min = Min > duration ? duration : Min;
Max = Max < duration ? duration : Max;
}
Elapsed += duration;
Calls++;
}
#endif

View File

@@ -0,0 +1,65 @@
#pragma once
#include <vector>
#include <algorithm>
#include <sstream>
class PerformancerData
{
public:
PerformancerData(const std::string& name, const std::string& fullName);
void Add(long long duration);
std::string Name;
std::string FullName;
long long Calls;
long long Elapsed;
long long Max;
long long Min;
};
#include <chrono>
struct HighResClock
{
typedef long long rep;
typedef std::nano period;
typedef std::chrono::duration<rep, period> duration;
typedef std::chrono::time_point<HighResClock> time_point;
static const bool is_steady = true;
static time_point now();
};
class Performancer
{
public:
int RegisterMethod(const std::string& name, const std::string& fullName);
void AddData(int index, long long duration);
void Dump();
static Performancer Instance;
private:
std::vector<PerformancerData> data;
};
class PerformancerEntry
{
public:
PerformancerEntry(int index);
~PerformancerEntry();
private:
std::chrono::time_point<HighResClock> start;
int index;
};
#define PERFORMANCER \
static int __performancerIndex = Performancer::Instance.RegisterMethod( __FUNCTION__, __FUNCSIG__); \
PerformancerEntry __performancerEntry(__performancerIndex);
#define PERFORMANCER_DUMP Performancer::Instance.Dump();

View File

@@ -0,0 +1,5 @@
#pragma once
#include "List.h"
#include "Map.h"
#include "Linq.h"

View File

@@ -0,0 +1,99 @@
#include "stdafx.h"
namespace mt
{
Edge::Edge()
: mesh{ nullptr }
, vertices{ 2 }
{
PERFORMANCER;
}
Edge::Edge(Vertex* a, Vertex* b)
: mesh{ nullptr }
, vertices{ 2 }
{
PERFORMANCER;
vertices.Add(a);
vertices.Add(b);
}
Edge::~Edge()
{
PERFORMANCER;
}
Vertex* Edge::GetOtherVertex(Vertex* vertex) const
{
PERFORMANCER;
return vertices[0] == vertex ? vertices[1] : vertices[0];
}
const VertexList& Edge::GetVertices() const
{
PERFORMANCER;
return vertices;
}
const FaceList& Edge::GetFaces() const
{
PERFORMANCER;
return faces;
}
EdgeList Edge::GetEdges() const
{
PERFORMANCER;
auto result = Linq::SelectUniqueMany<Edge*>(faces, [](Face* face) { return face->GetEdges(); });
result.Remove(const_cast<Edge*>(this));
return result;
}
vec3 Edge::GetDirection() const
{
PERFORMANCER;
auto direction = vertices[1]->Position - vertices[0]->Position;
direction.Normalize();
return direction;
}
vec3 Edge::GetCenter() const
{
PERFORMANCER;
return (vertices[1]->Position + vertices[0]->Position) * 0.5f;
}
float Edge::GetLength() const
{
PERFORMANCER;
auto length = vertices[0]->Position - vertices[1]->Position;
return length.GetLength();
}
Edge* Edge::GetHalfEdge(Face* face) const
{
PERFORMANCER;
auto edges = face->GetEdges();
auto index = edges.IndexOf(const_cast<Edge*>(this));
auto faceVertices = face->GetVertices();
auto next = (index + 1) % faceVertices.Count();
auto newEdge = new Edge(faceVertices[index], faceVertices[next]);
newEdge->faces = faces;
return newEdge;
}
}

View File

@@ -0,0 +1,103 @@
#pragma once
namespace mt
{
const unsigned int InvalidElementIndex = -1;
template<class TData, class TMetaData, class TWrapper>
class Element
{
friend class Mesh;
friend class ElementSection;
public:
struct ElementSection
{
friend class Element;
friend class Mesh;
List<TData> Data;
List<TMetaData> MetaData;
ElementSection()
{
}
ElementSection(const ElementSection& other)
: Data(other.Data)
, MetaData(other.MetaData)
{
}
void operator=(const ElementSection& other)
{
Data = other.Data;
MetaData = other.MetaData;
}
~ElementSection()
{
for (auto& element : _wrapperList)
element->_isDetached = true;
}
TWrapper Get(unsigned int index, bool trackIndexChanges = false)
{
return{ index, this, _mesh, trackIndexChanges };
}
private:
List<Element*> _wrapperList;
Mesh* _mesh;
};
Element(unsigned int index, ElementSection* section, Mesh* mesh, bool trackIndexChanges)
: _index(index)
, _section(section)
, _isDetached(!trackIndexChanges)
, _mesh(mesh)
{
if (trackIndexChanges)
_section->_wrapperList.Add(this);
}
~Element()
{
if (!_isDetached)
_section->_wrapperList.Remove(this);
}
Element& operator=(const Element& other)
{
_isDetached = other._isDetached;
_index = other._index;
_section = other._section;
return *this;
}
TData& GetData() const
{
return _section->Data[_index];
}
void SetData(const TData& data)
{
_section->Data[_index] = data;
}
TMetaData& GetMetaData() const
{
return _section->MetaData[_index];
}
int GetIndex() const
{
return _index;
}
protected:
bool _isDetached;
unsigned int _index;
ElementSection* _section;
Mesh* _mesh;
};
}

View File

@@ -0,0 +1,304 @@
#include "stdafx.h"
namespace mt
{
Face::Face()
{
PERFORMANCER;
}
Face::Face(Vertex* a, Vertex* b, Vertex* c, Vertex* d)
: materialId{ 0 }
//, uvGenerator{ nullptr }
, mesh{ nullptr }
{
PERFORMANCER;
vertices.Add(a);
vertices.Add(b);
vertices.Add(c);
if (d != nullptr)
vertices.Add(d);
}
Face::Face(const VertexList& otherVertices)
: materialId{ 0 }
//, uvGenerator{ nullptr }
, mesh{ nullptr }
{
PERFORMANCER;
vertices = otherVertices;
}
Face::~Face()
{
PERFORMANCER;
}
vec3 Face::GetNormal() const
{
PERFORMANCER;
vec3 normal;
auto cnt = vertices.Count();
for (int i = 0; i < cnt; i++)
normal += vec3::Cross(vertices[i]->Position, vertices[(i + 1) % cnt]->Position); // cross product
normal.Normalize();
return normal;
}
Plane Face::GetPlane() const
{
return Plane(vertices[0]->Position, vertices[1]->Position, vertices[2]->Position);
}
bool Face::IsTriangle() const
{
PERFORMANCER;
return vertices.Count() == 3;
}
List<Triangle> Face::GetTriangles() const
{
PERFORMANCER;
List<Triangle> result(2);
if (vertices.Count() == 3)
result.Add({ vertices[0], vertices[1], vertices[2] });
else
{
result.Add({ vertices[0], vertices[1], vertices[2] });
result.Add({ vertices[2], vertices[3], vertices[0] });
}
return result;
}
List<unsigned int> Face::GetIndices(bool allowQuads) const
{
PERFORMANCER;
if (allowQuads)
return Linq::Select<unsigned int>(vertices, [](Vertex* vertex) { return vertex->GetIndex(); });
const int quadIndices[7] =
{
6,
0, 1, 2,
2, 3, 0
};
const int triangleIndices[4] =
{
3,
0, 1, 2
};
const int* metaIndices = vertices.Count() == 3 ? triangleIndices : quadIndices;
List<unsigned int> result;
for (int i = 0; i < metaIndices[0]; ++i)
result.Add(vertices[metaIndices[i + 1]]->GetIndex());
return result;
}
void Face::FlipNormal()
{
PERFORMANCER;
vertices = Linq::Reverse(vertices);
}
void Face::FlipNormal(const vec3& dir)
{
PERFORMANCER;
if (vec3::Dot(GetNormal(), dir) < 0)
FlipNormal();
}
FaceList Face::Triangulate()
{
PERFORMANCER;
FaceList result;
if (IsTriangle() && !IsDegenerated())
{
result.Add(this);
return result;
}
auto triangles = GetTriangles();
for (const auto& triangle : triangles)
{
if (triangle.IsDegenerated())
continue;
auto newFace = new Face(triangle.GetVertices());
newFace->CopyProperties(this);
mesh->AddFace(newFace);
result.Add(newFace);
}
mesh->RemoveFace(this);
return result;
}
void Face::FlipEdge()
{
if (IsTriangle())
return;
auto oldVertices = vertices;
vertices.Clear();
vertices.Add(oldVertices[1]);
vertices.Add(oldVertices[2]);
vertices.Add(oldVertices[3]);
vertices.Add(oldVertices[0]);
}
bool Face::IsDegenerated() const
{
PERFORMANCER;
auto triangles = GetTriangles();
for (const auto& triangle : triangles)
if (!triangle.IsDegenerated())
return false;
return true;
}
bool Face::RegainIntegrity()
{
PERFORMANCER;
auto triangles = GetTriangles();
for (const auto& triangle : triangles)
if (triangle.IsDegenerated())
{
vertices = Linq::Distinct(vertices);
return vertices.Count() > 2;
}
return true;
}
void Face::CopyProperties(Face* other, bool merge)
{
PERFORMANCER;
if (!merge)
tags = other->tags;
else
tags = Linq::Union(tags, other->tags);
materialId = other->materialId;
}
Mesh* Face::GetMesh() const
{
PERFORMANCER;
return mesh;
}
const VertexList& Face::GetVertices() const
{
PERFORMANCER;
return vertices;
}
FaceList Face::GetFaces() const
{
PERFORMANCER;
auto result = Linq::SelectUniqueMany<Face*>(edges, [](Edge* edge) { return edge->GetFaces(); });
result.Remove(const_cast<Face*>(this));
return result;
}
const EdgeList& Face::GetEdges() const
{
PERFORMANCER;
return edges;
}
bool Face::HasTag(int tag) const
{
PERFORMANCER;
return tags.IndexOf(tag) != -1;
}
bool Face::HasTagsAny(const List<int>& tagsToCheck) const
{
PERFORMANCER;
return Linq::Intersect(tags, tagsToCheck).Count() > 0;
}
bool Face::HasTagsAll(const List<int>& tagsToCheck) const
{
PERFORMANCER;
return Linq::Intersect(tags, tagsToCheck).Count() == tags.Count();
}
void Face::AddTag(int tag)
{
PERFORMANCER;
if (HasTag(tag))
return;
tags.Add(tag);
}
void Face::RemoveTag(int tag)
{
PERFORMANCER;
if (!HasTag(tag))
return;
tags.Remove(tag);
}
List<int> Face::GetTags() const
{
PERFORMANCER;
return tags;
}
void Face::SetMaterialId(int materialId)
{
PERFORMANCER;
this->materialId = materialId;
}
int Face::GetMaterialId() const
{
PERFORMANCER;
return materialId;
}
/*void Face::SetUVGenerator(UVGeneratorBase* generator)
{
PERFORMANCER;
uvGenerator = generator;
}
UVGeneratorBase* Face::GetUVGenerator() const
{
PERFORMANCER;
return uvGenerator;
}*/
}

View File

@@ -0,0 +1,63 @@
#pragma once
#include "typedefs.h"
namespace mt
{
class Face
{
friend class Mesh;
public:
Face();
Face(Vertex* a, Vertex* b, Vertex* c, Vertex* d = nullptr);
Face(const VertexList& vertices);
~Face();
vec3 GetNormal() const;
Plane GetPlane() const;
bool IsTriangle() const;
void FlipNormal();
void FlipNormal(const vec3& dir);
FaceList Triangulate();
void FlipEdge();
bool IsDegenerated() const;
bool RegainIntegrity();
const VertexList& GetVertices() const;
FaceList GetFaces() const;
const EdgeList& GetEdges() const;
bool HasTag(int tag) const;
bool HasTagsAny(const List<int>& tagsToCheck) const;
bool HasTagsAll(const List<int>& tagsToCheck) const;
void AddTag(int tag);
void RemoveTag(int tag);
List<int> GetTags() const;
void SetMaterialId(int materialId);
int GetMaterialId() const;
//void SetUVGenerator(UVGeneratorBase* generator);
//UVGeneratorBase* GetUVGenerator() const;
List<unsigned int> GetIndices(bool allowQuads) const;
void CopyProperties(Face* other, bool merge = false);
Mesh* GetMesh() const;
operator FaceList() { FaceList result; result.Add(const_cast<Face*>(this)); return result; }
private:
List<Triangle> GetTriangles() const;
List<int> GetMetaIndices() const;
List<int> tags;
//UVGeneratorBase* uvGenerator;
VertexList vertices;
EdgeList edges;
int materialId;
Mesh* mesh;
};
}

View File

@@ -0,0 +1,302 @@
#include "stdafx.h"
namespace mt
{
Mesh::Mesh()
{
PERFORMANCER;
}
Mesh::~Mesh()
{
PERFORMANCER;
}
const VertexList& Mesh::GetVertices() const
{
PERFORMANCER;
return vertices;
}
List<RawVertex> Mesh::GetRawVertices() const
{
PERFORMANCER;
return Linq::Select<RawVertex>(vertices, [](Vertex* vertex)
{
return vertex->GetRaw();
});
}
const FaceList& Mesh::GetFaces() const
{
PERFORMANCER;
return faces;
}
EdgeList Mesh::GetEdges() const
{
PERFORMANCER;
return Linq::SelectUniqueMany<Edge*>(faces, [](Face* face) { return face->GetEdges(); });
}
void Mesh::AddFace(Face* faceToAdd)
{
PERFORMANCER;
faceToAdd->mesh = this;
faces.Add(faceToAdd);
auto& faceVertices = faceToAdd->vertices;
auto& faceEdges = faceToAdd->edges;
faceEdges.Add(FindEdge(faceVertices[0], faceVertices[1]));
faceEdges.Add(FindEdge(faceVertices[1], faceVertices[2]));
if (faceToAdd->IsTriangle())
faceEdges.Add(FindEdge(faceVertices[2], faceVertices[0]));
else
{
faceEdges.Add(FindEdge(faceVertices[2], faceVertices[3]));
faceEdges.Add(FindEdge(faceVertices[3], faceVertices[0]));
}
for (const auto& edge : faceEdges)
edge->faces.Add(faceToAdd);
}
// Removing a face results in an update to all affected elements of the face
// We remove the face from the meshs face list and from all neighbourfaces, edges and vertices.
void Mesh::RemoveFace(Face* faceToRemove)
{
PERFORMANCER;
faceToRemove->mesh = nullptr;
faces.Remove(faceToRemove);
auto& faceEdges = faceToRemove->edges;
for (const auto& edge : faceEdges)
RemoveFaceFromEdge(edge, faceToRemove);
faceEdges.Clear();
}
Edge* Mesh::FindEdge(Vertex* a, Vertex* b)
{
PERFORMANCER;
for (const auto& existingEdge : a->edges)
for (const auto& edgeVertex : existingEdge->vertices)
if (edgeVertex == b)
return existingEdge;
Edge* newEdge = new Edge{ a, b };
newEdge->mesh = this;
a->edges.Add(newEdge);
b->edges.Add(newEdge);
if (a->mesh == nullptr)
{
a->mesh = this;
vertices.Add(a);
}
if (b->mesh == nullptr)
{
b->mesh = this;
vertices.Add(b);
}
return newEdge;
}
List<unsigned int> Mesh::GetIndices(bool allowQuads)
{
PERFORMANCER;
UpdateIndices();
return Linq::SelectMany<unsigned int>(faces, [allowQuads](Face* face) { return face->GetIndices(allowQuads); });
}
void Mesh::UpdateIndices()
{
PERFORMANCER;
for (int i = 0, iLength = vertices.Count(); i < iLength; ++i)
vertices[i]->index = i;
}
FaceList Mesh::SplitEdge(Edge* edgeToSplit, Vertex* splitVertex)
{
PERFORMANCER;
auto attachedFaces = edgeToSplit->faces;
FaceList allNewFaces;
for (const auto& attachedFace : attachedFaces)
{
auto normal = attachedFace->GetNormal();
auto faceEdges = attachedFace->edges;
FaceList newFaces;
for (const auto& faceEdge : faceEdges)
{
if (faceEdge != edgeToSplit)
{
auto newFace = new Face(faceEdge->vertices[0], faceEdge->vertices[1], splitVertex);
newFace->FlipNormal(normal);
newFace->CopyProperties(attachedFace);
AddFace(newFace);
allNewFaces.Add(newFace);
newFaces.Add(newFace);
}
}
TriggerFaceReplaced(attachedFace, newFaces);
RemoveFace(attachedFace);
}
return allNewFaces;
}
void Mesh::ReplaceVertexFromFaces(const FaceList& faces, Vertex* oldVertex, Vertex* newVertex)
{
PERFORMANCER;
for (const auto& face : faces)
{
bool isRemoved = false;
for (int i = 0; i < face->vertices.Count(); ++i)
if (face->vertices[i] == oldVertex)
{
if (!isRemoved)
{
RemoveFace(face);
isRemoved = true;
}
face->vertices[i] = newVertex;
}
if (isRemoved)
AddFace(face);
}
}
void Mesh::ReplaceVertices(const VertexList& verticesToReplace, Vertex* newVertex)
{
PERFORMANCER;
for (const auto& vertex : verticesToReplace)
{
auto faces = vertex->GetFaces();
ReplaceVertexFromFaces(faces, vertex, newVertex);
}
}
void Mesh::RemoveFaceFromEdge(Edge* edge, Face* face)
{
PERFORMANCER;
edge->faces.Remove(face);
if (edge->faces.Count() == 0)
{
edge->mesh = nullptr;
for (const auto& vertex : edge->vertices)
RemoveEdgeFromVertex(vertex, edge);
delete edge;
}
}
void Mesh::RemoveEdgeFromVertex(Vertex* vertex, Edge* edge)
{
PERFORMANCER;
vertex->edges.Remove(edge);
if (vertex->edges.Count() == 0)
{
vertex->mesh = nullptr;
vertices.Remove(vertex);
}
}
Map<int, FaceList> Mesh::GetSubMeshs()
{
PERFORMANCER;
UpdateIndices();
Map<int, FaceList> groups;
Linq::GroupBy(this->GetFaces(), groups, [](Face* face)
{
return face->GetMaterialId();
});
return groups;
}
void Mesh::StartAutoUpdate(FaceList& faceList)
{
PERFORMANCER;
autoUpdateHandles.Add(&faceList);
}
void Mesh::StopAutoUpdate(FaceList& handle)
{
PERFORMANCER;
autoUpdateHandles.Remove(&handle);
}
void Mesh::TriggerFaceReplaced(Face* oldFace, const FaceList& newFaces)
{
PERFORMANCER;
for (const auto& faces : autoUpdateHandles)
{
auto index = faces->IndexOf(oldFace);
if (index == -1)
continue;
faces->RemoveAt(index);
for (auto const& newFace : newFaces)
if (!faces->Contains(newFace))
faces->Add(newFace);
}
}
///////////////////////////////////////////////
AutoFaceList::AutoFaceList(FaceList&& other)
: FaceList(other)
{
Init();
}
AutoFaceList::AutoFaceList(const FaceList& other)
: FaceList(other)
{
Init();
}
AutoFaceList::~AutoFaceList()
{
if (mesh != nullptr)
mesh->StopAutoUpdate(*this);
}
void AutoFaceList::Init()
{
if (Count() == 0)
{
mesh = nullptr;
return;
}
mesh = (*this)[0]->GetMesh();
mesh->StartAutoUpdate(*this);
}
}

View File

@@ -0,0 +1,67 @@
#pragma once
#include "typedefs.h"
namespace mt
{
class Mesh
{
public:
Mesh();
~Mesh();
const VertexList& GetVertices() const;
List<RawVertex> GetRawVertices() const;
const FaceList& GetFaces() const;
EdgeList GetEdges() const;
void AddFace(Face* face);
void RemoveFace(Face* face);
FaceList SplitEdge(Edge* edgeToSplit, Vertex* splitVertex);
void ReplaceVertexFromFaces(const FaceList& faces, Vertex* oldVertex, Vertex* newVertex);
void ReplaceVertices(const VertexList& verticesToReplace, Vertex* newVertex);
List<unsigned int> GetIndices(bool allowQuads);
Map<int, FaceList> GetSubMeshs();
void StartAutoUpdate(FaceList& faceList);
void StopAutoUpdate(FaceList& faceList);
void TriggerFaceReplaced(Face* oldFace, const FaceList& newFaces);
void UpdateIndices();
private:
Edge* FindEdge(Vertex* a, Vertex* b);
void RemoveFaceFromEdge(Edge* edge, Face* face);
void RemoveEdgeFromVertex(Vertex* vertex, Edge* edge);
private:
VertexList vertices;
FaceList faces;
List<FaceList*> autoUpdateHandles;
};
// AutoFaceList will watch for changes (replace & remove) on the content of this list and will reflect these.
// This means, when an operation removes a face which is contained in the AutoFaceList it will removed from the
// list even when the operation was performed on a different list.
// Example:
// FaceList a;
// .. // fill a
// AutoFaceList b(a);
// mt::Delete(a); // b.Count() == 0;
class AutoFaceList : public FaceList
{
public:
AutoFaceList(FaceList&& other);
AutoFaceList(const FaceList& other);
~AutoFaceList();
private:
void Init();
Mesh* mesh;
};
}

View File

@@ -0,0 +1,100 @@
#include "stdafx.h"
namespace mt
{
void Path::SetPoints(const List<vec3>& points)
{
PERFORMANCER;
this->points = points;
}
void Path::SetScale(const List<float>& scale)
{
PERFORMANCER;
this->scale = scale;
}
void Path::SetRotation(const List<float>& rotation)
{
PERFORMANCER;
this->rotation = rotation;
}
vec3 Path::GetPoint(float t) const
{
PERFORMANCER;
vec3 p1;
vec3 p2;
vec3 p0;
vec3 p3;
Path::GetValues(points, t, p0, p1, p2, p3);
return Spline(p0, p1, p2, p3, t);
}
float Path::GetScale(float t) const
{
PERFORMANCER;
if (scale.Count() == 0)
return 1.0f;
float p1;
float p2;
float p0;
float p3;
Path::GetValues(scale, t, p0, p1, p2, p3);
return Math::Max(0, Spline(p0, p1, p2, p3, t));
}
float Path::GetRotation(float t) const
{
PERFORMANCER;
if (rotation.Count() == 0)
return 0.0f;
float p1;
float p2;
float p0;
float p3;
Path::GetValues(rotation, t, p0, p1, p2, p3);
return Spline(p0, p1, p2, p3, t);
}
vec3 Path::GetDirection(float t) const
{
PERFORMANCER;
const float delta = 0.0001f;
auto a = GetPoint(t);
auto b = GetPoint(t + delta);
b -= a;
b.Normalize();
return b;
}
float Path::Spline(float p0, float p1, float p2, float p3, float t)
{
PERFORMANCER;
return 0.5f *((2 * p1) +
(-p0 + p2) * t +
(2 * p0 - 5 * p1 + 4 * p2 - p3) * (t*t) +
(-p0 + 3 * p1 - 3 * p2 + p3) * (t*t*t));
}
vec3 Path::Spline(const vec3& p0, const vec3& p1, const vec3& p2, const vec3& p3, float t)
{
PERFORMANCER;
return
{
Spline(p0.x, p1.x, p2.x, p3.x, t),
Spline(p0.y, p1.y, p2.y, p3.y, t),
Spline(p0.z, p1.z, p2.z, p3.z, t)
};
}
}

View File

@@ -0,0 +1,43 @@
#pragma once
namespace mt
{
class Path
{
public:
void SetPoints(const List<vec3>& points);
void SetScale(const List<float>& scale);
void SetRotation(const List<float>& rotation);
vec3 GetPoint(float t) const;
float GetScale(float t) const;
float GetRotation(float t) const;
vec3 GetDirection(float t) const;
private:
template <typename T> static void GetValues(const List<T>& source, float& t, T& p0, T& p1, T& p2, T& p3)
{
auto maxT = source.Count();
auto p1Index = (int)Math::Min(t * maxT, maxT - 1.0f);
auto p0Index = (int)Math::Max(p1Index - 1.0f, 0.0f);
auto p2Index = (int)Math::Min(p1Index + 1.0f, maxT - 1.0f);
auto p3Index = (int)Math::Min(p2Index + 1.0f, maxT - 1.0f);
p1 = source[p1Index];
p2 = p1Index == p2Index ? p1 + (p1 - source[p0Index]) : source[p2Index];
p0 = p0Index == p1Index ? p1 - (p2 - p1) : source[p0Index];
p3 = p3Index == p2Index ? p1 + (p2 - p1) : source[p3Index];
t = (t - (1.0f / maxT * p1Index)) / (1.0f / maxT);
}
static float Spline(float p0, float p1, float p2, float p3, float t);
static vec3 Spline(const vec3& p0, const vec3& p1, const vec3& p2, const vec3& p3, float t);
private:
List<vec3> points;
List<float> rotation;
List<float> scale;
};
}

View File

@@ -0,0 +1,80 @@
#include "stdafx.h"
namespace mt
{
Triangle::Triangle()
{
PERFORMANCER;
}
Triangle::Triangle(Vertex* a, Vertex* b, Vertex* c)
{
PERFORMANCER;
vertices.Add(a);
vertices.Add(b);
vertices.Add(c);
}
Triangle::~Triangle()
{
PERFORMANCER;
}
vec3 Triangle::GetNormal() const
{
PERFORMANCER;
auto v1 = vertices[0]->Position;
auto v2 = vertices[1]->Position;
auto v3 = vertices[2]->Position;
auto normal = vec3::Cross(v2 - v1, v3 - v1);
normal.Normalize();
return normal;
}
const List<Vertex*>& Triangle::GetVertices() const
{
PERFORMANCER;
return vertices;
}
bool Triangle::IsDegenerated() const
{
PERFORMANCER;
if (vertices[0] == vertices[1] || vertices[1] == vertices[2] || vertices[2] == vertices[0])
return true;
auto d = (vertices[0]->Position - vertices[1]->Position).GetLengthSq();
if (d <= Math::FloatEpsilon)
return true;
d = (vertices[1]->Position - vertices[2]->Position).GetLengthSq();
if (d <= Math::FloatEpsilon)
return true;
d = (vertices[2]->Position - vertices[0]->Position).GetLengthSq();
if (d <= Math::FloatEpsilon)
return true;
return false;
}
float Triangle::GetArea() const
{
PERFORMANCER;
// http://www.iquilezles.org/blog/?p=1579
auto a = (vertices[0]->Position - vertices[1]->Position).GetLengthSq();
auto b = (vertices[1]->Position - vertices[2]->Position).GetLengthSq();
auto c = (vertices[2]->Position - vertices[0]->Position).GetLengthSq();
auto area = (2 * a*b + 2 * b*c + 2 * c*a - a*a - b*b - c*c) / 16;
return Math::Sqrt(area);
}
}

View File

@@ -0,0 +1,21 @@
#pragma once
namespace mt
{
class Triangle
{
public:
Triangle();
Triangle(Vertex* a, Vertex* b, Vertex* c);
~Triangle();
vec3 GetNormal() const;
const VertexList& GetVertices() const;
bool IsDegenerated() const;
float GetArea() const;
private:
VertexList vertices;
};
}

View File

@@ -0,0 +1,142 @@
#include "stdafx.h"
namespace mt
{
Vertex::Vertex(const vec3& position)
: index{ -1 }
, normal{ nullptr }
, Position{ position }
, mesh{ nullptr }
{
PERFORMANCER;
for (int i = 0; i < 4; ++i)
{
UV[i] = 0;
UV2[i] = 0;
}
}
Vertex::Vertex(Vertex* other)
: index{ -1 }
, normal{ nullptr }
, Position{ other->Position }
, mesh{ nullptr }
{
PERFORMANCER;
for (int i = 0; i < 4; ++i)
{
UV[i] = other->UV[i];
UV2[i] = other->UV2[i];
}
if (other->normal != nullptr)
normal = new vec3{ *other->normal };
}
Vertex::~Vertex()
{
PERFORMANCER;
delete normal;
}
int Vertex::GetIndex() const
{
PERFORMANCER;
return index;
}
vec3 Vertex::GetNormal() const
{
PERFORMANCER;
if (normal == nullptr)
{
vec3 n;
for (const auto& face : GetFaces())
n += face->GetNormal();
n.Normalize();
return n;
}
else
return *normal;
}
void Vertex::SetNormal(const vec3& newNormal)
{
PERFORMANCER;
delete normal;
if (newNormal == vec3::zero)
normal = nullptr;
else
normal = new vec3{ newNormal };
}
VertexList Vertex::GetVertices() const
{
PERFORMANCER;
auto result = Linq::SelectUniqueMany<Vertex*>(edges, [](Edge* edge) { return edge->GetVertices(); });
result.Remove(const_cast<Vertex*>(this));
return result;
}
FaceList Vertex::GetFaces() const
{
PERFORMANCER;
FaceList result;
for (const auto& edge : edges)
for (const auto& face : edge->GetFaces())
if (!result.Contains(face))
result.Add(face);
//auto result = Linq::SelectUniqueMany<Face*>(edges, [](Edge* edge){ return edge->GetFaces(); });
return result;
}
const EdgeList& Vertex::GetEdges() const
{
PERFORMANCER;
return edges;
}
Mesh* Vertex::GetMesh() const
{
PERFORMANCER;
return mesh;
}
void Vertex::Interpolate(Vertex* other, float t)
{
Position = vec3::Lerp(Position, other->Position, t);
if (other->HasManualNormal() && HasManualNormal())
*normal = vec3::Lerp(*normal, *other->normal, t);
for (int i = 0; i < 4; ++i)
{
UV[i] = Math::Lerp(UV[i], other->UV[i], t);
UV2[i] = Math::Lerp(UV2[i], other->UV2[i], t);
}
}
RawVertex Vertex::GetRaw() const
{
RawVertex result;
result.Position = Position;
result.Normal = GetNormal();
for (int i = 0; i < 4; ++i)
result.UV[i] = UV[i];
return result;
}
}

View File

@@ -0,0 +1,52 @@
#pragma once
#include "typedefs.h"
namespace mt
{
struct RawVertex
{
vec3 Position;
vec3 Normal;
float UV[4];
};
class Vertex
{
friend class Mesh;
friend class Selection;
public:
Vertex(const vec3& position);
Vertex(Vertex* other);
//Vertex();
~Vertex();
int GetIndex() const;
vec3 GetNormal() const;
void SetNormal(const vec3& normal);
bool HasManualNormal() const { return normal != nullptr; }
VertexList GetVertices() const;
FaceList GetFaces() const;
const EdgeList& GetEdges() const;
Mesh* GetMesh() const;
void Interpolate(Vertex* other, float t);
RawVertex GetRaw() const;
public:
vec3 Position;
float UV[4];
float UV2[4];
private:
vec3* normal;
int index;
EdgeList edges;
Mesh* mesh;
};
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include "Vertex.h"
#include "Triangle.h"
#include "Face.h"
#include "Mesh.h"
#include "Edge.h"
#include "Path.h"

View File

@@ -0,0 +1,29 @@
#pragma once
namespace mt
{
class Edge
{
friend class Mesh;
public:
Edge();
Edge(Vertex* a, Vertex* b);
~Edge();
Vertex* GetOtherVertex(Vertex* vertex) const;
const VertexList& GetVertices() const;
const FaceList& GetFaces() const;
EdgeList GetEdges() const;
vec3 GetDirection() const;
vec3 GetCenter() const;
float GetLength() const;
Edge* GetHalfEdge(Face* face) const;
private:
VertexList vertices;
FaceList faces;
Mesh* mesh;
};
}

View File

@@ -0,0 +1,12 @@
#pragma once
namespace mt
{
class Vertex;
class Edge;
class Face;
typedef List<Vertex*> VertexList;
typedef List<Edge*> EdgeList;
typedef List<Face*> FaceList;
}

View File

@@ -0,0 +1,29 @@
#pragma once
namespace mt
{
class Bounds
{
public:
Bounds(vec3 min, vec3 max)
: Min{ min }
, Max{ max }
{
}
vec3 Min;
vec3 Max;
float GetRadius() const
{
auto length = (Max - Min).GetLength();
return length / 2;
}
vec3 GetCenter() const
{
return (Min + Max) * 0.5f;
}
};
}

View File

@@ -0,0 +1,10 @@
#include <stdafx.h>
namespace mt
{
const float Math::Rad2Deg = 57.2957795f;
const float Math::Deg2Rad = 3.14159265359f / 180;
const float Math::FloatEpsilon = 1E-5f;
const float Math::Pi = 3.14159265359f;
const float Math::Infinity = 3.402823466e+38F;
}

View File

@@ -0,0 +1,61 @@
#include <stdafx.h>
namespace mt
{
Matrix Matrix::identity;
Matrix::Matrix()
: M11{ 1 }
, M12{ 0 }
, M13{ 0 }
, M14{ 0 }
, M21{ 0 }
, M22{ 1 }
, M23{ 0 }
, M24{ 0 }
, M31{ 0 }
, M32{ 0 }
, M33{ 1 }
, M34{ 0 }
, M41{ 0 }
, M42{ 0 }
, M43{ 0 }
, M44{ 1 }
{
}
Matrix Matrix::FromQuaternion(const Quaternion& quat)
{
float xx = 2 * quat.x * quat.x;
float xy = 2 * quat.x * quat.y;
float xw = 2 * quat.x * quat.w;
float yy = 2 * quat.y * quat.y;
float yz = 2 * quat.y * quat.z;
float yw = 2 * quat.y * quat.w;
float zx = 2 * quat.z * quat.x;
float zz = 2 * quat.z * quat.z;
float zw = 2 * quat.z * quat.w;
Matrix result;
result.M11 = 1 - (yy + zz);
result.M12 = xy + zw;
result.M13 = zx - yw;
result.M14 = 0;
result.M21 = xy - zw;
result.M22 = 1 - (zz + xx);
result.M23 = yz + xw;
result.M24 = 0;
result.M31 = zx + yw;
result.M32 = yz - xw;
result.M33 = 1 - (yy + xx);
result.M34 = 0;
result.M41 = 0;
result.M42 = 0;
result.M43 = 0;
result.M44 = 1;
return result;
}
}

View File

@@ -0,0 +1,32 @@
#pragma once
namespace mt
{
class Matrix
{
public:
static Matrix identity;
static Matrix FromQuaternion(const Quaternion& quat);
public:
Matrix();
public:
float M11;
float M12;
float M13;
float M14;
float M21;
float M22;
float M23;
float M24;
float M31;
float M32;
float M33;
float M34;
float M41;
float M42;
float M43;
float M44;
};
}

View File

@@ -0,0 +1,67 @@
#include "stdafx.h"
namespace mt
{
Plane::Plane(const vec3& normal, const vec3& point)
: normal{ normal }
, distance{ vec3::Dot(normal, point) }
{
}
Plane::Plane(const vec3& a, const vec3& b, const vec3& c)
{
normal = vec3::Cross(b - a, c - a);
normal.Normalize();
distance = vec3::Dot(normal, a);
}
Plane::~Plane()
{
}
float Plane::GetDistanceToPoint(const vec3& point) const
{
return vec3::Dot(normal, point) - distance;
}
vec3 Plane::GetNormal() const
{
return normal;
}
float Plane::GetDistance() const
{
return distance;
}
bool Plane::GetSide(const vec3& point) const
{
return GetDistanceToPoint(point) > 0.0;
}
void Plane::Flip()
{
normal = -normal;
distance = -distance;
}
float Plane::IntersectLinesegment(vec3 a, vec3 b, vec3& result) const
{
auto ba = b - a;
float nDotA = vec3::Dot(normal, a);
float nDotBA = vec3::Dot(normal, ba);
auto d = (distance - nDotA) / nDotBA;
result = a + (ba * d);
return d;
}
}
#include <stdafx.h>

View File

@@ -0,0 +1,23 @@
#pragma once
namespace mt
{
class Plane
{
public:
Plane(const vec3& normal, const vec3& point);
Plane(const vec3& a, const vec3& b, const vec3& c);
~Plane();
float GetDistanceToPoint(const vec3& point) const;
vec3 GetNormal() const;
float GetDistance() const;
bool GetSide(const vec3& point) const;
void Flip();
float IntersectLinesegment(vec3 a, vec3 b, vec3& result) const;
private:
vec3 normal;
float distance;
};
}

View File

@@ -0,0 +1,125 @@
#include <stdafx.h>
namespace mt
{
Quaternion Quaternion::identity;
Quaternion::Quaternion()
: x{ 0 }
, y{ 0 }
, z{ 0 }
, w{ 1 }
{
}
Quaternion Quaternion::FromAxisAngle(const vec3& axis, float angle)
{
float halfAngle = angle * .5f;
float s = (float)Math::Sin(halfAngle);
Quaternion q;
q.x = axis.x * s;
q.y = axis.y * s;
q.z = axis.z * s;
q.w = (float)Math::Cos(halfAngle);
return q;
}
Quaternion Quaternion::LookRotation(const vec3& forward)
{
float dot = vec3::Dot(vec3::up, forward);
if (Math::Abs(dot - (-1.0f)) < 0.000001f)
{
return FromAxisAngle(vec3::forward, Math::Pi);
}
if (Math::Abs(dot - (1.0f)) < 0.000001f)
{
return Quaternion::identity;
}
float rotAngle = (float)Math::Acos(dot);
vec3 rotAxis = vec3::Cross(vec3::up, forward);
rotAxis.Normalize();
return FromAxisAngle(rotAxis, rotAngle);
}
Quaternion Quaternion::FromTo(vec3 v0, vec3 v1)
{
Quaternion q;
v0.Normalize();
v1.Normalize();
float d = vec3::Dot(v0, v1);
// If dot == 1, vectors are the same
if (d >= 1.0f)
{
return Quaternion::identity;
}
if (d < (1e-6f - 1.0f))
{
vec3 axis = vec3::Cross(vec3::right, v0);
if (axis.GetLengthSq() < Math::FloatEpsilon) // pick another if colinear
axis = vec3::Cross(vec3::up, v0);
axis.Normalize();
return Quaternion::FromAxisAngle(axis, Math::Pi);
}
else
{
auto s = Math::Sqrt((1 + d) * 2);
auto invs = 1 / s;
auto c = vec3::Cross(v0, v1);
q.x = c.x * invs;
q.y = c.y * invs;
q.z = c.z * invs;
q.w = s * 0.5f;
q.Normalize();
}
return q;
}
void Quaternion::Inverse()
{
auto newX = w;
auto newY = -x;
auto newZ = -y;
auto newW = -z;
x = newX;
y = newY;
z = newZ;
w = newW;
Normalize();
}
void Quaternion::Normalize()
{
auto norm = w*w + x*x + y*y + z*z;
auto s = 1 / norm;
x *= s;
y *= s;
z *= s;
w *= s;
}
Quaternion Quaternion::operator*(Quaternion b) const
{
Quaternion result;
result.x = (b.x * w) + (b.w * x) + ((y * b.z) - (z * b.y));
result.y = (b.y * w) + (b.w * y) + ((z * b.x) - (x * b.z));
result.z = (b.z * w) + (b.w * z) + ((x * b.y) - (y * b.x));
result.w = (b.w * w) - ((b.x * x) + (y * b.y) + (z * b.z));
return result;
}
}

View File

@@ -0,0 +1,26 @@
#pragma once
namespace mt
{
class Quaternion
{
public:
static Quaternion identity;
static Quaternion LookRotation(const vec3& normal);
static Quaternion FromAxisAngle(const vec3& axis, float angle);
static Quaternion FromTo(vec3 v0, vec3 v1);
Quaternion operator* (Quaternion other) const;
public:
Quaternion();
void Inverse();
void Normalize();
public:
float x;
float y;
float z;
float w;
};
}

View File

@@ -0,0 +1,118 @@
#pragma once
#include <cmath> // acos and shit
#include "vec3.h"
#include "Bounds.h"
namespace mt
{
struct vec2
{
float x;
float y;
};
struct vec4
{
float x;
float y;
float z;
float w;
};
class Math
{
public:
static const float Rad2Deg;
static const float Deg2Rad;
static const float FloatEpsilon;
static const float Pi;
static const float Infinity;
static float Clamp01(float a)
{
return a > 1 ? 1 : a < 0 ? 0 : a;
}
static float Pow(float a, float b)
{
return std::pow(a, b);
}
static float Max(float a, float b)
{
return a > b ? a : b;
}
static float Min(float a, float b)
{
return a > b ? b : a;
}
static float Abs(float a)
{
return a > 0 ? a : -a;
}
static float Sin(float x)
{
/*_asm fld x
_asm fsin*/
return std::sin(x);
}
static float Cos(float x)
{
/*_asm fld x
_asm fcos*/
return std::cos(x);
}
static float Acos(float x)
{
/*_asm
{
fld x
fld x
fmul
fld1
fsubr
fsqrt
fxch
fpatan
}*/
return std::acos(x);
}
static float Atan2(float x, float y)
{
return std::atan2(x, y);
}
static float Lerp(float a, float b, float t)
{
return a + t * (b - a);
}
static float Sqrt(float x)
{
#if _DEBUG
return std::sqrt(x);
#else
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f375a86 - (i >> 1);
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x);
x = x*(1.5f - xhalf*x*x);
x = x*(1.5f - xhalf*x*x);
x = 1 / x;
return x;
#endif
}
};
}
#include "Plane.h"
#include "Matrix.h"
#include "Quaternion.h"

View File

@@ -0,0 +1,228 @@
#include <stdafx.h>
namespace mt
{
vec3 const vec3::zero = { 0, 0, 0 };
vec3 const vec3::one = { 1,1,1 };
vec3 const vec3::up = { 0, 1, 0 };
vec3 const vec3::down = { 0, -1, 0 };
vec3 const vec3::left = { -1, 0, 0 };
vec3 const vec3::right = { 1, 0, 0 };
vec3 const vec3::forward = { 0, 0, 1 };
vec3 const vec3::back = { 0, 0, -1 };
vec3::vec3()
: x{ 0 }
, y{ 0 }
, z{ 0 }
{
}
vec3::vec3(float x, float y, float z)
: x{ x }
, y{ y }
, z{ z }
{
}
vec3::vec3(const vec3& other)
: x{ other.x }
, y{ other.y }
, z{ other.z }
{
}
vec3::~vec3()
{
}
float vec3::GetLength() const
{
return Math::Sqrt(x*x + y*y + z*z);
}
float vec3::GetLengthSq() const
{
return x*x + y*y + z*z;
}
void vec3::Normalize()
{
auto length = GetLength();
if (length == 0)
{
x = y = z = 0;
return;
}
x /= length;
y /= length;
z /= length;
}
vec3 vec3::Mul(const vec3& a, const vec3& b)
{
return vec3(a.x * b.x, a.y * b.y, a.z * b.z);
}
float vec3::Dot(const vec3& a, const vec3& b)
{
float result = 0;
result += a.x * b.x;
result += a.y * b.y;
result += a.z * b.z;
return result;
}
vec3 vec3::Cross(const vec3& a, const vec3& b)
{
return vec3(
a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.x * b.y - a.y * b.x
);
}
vec3 vec3::Transform(const vec3& a, const Matrix& m)
{
return{
(a.x * m.M11) + (a.y * m.M21) + (a.z * m.M31) + m.M41,
(a.x * m.M12) + (a.y * m.M22) + (a.z * m.M32) + m.M42,
(a.x * m.M13) + (a.y * m.M23) + (a.z * m.M33) + m.M43
};
}
vec3 vec3::Min(const vec3& a, const vec3& b)
{
return{
Math::Min(a.x, b.x),
Math::Min(a.y, b.y),
Math::Min(a.z, b.z),
};
}
vec3 vec3::Max(const vec3& a, const vec3& b)
{
return{
Math::Max(a.x, b.x),
Math::Max(a.y, b.y),
Math::Max(a.z, b.z),
};
}
float vec3::Distance(const vec3& a, const vec3& b)
{
return (a - b).GetLength();
}
float vec3::DistanceSq(const vec3& a, const vec3& b)
{
return (a - b).GetLengthSq();
}
vec3 vec3::Lerp(const vec3& a, const vec3& b, float t)
{
return{
Math::Lerp(a.x, b.x, t),
Math::Lerp(a.y, b.y, t),
Math::Lerp(a.z, b.z, t)
};
}
vec3 vec3::operator- () const
{
return{ -x, -y, -z };
}
bool vec3::operator== (const vec3& other) const
{
return x == other.x && y == other.y && z == other.z;
}
bool vec3::operator!= (const vec3& other) const
{
return x != other.x || y != other.y || z != other.z;
}
vec3 vec3::operator+ (const vec3& other) const
{
return{ x + other.x, y + other.y, z + other.z };
}
void vec3::operator+= (const vec3& other)
{
x += other.x;
y += other.y;
z += other.z;
}
void vec3::operator-= (const vec3& other)
{
x -= other.x;
y -= other.y;
z -= other.z;
}
void vec3::operator/= (float other)
{
x /= other;
y /= other;
z /= other;
}
void vec3::operator*= (float other)
{
x *= other;
y *= other;
z *= other;
}
vec3 vec3::operator- (const vec3& other) const
{
return{ x - other.x, y - other.y, z - other.z };
}
vec3 vec3::operator* (float other) const
{
return{ x * other, y * other, z * other };
}
vec3 vec3::operator/ (float other) const
{
return{ x / other, y / other, z / other };
}
vec3 vec3::operator* (const Quaternion& q) const
{
vec3 qxyz = { q.x, q.y, q.z };
auto t = vec3::Cross(qxyz, *this) * 2;
return *this + t * q.w + vec3::Cross(qxyz, t);
}
}

View File

@@ -0,0 +1,59 @@
#pragma once
namespace mt
{
class Matrix;
class Quaternion;
class vec3
{
public:
static const vec3 zero;
static const vec3 one;
static const vec3 up;
static const vec3 down;
static const vec3 left;
static const vec3 right;
static const vec3 forward;
static const vec3 back;
vec3();
vec3(float x, float y, float z);
vec3(const vec3& other);
~vec3();
float GetLength() const;
float GetLengthSq() const;
void Normalize();
static vec3 Mul(const vec3& a, const vec3& b);
static float Dot(const vec3& a, const vec3& b);
static vec3 Cross(const vec3& a, const vec3& b);
static vec3 Transform(const vec3& a, const Matrix& m);
static vec3 Min(const vec3& a, const vec3& b);
static vec3 Max(const vec3& a, const vec3& b);
static float Distance(const vec3& a, const vec3& b);
static float DistanceSq(const vec3& a, const vec3& b);
static vec3 Lerp(const vec3& a, const vec3& b, float t);
vec3 operator- () const;
bool operator== (const vec3& other) const;
bool operator!= (const vec3& other) const;
vec3 operator+ (const vec3& other) const;
void operator+= (const vec3& other);
void operator-= (const vec3& other);
void operator/= (float other);
void operator*= (float other);
vec3 operator- (const vec3& other) const;
vec3 operator* (float other) const;
vec3 operator/ (float other) const;
vec3 operator* (const Quaternion& q) const;
public:
float x;
float y;
float z;
};
}

View File

@@ -0,0 +1,20 @@
#pragma once
#include "typedef.h"
#include "common/common.h"
#include "math/math.h"
#include "core/core.h"
#if _DEBUG
#include "common/Performancer.h"
#else
#define PERFORMANCER
#define PERFORMANCER_DUMP
#endif
#include "operators/OpMesh.h"
#include "operators/operators.h"
#include "parser/registers.h"
#include "parser/parser.h"
#include "tools/tools.h"

View File

@@ -0,0 +1,26 @@
#include "stdafx.h"
#include "OpDocument.h"
#include "OpMesh.h"
namespace mt
{
OpDocument::OpDocument(unsigned int _iRegisterCount)
{
r = new void*[_iRegisterCount];
memset(r, 0, sizeof(void*) * _iRegisterCount);
}
OpDocument::~OpDocument()
{
delete[] r;
}
OpMesh* OpDocument::GetMesh(unsigned int _index)
{
auto result = new mt::OpMesh();
result->Copy(*(OpMesh*)r[_index], false);
return result;
}
}

View File

@@ -0,0 +1,16 @@
#pragma once
namespace mt
{
class OpMesh;
class OpDocument
{
public:
OpDocument(unsigned int _iRegisterCount);
~OpDocument();
OpMesh* GetMesh(unsigned int _index);
void** r;
};
}

View File

@@ -0,0 +1,60 @@
#include "stdafx.h"
namespace mt
{
OpMesh::OpMesh()
: _mesh { nullptr }
{
}
OpMesh::OpMesh(Mesh* mesh)
: _mesh{ mesh }
{
}
OpMesh::~OpMesh()
{
}
void OpMesh::Copy(const OpMesh& other, bool shareMesh)
{
if (shareMesh)
_mesh = other._mesh ;
else
_mesh = mt::ToMesh(other.GetMesh()->GetFaces());
Selection = other.Selection;
}
FaceList OpMesh::GetSelectedFaces() const
{
const auto& faces = GetMesh()->GetFaces();
return Linq::Select<Face*>(Selection, [&](unsigned int index) { return faces[index]; });
}
List<RawVertex> OpMesh::GetSelectedFaceVertices() const
{
auto selectedFaces = GetSelectedFaces();
auto selectedVertices = Linq::SelectMany<mt::RawVertex>(selectedFaces, [](mt::Face* face)
{
return ::Linq::Select<mt::RawVertex>(face->GetVertices(), [](mt::Vertex* vertex)
{
return vertex->GetRaw();
});
});
return selectedVertices;
}
List<unsigned int> OpMesh::GetSelectedFaceIndices() const
{
GetMesh()->UpdateIndices();
auto selectedFaces = GetSelectedFaces();
auto selectedIndices = Linq::SelectMany<unsigned int>(selectedFaces, [](mt::Face* face)
{
return face->GetIndices(false);
});
return selectedIndices;
}
}

View File

@@ -0,0 +1,83 @@
#pragma once
namespace mt
{
template<class T>
class RefCounter
{
struct RefValue
{
RefValue(T* value)
: Count { 1 }
, Value { value }
{
}
void Add() { Count++; }
bool Remove()
{
if (--Count == 0 && Value != nullptr)
delete Value;
return Count == 0;
}
int Count;
T* Value;
};
public:
RefCounter(T* input)
: _value{ new RefValue {input} }
{
}
RefCounter(const RefCounter& other)
: _value{other._value}
{
_value->Add();
}
~RefCounter()
{
if (_value->Remove())
delete _value;
}
RefCounter<T>& operator=(const RefCounter<T>& other)
{
if (_value->Remove())
delete _value;
_value = other._value;
_value->Add();
return *this;
}
T* Value() const { return _value->Value; }
private:
RefCounter()
{
int a = 0;
}
RefValue* _value;
};
class OpMesh
{
public:
OpMesh();
OpMesh(Mesh* mesh);
~OpMesh();
void Copy(const OpMesh& other, bool shareMesh);
FaceList GetSelectedFaces() const;
Mesh* GetMesh() const { return _mesh.Value(); }
List<unsigned int> Selection;
List<RawVertex> OpMesh::GetSelectedFaceVertices() const;
List<unsigned int> OpMesh::GetSelectedFaceIndices() const;
private:
RefCounter<Mesh> _mesh;
};
}

View File

@@ -0,0 +1,46 @@
#include "stdafx.h"
namespace mt
{
namespace op
{
void CreateCube(OpMesh& output, bool weldVertices, vec3 position, float size)
{
output = { mt::CreateCube(weldVertices, position, size) };
}
void Subdivide(OpMesh& output, const OpMesh& input, int amount, bool smooth)
{
output.Copy(input, false);
auto faces = AutoFaceList(output.GetSelectedFaces());
for(int i = 0; i < amount;++i)
mt::Subdivide(faces, smooth);
}
void SelectAllFaces(OpMesh& output, const OpMesh& input)
{
output.Copy(input, true);
output.Selection.Clear();
for (int i = 0; i < output.GetMesh()->GetFaces().Count(); ++i)
output.Selection.Add(i);
}
void SelectFacesByDirection(OpMesh& output, const OpMesh& input, vec3 direction, float threshold, bool mirror)
{
output.Copy(input, true);
const auto& meshFaces = output.GetMesh()->GetFaces();
auto selectedFaces = mt::GetFacesByDirection(output.GetSelectedFaces(), direction, threshold, mirror);
output.Selection = Linq::Select<unsigned int>(selectedFaces, [&](Face* face)
{
return meshFaces.IndexOf(face);
});
}
void Delete(OpMesh& output, const OpMesh& input)
{
output.Copy(input, false);
const auto& meshFaces = output.GetMesh()->GetFaces();
mt::Delete(output.GetSelectedFaces());
}
}
}

View File

@@ -0,0 +1,29 @@
#pragma once
// API guidelines:
//
// - All return types must be void
// - All methods need at least one argument
// - The first argument must be of a non-const reference type and must be named "output"
// - All following (optional) input arguments must be of const reference or primitive types, and must have default values
namespace mt
{
namespace op
{
// [toolTip] Creates a cube mesh with the given size, direction and center position, the cube may be optionally smooth or sharp.
// [weldVertices] DisplayName="Weld vertices"
// [position] DisplayName="Position"
// [edgeSize] DisplayName="Edge size" Min="0" Max="Infinity" Step="0.1"
// [smooth] DisplayName="Smooth"
void CreateCube(OpMesh& output, bool weldVertices = true, vec3 position = vec3::zero, float edgeSize = 1);
// Subdivide
void Subdivide(OpMesh& output, const OpMesh& input, int amount = 2, bool smooth = true);
void Delete(OpMesh& output, const OpMesh& input);
void SelectAllFaces(OpMesh& output, const OpMesh& input);
void SelectFacesByDirection(OpMesh& output, const OpMesh& input, vec3 direction, float threshold = 0.0f, bool mirror = false);
}
}

View File

@@ -0,0 +1,24 @@
#include "stdafx.h"
#include "../operators/OpDocument.h"
#include "ops.h"
mt::OpDocument* mt::Parser::ParseDocument(unsigned char* _data)
{
auto iRegisterCount = *((unsigned short*)_data); _data += sizeof(unsigned short);
auto doc = new OpDocument(iRegisterCount);
auto iGroupCount = *((unsigned short*)_data); _data += sizeof(unsigned short);
auto groupPtr = _data + iGroupCount * sizeof(unsigned short*);
for (auto i = 0u; i < iGroupCount; ++i)
{
doc->r[i] = groupPtr + *((unsigned short*)_data); _data += sizeof(unsigned short);
}
auto iOpCount = *((unsigned short*)_data); _data += sizeof(unsigned short);
for (auto i = 0u; i < iOpCount; ++i)
{
mt::ParseOp(doc->r, &_data);
}
return doc;
}

View File

@@ -0,0 +1,11 @@
#pragma once
namespace mt
{
class OpDocument;
class Parser
{
public:
OpDocument* ParseDocument(unsigned char* _data);
};
}

Some files were not shown because too many files have changed in this diff Show More