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,115 @@
#if _DEBUG
#include "ObjExporter.h"
#include <iostream>
#include <fstream>
void ObjExporter::Export(Mesh* mesh, const std::string& filePath)
{
PERFORMANCER;
ObjExporter exporter(mesh);
exporter.Export(filePath);
}
ObjExporter::ObjExporter(Mesh* mesh)
: mesh{mesh}
{
PERFORMANCER;
}
void ObjExporter::Export(const std::string& filePath)
{
PERFORMANCER;
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)
{
PERFORMANCER;
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 FaceList& faces)
{
PERFORMANCER;
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)
{
PERFORMANCER;
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)
{
PERFORMANCER;
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)
{
PERFORMANCER;
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 <core/core.h>
#include <sstream>
#include <string>
class Mesh;
class ObjExporter
{
public:
static void Export(Mesh* mesh, const std::string& filePath);
ObjExporter(Mesh* mesh);
void Export(const std::string& filePath);
void WriteFaceGroups(std::ostringstream& builder, std::ostringstream& mtlBuilder);
void WriteFaces(std::ostringstream& builder, const 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:
Mesh* mesh;
};
#endif

247
meshTools/test/src/main.cpp Normal file
View File

@@ -0,0 +1,247 @@
#include <TCHAR.h>
#include <tools/tools.h>
#include "ObjExporter.h"
void PlaceCubesOnPoints(const List<vec3*> points, Mesh* target, float size = 0.025f)
{
auto sphere = mt::CreateSphere(1, vec3::zero, size);
for (auto point : points)
{
auto faces = mt::CopyToMesh(sphere->GetFaces(), target);
mt::MoveTo(mt::GetVertices(faces), *point);
}
delete sphere;
}
void MakePointer(vec3 pos, vec3 dir, Mesh* mesh)
{
auto pointer = mt::CreateCube(true, vec3::zero, 0.1f);
mt::Collapse(mt::GetFacesWithTag(pointer->GetFaces(), mt::Tags::DirectionUp));
mt::Scale(pointer->GetVertices(), vec3{0.5f, 2, 0.5f});
mt::MoveBy(pointer->GetVertices(), { 0, 0.1f, 0 });
mt::Rotate(pointer->GetVertices(), vec3::zero, vec3::up, dir);
mt::MoveTo(pointer->GetVertices(), pos);
mt::CopyToMesh(pointer->GetFaces(), mesh);
delete pointer;
}
void DeleteOffsideFaces(const FaceList& faces, bool negate = false)
{
mt::Delete(mt::GetFacesByDirection(faces, negate ? vec3::right : vec3::left));
}
void MarkFaces(const FaceList& faces)
{
int i = 0;
for (auto face : faces)
face->SetMaterialId(i++);
}
Mesh* Skull()
{
const int EYE = 0;
const int BROW = 1;
const int NOSE = 2;
PERFORMANCER;
auto mesh = mt::CreateSphere(2);
const auto& meshFaces = mesh->GetFaces();
mt::Scale(mesh->GetVertices(), vec3{ 1, 0.8f, 0.8f });
mt::Delete(mt::GetFacesOnPositivePlane(meshFaces, { vec3::left, vec3::zero }));
{
mt::FFD ffd(meshFaces, 1, 3, 3);
auto points = ffd.SelectPoints(0, 1, 0, 0, 3, 3);
for (auto point : points)
*point += vec3::forward * 0.1f;
points = ffd.SelectPoints(0, 0, 0, 0, 3, 3);
for (auto point : points)
*point += vec3::up * 0.15f;
points = ffd.SelectPoints(0, 1, 1, 1, 3, 3);
for (auto point : points)
*point += vec3::forward * 0.25f + vec3::up * 0.1f;
points = ffd.SelectPoints(0, 1, 2, 2, 3, 3);
for (auto point : points)
*point += vec3::forward * -0.1f;
points = ffd.SelectPoints(0, 1, 0, 0, 2, 2);
for (auto point : points)
*point += vec3::up * 0.15f + vec3::forward * 0.1f;
points = ffd.SelectPoints(0, 1, 0, 3, 3, 3);
for (auto point : points)
*point += vec3::up * 0.2f;
points = ffd.SelectPoints(1, 1, 0, 3, 3, 3);
for (auto point : points)
*point += vec3::left * 0.1f;
points = ffd.SelectPoints(1, 1, 0, 3, 0, 3);
for (auto point : points)
*point += vec3::left * 0.05f;
ffd.Apply();
}
// Chin
FaceList selection;
selection.Add(meshFaces[8]);
selection.Add(meshFaces[9]);
selection.Add(meshFaces[20]);
selection.Add(meshFaces[23]);
auto vertices = mt::GetVertices(selection);
vertices[0]->Position.x += 0.03f;
mt::Flatten(vertices, vec3::down);
mt::MoveBy(vertices, vec3{ 0, -0.08f, 0 });
mt::Weld(mesh->GetVertices(), 0.05f);
mt::Weld(mesh->GetVertices(), 0.05f);
mt::Rotate(mesh->GetVertices(), vec3::right, 0.2f);
DeleteOffsideFaces(mt::Extrude(selection, vec3{ 0, -0.05f, 0 }));
// Eye socket
selection.Clear();
selection.Add(meshFaces[42]);
selection.Add(meshFaces[18]);
mt::Split(selection, { vec3::up, vec3::zero });
selection = Linq::ToList(meshFaces[54]);
vertices = meshFaces[54]->GetVertices();
vertices[0]->Position.x -= 0.09f;
vertices[1]->Position.x -= 0.07f;
vertices[2]->Position.y += 0.025f;
vertices[3]->Position += vec3{ -0.02f, 0.05f, 0 };
auto brows = mt::Bevel(selection, 0, 0.9f);
mt::AddTag(selection, EYE);
mt::Scale(selection, 0.8f);
// Nose
selection = Linq::ToList(meshFaces[53]);
mt::Split(selection, { vec3::up, vec3{0, 0.08f, 0} });
vertices = meshFaces[16]->GetVertices();
vertices[0]->Position.z -= 0.03f;
selection = Linq::ToList(meshFaces[55]);
mt::Split(selection, { vec3::up, vec3{ 0, -0.08f, 0 } });
selection = Linq::ToList(meshFaces[53]);
mt::Split(selection, { vec3::up, vec3{ 0, -0.08f, 0 } });
selection.Clear();
selection.Add(meshFaces[61]);
selection.Add(meshFaces[65]);
mt::AddTag(selection, NOSE);
DeleteOffsideFaces(mt::Extrude(selection, vec3{ 0, 0.05f, -0.1f }), true);
mt::Scale(selection, vec3::one * .5f, vec3::zero);
{
mt::FFD ffd(meshFaces, 1, 2, 2);
// shrink upper head area
auto points = ffd.SelectPoints(0, 1, 2, 2, 0, 2);
for (auto point : points)
{
*point = vec3::Mul(*point, vec3(0.7f, 0.8f, 0.7f));
point->z -= 0.1f;
}
points = ffd.SelectPoints(0, 0, 2, 2, 0, 2);
for (auto point : points)
point->y += 0.03f;
// thinning the upper jaw
points = ffd.SelectPoints(0, 1, 0, 0, 2, 2);
for (auto point : points)
{
point->x *= 0.2f;
point->z *= 0.9f;
}
points = ffd.SelectPoints(1, 1, 0, 2, 0, 0);
for (auto point : points)
point->x *= 0.6f;
points = ffd.SelectPoints(1, 1, 0, 1, 0, 0);
for (auto point : points)
point->x *= 0.6f;
points = ffd.SelectPoints(0, 0, 0, 2, 2, 2);
for (auto point : points)
point->z -= 0.05f;
ffd.Apply();
}
selection.Clear();
selection.Add(meshFaces[26]);
selection.Add(meshFaces[9]);
selection.Add(meshFaces[31]);
vertices = mt::GetVertices(selection);
vertices = Linq::Where(vertices, [](Vertex* vertex) { return vertex->Position.z > 0; });
for (const auto& vertex : vertices)
vertex->Position.x *= 0.3f;
selection = mt::GetFacesWithTag(meshFaces, EYE);
mt::Bevel(selection, { 0, 0, -0.1f }, 0.7f);
selection.Clear();
selection.Add(brows[3]);
mt::Scale(selection, { 1, 2, 1 });
mt::Bevel(selection, 0.02f, 0.5f);
selection = Linq::ToList(meshFaces[58]);
vertices = mt::GetVertices(selection);
vertices[0]->Position += vec3{ 0, -0.01f, 0.08f };
vertices[1]->Position += vec3{ 0, -0.01f, 0.025f };
MarkFaces(meshFaces);
// Finalize
auto clone = mt::Copy(meshFaces);
mt::Mirror(clone, { vec3::left, vec3::zero });
auto edges = mt::GetOutlineEdges(meshFaces);
mt::Weld(edges);
return mesh;
}
#include <stdarg.h>
#ifdef _DEBUG
int _tmain()
#else
int mainCRTStartup()
#endif
{
auto mesh = Skull();
/*MakePointer(vec3::up, vec3::up, mesh);
MakePointer(vec3::right, vec3::right, mesh);
MakePointer(vec3::forward, vec3::forward, mesh);*/
#ifdef _DEBUG
ObjExporter exporter(mesh);
exporter.Export("../Bin/export.obj");
#endif
PERFORMANCER_DUMP
return 0;
}

102
meshTools/test/test.vcxproj Normal file
View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.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>{6E7DF6F1-481D-41A2-84CD-27B2626BC21D}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>test</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</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'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)Bin\$(Configuration)\</OutDir>
<IncludePath>$(SolutionDir)common/include;$(SolutionDir)math/include;$(SolutionDir)meshCore/include;$(SolutionDir)meshTools/include;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)Bin\$(Configuration)\lib\;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win32;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)Bin\$(Configuration)\</OutDir>
<IncludePath>$(SolutionDir)meshTools/include;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir);$(SolutionDir)Bin\$(Configuration)\lib\;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win32;$(LibraryPath)</LibraryPath>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>meshTools.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)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MinSpace</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WholeProgramOptimization>false</WholeProgramOptimization>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FloatingPointModel>Fast</FloatingPointModel>
<AdditionalOptions>/QIfist %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>msvcrt_old.LIB;meshTools.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>
<AdditionalOptions>/CRINKLER %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\ObjExporter.cpp" />
<ClCompile Include="src\main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\ObjExporter.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,30 @@
<?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>
<ClCompile Include="src\ObjExporter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\ObjExporter.h">
<Filter>Header Files</Filter>
</ClInclude>
</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>