MXVK Vulkan Framework 0.24.0
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
mxvk::mxObject Class Reference

Simple mesh object loaded from PLG-style indexed triangle data. More...

#include <mxvk/include/mxvk/mxvk_math.h>

Public Member Functions

void BuildRenderList (RenderList &list) const
 Append this object's triangles to a render list.
void BuildRenderList (RenderList &list) const
 Append this object's triangles to a render list.
float ComputeRad ()
 Compute and cache average and maximum local-space radii.
float ComputeRad ()
 Compute and cache average and maximum local-space radii.
bool LoadMTL (const std::string &path)
 Replace this object's material library with an MTL file.
bool LoadMTL (const std::string &path)
 Replace this object's material library with an MTL file.
bool LoadMX (const std::string &path, const vec4D &scale, const vec4D &obj_pos, const vec4D &rotation)
 Load an MX mesh file using the PLG loader compatibility path.
bool LoadMX (const std::string &path, const vec4D &scale, const vec4D &obj_pos, const vec4D &rotation)
 Load an MX mesh file using the PLG loader compatibility path.
bool LoadOBJ (const std::string &path, const vec4D &scale, const vec4D &obj_pos, const vec4D &rotation)
 Load a Wavefront OBJ mesh and its referenced MTL material library.
bool LoadOBJ (const std::string &path, const vec4D &scale, const vec4D &obj_pos, const vec4D &rotation)
 Load a Wavefront OBJ mesh and its referenced MTL material library.
bool LoadPLG (const std::string &path, const vec4D &scale, const vec4D &obj_pos, const vec4D &rotation)
 Load a PLG mesh file.
bool LoadPLG (const std::string &path, const vec4D &scale, const vec4D &obj_pos, const vec4D &rotation)
 Load a PLG mesh file.
void ModelToWorld (int type=0)
 Convert local or transformed vertices to world space.
void ModelToWorld (int type=0)
 Convert local or transformed vertices to world space.
void RemoveFaces (const vec4D &pos)
 Mark object polygons that face away from a view position.
void RemoveFaces (const vec4D &pos)
 Mark object polygons that face away from a view position.
void Reset ()
 Reset object and polygon state to active.
void Reset ()
 Reset object and polygon state to active.
void SetState (int new_state)
 Replace the object state flags.
void SetState (int new_state)
 Replace the object state flags.
void TransformObject (const Mat4D &mrot, int type=0)
 Apply a transform to local vertices, transformed vertices, or local-to-transformed output.
void TransformObject (const Mat4D &mrot, int type=0)
 Apply a transform to local vertices, transformed vertices, or local-to-transformed output.

Public Attributes

int attr = 0
 Object attributes.
float avg_rad = 0.0f
 Average radius from the local origin.
vec4D dir
 Object direction.
std::vector< vec4Dlocal
 Local-space vertices.
std::string material_library_path
 Resolved path of the OBJ material library.
std::vector< OBJMaterialmaterials
 Materials loaded from the OBJ material library.
float max_rad = 0.0f
 Maximum radius from the local origin.
int num_polys = 0
 Number of loaded polygons.
int num_vertices = 0
 Number of loaded vertices.
std::string object_name
 Object name loaded from the model file.
int state = MX_ACTIVE
 Object state flags.
std::vector< vec2Dtexcoords
 Optional texture coordinates corresponding to local-space vertices.
std::vector< vec4Dtrans
 Transformed vertices.
vec4D ux
 Local X basis vector.
vec4D uy
 Local Y basis vector.
vec4D uz
 Local Z basis vector.
std::vector< Trianglevlist
 Indexed triangle list.
vec4D world_pos
 Object world position.

Detailed Description

Simple mesh object loaded from PLG-style indexed triangle data.

Definition at line 1439 of file mxvk_math.h.

Member Function Documentation

◆ BuildRenderList() [1/2]

void mxvk::mxObject::BuildRenderList ( RenderList & list) const
inline

Append this object's triangles to a render list.

Definition at line 1782 of file mxvk_math.h.

1782 {
1783 for (const auto &poly : vlist) {
1784 Triangle tri = poly;
1785 for (int i = 0; i < 3; ++i) {
1786 const auto index = static_cast<std::size_t>(poly.vert[i]);
1787 if (index < local.size()) {
1788 tri.vlist[i] = local[index];
1789 }
1790 if (index < trans.size()) {
1791 tri.tlist[i] = trans[index];
1792 }
1793 }
1794 list.BuildRenderList(tri);
1795 }
1796 }
std::vector< vec4D > local
Local-space vertices.
Definition mxvk_math.h:1475
std::vector< Triangle > vlist
Indexed triangle list.
Definition mxvk_math.h:1484
std::vector< vec4D > trans
Transformed vertices.
Definition mxvk_math.h:1478

◆ BuildRenderList() [2/2]

void mxvk::mxObject::BuildRenderList ( RenderList & list) const
inline

Append this object's triangles to a render list.

Definition at line 1779 of file mxvk_math_eigen.hpp.

1779 {
1780 for (const auto &poly : vlist) {
1781 Triangle tri = poly;
1782 for (int i = 0; i < 3; ++i) {
1783 const auto index = static_cast<std::size_t>(poly.vert[i]);
1784 if (index < local.size()) {
1785 tri.vlist[i] = local[index];
1786 }
1787 if (index < trans.size()) {
1788 tri.tlist[i] = trans[index];
1789 }
1790 }
1791 list.BuildRenderList(tri);
1792 }
1793 }

◆ ComputeRad() [1/2]

float mxvk::mxObject::ComputeRad ( )
inline

Compute and cache average and maximum local-space radii.

Definition at line 1807 of file mxvk_math.h.

1807 {
1808 max_rad = 0.0f;
1809 avg_rad = 0.0f;
1810 if (local.empty()) {
1811 return 0.0f;
1812 }
1813 for (const auto &vertex : local) {
1814 const float dist = std::sqrt(vertex.x * vertex.x + vertex.y * vertex.y + vertex.z * vertex.z);
1815 avg_rad += dist;
1816 max_rad = std::max(max_rad, dist);
1817 }
1818 avg_rad /= static_cast<float>(local.size());
1819 return max_rad;
1820 }
float max_rad
Maximum radius from the local origin.
Definition mxvk_math.h:1451
float avg_rad
Average radius from the local origin.
Definition mxvk_math.h:1448

◆ ComputeRad() [2/2]

float mxvk::mxObject::ComputeRad ( )
inline

Compute and cache average and maximum local-space radii.

Definition at line 1804 of file mxvk_math_eigen.hpp.

1804 {
1805 max_rad = 0.0f;
1806 avg_rad = 0.0f;
1807 if (local.empty()) {
1808 return 0.0f;
1809 }
1810 for (const auto &vertex : local) {
1811 const float dist = Eigen::Vector3f(vertex.x, vertex.y, vertex.z).norm();
1812 avg_rad += dist;
1813 max_rad = std::max(max_rad, dist);
1814 }
1815 avg_rad /= static_cast<float>(local.size());
1816 return max_rad;
1817 }

◆ LoadMTL() [1/2]

bool mxvk::mxObject::LoadMTL ( const std::string & path)
inlinenodiscard

Replace this object's material library with an MTL file.

Returns
True when the material file is parsed successfully.

Definition at line 1704 of file mxvk_math.h.

1704 {
1705 std::vector<OBJMaterial> loaded_materials;
1706 std::string error;
1707 if (!detail::load_mtl_file(path, loaded_materials, error)) {
1708 std::cerr << "mxvk_math: failed to load MTL file '" << path << "': " << error << '\n';
1709 return false;
1710 }
1711
1712 std::unordered_map<std::string, int> material_indices;
1713 for (std::size_t index = 0; index < loaded_materials.size(); ++index) {
1714 material_indices.emplace(loaded_materials[index].name, static_cast<int>(index));
1715 }
1716 for (std::size_t index = 0; index < vlist.size(); ++index) {
1717 const auto material = material_indices.find(vlist[index].material_name);
1718 vlist[index].material_index = material == material_indices.end() ? -1 : material->second;
1719 if (material != material_indices.end()) {
1720 vlist[index].color = material_color(loaded_materials[static_cast<std::size_t>(material->second)]);
1721 }
1722 }
1723
1724 materials = std::move(loaded_materials);
1725 material_library_path = path;
1726 return true;
1727 }
std::string material_library_path
Resolved path of the OBJ material library.
Definition mxvk_math.h:1493
std::vector< OBJMaterial > materials
Materials loaded from the OBJ material library.
Definition mxvk_math.h:1490
bool load_mtl_file(const std::string &path, std::vector< OBJMaterial > &materials, std::string &error)

◆ LoadMTL() [2/2]

bool mxvk::mxObject::LoadMTL ( const std::string & path)
inlinenodiscard

Replace this object's material library with an MTL file.

Returns
True when the material file is parsed successfully.

Definition at line 1701 of file mxvk_math_eigen.hpp.

1701 {
1702 std::vector<OBJMaterial> loaded_materials;
1703 std::string error;
1704 if (!detail::load_mtl_file(path, loaded_materials, error)) {
1705 std::cerr << "mxvk_math_eigen: failed to load MTL file '" << path << "': " << error << '\n';
1706 return false;
1707 }
1708
1709 std::unordered_map<std::string, int> material_indices;
1710 for (std::size_t index = 0; index < loaded_materials.size(); ++index) {
1711 material_indices.emplace(loaded_materials[index].name, static_cast<int>(index));
1712 }
1713 for (std::size_t index = 0; index < vlist.size(); ++index) {
1714 const auto material = material_indices.find(vlist[index].material_name);
1715 vlist[index].material_index = material == material_indices.end() ? -1 : material->second;
1716 if (material != material_indices.end()) {
1717 vlist[index].color = material_color(loaded_materials[static_cast<std::size_t>(material->second)]);
1718 }
1719 }
1720
1721 materials = std::move(loaded_materials);
1722 material_library_path = path;
1723 return true;
1724 }

◆ LoadMX() [1/2]

bool mxvk::mxObject::LoadMX ( const std::string & path,
const vec4D & scale,
const vec4D & obj_pos,
const vec4D & rotation )
inlinenodiscard

Load an MX mesh file using the PLG loader compatibility path.

Definition at line 1624 of file mxvk_math.h.

1624 {
1625 return LoadPLG(path, scale, obj_pos, rotation);
1626 }
bool LoadPLG(const std::string &path, const vec4D &scale, const vec4D &obj_pos, const vec4D &rotation)
Load a PLG mesh file.
Definition mxvk_math.h:1507

◆ LoadMX() [2/2]

bool mxvk::mxObject::LoadMX ( const std::string & path,
const vec4D & scale,
const vec4D & obj_pos,
const vec4D & rotation )
inlinenodiscard

Load an MX mesh file using the PLG loader compatibility path.

Definition at line 1621 of file mxvk_math_eigen.hpp.

1621 {
1622 return LoadPLG(path, scale, obj_pos, rotation);
1623 }

◆ LoadOBJ() [1/2]

bool mxvk::mxObject::LoadOBJ ( const std::string & path,
const vec4D & scale,
const vec4D & obj_pos,
const vec4D & rotation )
inlinenodiscard

Load a Wavefront OBJ mesh and its referenced MTL material library.

Wavefront faces may use independent position and texture-coordinate indices, negative indices, triangles, quads, or concave polygons. Faces are triangulated and de-indexed into the representation used by the software rasterizer. MTL diffuse colors become triangle colors.

Definition at line 1636 of file mxvk_math.h.

1636 {
1637 std::cout << "mxvk_math: loading OBJ model: " << path << '\n';
1638 detail::OBJLoadResult loaded;
1639 std::string error;
1640 if (!detail::load_obj_file(path, loaded, error)) {
1641 std::cerr << "mxvk_math: failed to load OBJ model '" << path << "': " << error << '\n';
1642 return false;
1643 }
1644
1645 std::unordered_map<std::string, int> material_indices;
1646 for (std::size_t index = 0; index < loaded.materials.size(); ++index) {
1647 material_indices.emplace(loaded.materials[index].name, static_cast<int>(index));
1648 }
1649
1650 std::vector<vec4D> loaded_local;
1651 std::vector<vec2D> loaded_texcoords;
1652 std::vector<Triangle> loaded_vlist;
1653 loaded_local.reserve(loaded.triangles.size() * 3);
1654 loaded_texcoords.reserve(loaded.triangles.size() * 3);
1655 loaded_vlist.reserve(loaded.triangles.size());
1656
1657 for (const detail::OBJTriangle &source_triangle : loaded.triangles) {
1658 Triangle triangle;
1659 triangle.state = MX_ACTIVE;
1660 triangle.material_name = source_triangle.material_name;
1661 triangle.source_object_name = source_triangle.object_name;
1662 const auto material = material_indices.find(source_triangle.material_name);
1663 if (material != material_indices.end()) {
1664 triangle.material_index = material->second;
1665 triangle.color = material_color(loaded.materials[static_cast<std::size_t>(material->second)]);
1666 }
1667
1668 for (std::size_t vertex_index = 0; vertex_index < source_triangle.vertices.size(); ++vertex_index) {
1669 const detail::OBJVertex &source_vertex = source_triangle.vertices[vertex_index];
1670 const float x = source_vertex.position[0] * scale.x;
1671 const float y = source_vertex.position[1] * scale.y;
1672 const float z = source_vertex.position[2] * scale.z;
1673 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(z)) {
1674 std::cerr << "mxvk_math: failed to load OBJ model '" << path << "': scaled vertex is not finite\n";
1675 return false;
1676 }
1677 triangle.vert[vertex_index] = static_cast<int>(loaded_local.size());
1678 loaded_local.emplace_back(x, y, z, 1.0f);
1679 loaded_texcoords.emplace_back(source_vertex.texcoord[0], source_vertex.texcoord[1]);
1680 }
1681 loaded_vlist.push_back(triangle);
1682 }
1683
1684 object_name = std::move(loaded.object_name);
1685 num_vertices = static_cast<int>(loaded_local.size());
1686 num_polys = static_cast<int>(loaded_vlist.size());
1687 local = std::move(loaded_local);
1688 trans.resize(local.size());
1689 texcoords = std::move(loaded_texcoords);
1690 vlist = std::move(loaded_vlist);
1691 materials = std::move(loaded.materials);
1692 material_library_path = std::move(loaded.material_library_path);
1693 world_pos = obj_pos;
1694 dir = rotation;
1695 ComputeRad();
1696 std::cout << "mxvk_math: OBJ model ready (object='" << object_name << "', vertices=" << num_vertices << ", triangles=" << num_polys << ", materials=" << materials.size() << ")\n";
1697 return true;
1698 }
float ComputeRad()
Compute and cache average and maximum local-space radii.
Definition mxvk_math.h:1807
vec4D world_pos
Object world position.
Definition mxvk_math.h:1454
std::vector< vec2D > texcoords
Optional texture coordinates corresponding to local-space vertices.
Definition mxvk_math.h:1481
int num_polys
Number of loaded polygons.
Definition mxvk_math.h:1472
std::string object_name
Object name loaded from the model file.
Definition mxvk_math.h:1487
vec4D dir
Object direction.
Definition mxvk_math.h:1457
int num_vertices
Number of loaded vertices.
Definition mxvk_math.h:1469
bool load_obj_file(const std::string &path, OBJLoadResult &result, std::string &error)
@ MX_ACTIVE
Active object or polygon.
Definition mxvk_math.h:1358

◆ LoadOBJ() [2/2]

bool mxvk::mxObject::LoadOBJ ( const std::string & path,
const vec4D & scale,
const vec4D & obj_pos,
const vec4D & rotation )
inlinenodiscard

Load a Wavefront OBJ mesh and its referenced MTL material library.

Wavefront faces may use independent position and texture-coordinate indices, negative indices, triangles, quads, or concave polygons. Faces are triangulated and de-indexed into the representation used by the software rasterizer. MTL diffuse colors become triangle colors.

Definition at line 1633 of file mxvk_math_eigen.hpp.

1633 {
1634 std::cout << "mxvk_math_eigen: loading OBJ model: " << path << '\n';
1635 detail::OBJLoadResult loaded;
1636 std::string error;
1637 if (!detail::load_obj_file(path, loaded, error)) {
1638 std::cerr << "mxvk_math_eigen: failed to load OBJ model '" << path << "': " << error << '\n';
1639 return false;
1640 }
1641
1642 std::unordered_map<std::string, int> material_indices;
1643 for (std::size_t index = 0; index < loaded.materials.size(); ++index) {
1644 material_indices.emplace(loaded.materials[index].name, static_cast<int>(index));
1645 }
1646
1647 std::vector<vec4D> loaded_local;
1648 std::vector<vec2D> loaded_texcoords;
1649 std::vector<Triangle> loaded_vlist;
1650 loaded_local.reserve(loaded.triangles.size() * 3);
1651 loaded_texcoords.reserve(loaded.triangles.size() * 3);
1652 loaded_vlist.reserve(loaded.triangles.size());
1653
1654 for (const detail::OBJTriangle &source_triangle : loaded.triangles) {
1655 Triangle triangle;
1656 triangle.state = MX_ACTIVE;
1657 triangle.material_name = source_triangle.material_name;
1658 triangle.source_object_name = source_triangle.object_name;
1659 const auto material = material_indices.find(source_triangle.material_name);
1660 if (material != material_indices.end()) {
1661 triangle.material_index = material->second;
1662 triangle.color = material_color(loaded.materials[static_cast<std::size_t>(material->second)]);
1663 }
1664
1665 for (std::size_t vertex_index = 0; vertex_index < source_triangle.vertices.size(); ++vertex_index) {
1666 const detail::OBJVertex &source_vertex = source_triangle.vertices[vertex_index];
1667 const Eigen::Vector3f scaled =
1668 Eigen::Vector3f(source_vertex.position[0], source_vertex.position[1], source_vertex.position[2])
1669 .cwiseProduct(Eigen::Vector3f(scale.x, scale.y, scale.z));
1670 if (!scaled.allFinite()) {
1671 std::cerr << "mxvk_math_eigen: failed to load OBJ model '" << path << "': scaled vertex is not finite\n";
1672 return false;
1673 }
1674 triangle.vert[vertex_index] = static_cast<int>(loaded_local.size());
1675 loaded_local.emplace_back(scaled.x(), scaled.y(), scaled.z(), 1.0f);
1676 loaded_texcoords.emplace_back(source_vertex.texcoord[0], source_vertex.texcoord[1]);
1677 }
1678 loaded_vlist.push_back(triangle);
1679 }
1680
1681 object_name = std::move(loaded.object_name);
1682 num_vertices = static_cast<int>(loaded_local.size());
1683 num_polys = static_cast<int>(loaded_vlist.size());
1684 local = std::move(loaded_local);
1685 trans.resize(local.size());
1686 texcoords = std::move(loaded_texcoords);
1687 vlist = std::move(loaded_vlist);
1688 materials = std::move(loaded.materials);
1689 material_library_path = std::move(loaded.material_library_path);
1690 world_pos = obj_pos;
1691 dir = rotation;
1692 ComputeRad();
1693 std::cout << "mxvk_math_eigen: OBJ model ready (object='" << object_name << "', vertices=" << num_vertices << ", triangles=" << num_polys << ", materials=" << materials.size() << ")\n";
1694 return true;
1695 }

◆ LoadPLG() [1/2]

bool mxvk::mxObject::LoadPLG ( const std::string & path,
const vec4D & scale,
const vec4D & obj_pos,
const vec4D & rotation )
inlinenodiscard

Load a PLG mesh file.

Parameters
pathFile path to load.
scalePer-axis scale applied to vertices.
obj_posWorld position assigned to the object.
rotationObject direction assigned after loading.
Returns
True when the file is opened and parsed successfully.

Vertex lines may contain optional u v texture coordinates after x y z. Blank lines and lines beginning with # are ignored. If loading fails, the object retains its previous mesh, texture coordinates, and transform.

Definition at line 1507 of file mxvk_math.h.

1507 {
1508 std::cout << "mxvk_math: loading PLG model: " << path << '\n';
1509 const auto load_failed = [&path](const char *reason) {
1510 std::cerr << "mxvk_math: failed to load PLG model '" << path << "': " << reason << '\n';
1511 return false;
1512 };
1513
1514 std::ifstream file(path);
1515 if (!file.is_open()) {
1516 return load_failed("could not open file");
1517 }
1518
1519 const auto read_data_line = [&file](std::string &line) {
1520 while (std::getline(file, line)) {
1521 const std::size_t comment = line.find('#');
1522 if (comment != std::string::npos) {
1523 line.erase(comment);
1524 }
1525 if (line.find_first_not_of(" \t\r\n") != std::string::npos) {
1526 return true;
1527 }
1528 }
1529 return false;
1530 };
1531
1532 std::string line;
1533 if (!read_data_line(line)) {
1534 return load_failed("missing model header");
1535 }
1536
1537 std::string name;
1538 int vertex_count = 0;
1539 int poly_count = 0;
1540 std::istringstream header(line);
1541 if (!(header >> name >> vertex_count >> poly_count) || vertex_count < 0 || poly_count < 0) {
1542 return load_failed("invalid model header");
1543 }
1544 std::cout << "mxvk_math: PLG header parsed (object='" << name << "', vertices=" << vertex_count << ", triangles=" << poly_count << ")\n";
1545
1546 std::vector<vec4D> loaded_local;
1547 std::vector<vec4D> loaded_trans;
1548 std::vector<vec2D> loaded_texcoords;
1549 std::vector<Triangle> loaded_vlist;
1550 loaded_local.reserve(static_cast<std::size_t>(vertex_count));
1551 loaded_trans.resize(static_cast<std::size_t>(vertex_count));
1552 loaded_texcoords.reserve(static_cast<std::size_t>(vertex_count));
1553 loaded_vlist.reserve(static_cast<std::size_t>(poly_count));
1554
1555 for (int i = 0; i < vertex_count; ++i) {
1556 if (!read_data_line(line)) {
1557 return load_failed("vertex data ended early");
1558 }
1559
1560 vec4D vertex;
1561 std::istringstream vertex_line(line);
1562 if (!(vertex_line >> vertex.x >> vertex.y >> vertex.z) ||
1563 !std::isfinite(vertex.x) || !std::isfinite(vertex.y) || !std::isfinite(vertex.z)) {
1564 return load_failed("invalid vertex data");
1565 }
1566
1567 vec2D texcoord;
1568 if (vertex_line >> texcoord.x) {
1569 if (!(vertex_line >> texcoord.y) || !std::isfinite(texcoord.x) || !std::isfinite(texcoord.y)) {
1570 return load_failed("invalid texture coordinates");
1571 }
1572 }
1573
1574 vertex.x *= scale.x;
1575 vertex.y *= scale.y;
1576 vertex.z *= scale.z;
1577 if (!std::isfinite(vertex.x) || !std::isfinite(vertex.y) || !std::isfinite(vertex.z)) {
1578 return load_failed("scaled vertex is not finite");
1579 }
1580 vertex.w = 1.0f;
1581 loaded_local.push_back(vertex);
1582 loaded_texcoords.push_back(texcoord);
1583 }
1584
1585 for (int i = 0; i < poly_count; ++i) {
1586 if (!read_data_line(line)) {
1587 return load_failed("triangle data ended early");
1588 }
1589
1590 Triangle tri;
1591 int count = 0;
1592 std::istringstream polygon_line(line);
1593 if (!(polygon_line >> std::hex >> tri.state >> std::dec >> count) || count != 3 ||
1594 !(polygon_line >> tri.vert[0] >> tri.vert[1] >> tri.vert[2])) {
1595 return load_failed("invalid triangle data");
1596 }
1597 for (const int index : tri.vert) {
1598 if (index < 0 || index >= vertex_count) {
1599 return load_failed("triangle vertex index is out of range");
1600 }
1601 }
1602 loaded_vlist.push_back(tri);
1603 }
1604
1605 for (auto &triangle : loaded_vlist) {
1606 triangle.color = MXVK_RGB(rrand(0, 255), rrand(0, 255), rrand(0, 255));
1607 }
1608
1609 object_name = std::move(name);
1610 num_vertices = vertex_count;
1611 num_polys = poly_count;
1612 local = std::move(loaded_local);
1613 trans = std::move(loaded_trans);
1614 texcoords = std::move(loaded_texcoords);
1615 vlist = std::move(loaded_vlist);
1616 world_pos = obj_pos;
1617 dir = rotation;
1618 ComputeRad();
1619 std::cout << "mxvk_math: PLG model ready (object='" << object_name << "', average radius=" << avg_rad << ", maximum radius=" << max_rad << ")\n";
1620 return true;
1621 }
int rrand(int x, int y)
Return a pseudo-random integer in the inclusive range between two bounds.
Definition mxvk_math.h:169
constexpr MXCOLOR MXVK_RGB(int r, int g, int b)
Build an opaque ARGB color from red, green, and blue components.
Definition mxvk_math.h:49

◆ LoadPLG() [2/2]

bool mxvk::mxObject::LoadPLG ( const std::string & path,
const vec4D & scale,
const vec4D & obj_pos,
const vec4D & rotation )
inlinenodiscard

Load a PLG mesh file.

Parameters
pathFile path to load.
scalePer-axis scale applied to vertices.
obj_posWorld position assigned to the object.
rotationObject direction assigned after loading.
Returns
True when the file is opened and parsed successfully.

Vertex lines may contain optional u v texture coordinates after x y z. Blank lines and lines beginning with # are ignored. If loading fails, the object retains its previous mesh, texture coordinates, and transform.

Definition at line 1507 of file mxvk_math_eigen.hpp.

1507 {
1508 std::cout << "mxvk_math_eigen: loading PLG model: " << path << '\n';
1509 const auto load_failed = [&path](const char *reason) {
1510 std::cerr << "mxvk_math_eigen: failed to load PLG model '" << path << "': " << reason << '\n';
1511 return false;
1512 };
1513
1514 std::ifstream file(path);
1515 if (!file.is_open()) {
1516 return load_failed("could not open file");
1517 }
1518
1519 const auto read_data_line = [&file](std::string &line) {
1520 while (std::getline(file, line)) {
1521 const std::size_t comment = line.find('#');
1522 if (comment != std::string::npos) {
1523 line.erase(comment);
1524 }
1525 if (line.find_first_not_of(" \t\r\n") != std::string::npos) {
1526 return true;
1527 }
1528 }
1529 return false;
1530 };
1531
1532 std::string line;
1533 if (!read_data_line(line)) {
1534 return load_failed("missing model header");
1535 }
1536
1537 std::string name;
1538 int vertex_count = 0;
1539 int poly_count = 0;
1540 std::istringstream header(line);
1541 if (!(header >> name >> vertex_count >> poly_count) || vertex_count < 0 || poly_count < 0) {
1542 return load_failed("invalid model header");
1543 }
1544 std::cout << "mxvk_math_eigen: PLG header parsed (object='" << name << "', vertices=" << vertex_count << ", triangles=" << poly_count << ")\n";
1545
1546 std::vector<vec4D> loaded_local;
1547 std::vector<vec4D> loaded_trans;
1548 std::vector<vec2D> loaded_texcoords;
1549 std::vector<Triangle> loaded_vlist;
1550 loaded_local.reserve(static_cast<std::size_t>(vertex_count));
1551 loaded_trans.resize(static_cast<std::size_t>(vertex_count));
1552 loaded_texcoords.reserve(static_cast<std::size_t>(vertex_count));
1553 loaded_vlist.reserve(static_cast<std::size_t>(poly_count));
1554
1555 for (int i = 0; i < vertex_count; ++i) {
1556 if (!read_data_line(line)) {
1557 return load_failed("vertex data ended early");
1558 }
1559
1560 Eigen::Vector3f coordinates;
1561 std::istringstream vertex_line(line);
1562 if (!(vertex_line >> coordinates.x() >> coordinates.y() >> coordinates.z()) || !coordinates.allFinite()) {
1563 return load_failed("invalid vertex data");
1564 }
1565
1566 vec2D texcoord;
1567 if (vertex_line >> texcoord.x) {
1568 if (!(vertex_line >> texcoord.y) || !std::isfinite(texcoord.x) || !std::isfinite(texcoord.y)) {
1569 return load_failed("invalid texture coordinates");
1570 }
1571 }
1572
1573 const Eigen::Vector3f scaled =
1574 coordinates.cwiseProduct(Eigen::Vector3f(scale.x, scale.y, scale.z));
1575 if (!scaled.allFinite()) {
1576 return load_failed("scaled vertex is not finite");
1577 }
1578 loaded_local.emplace_back(scaled.x(), scaled.y(), scaled.z(), 1.0f);
1579 loaded_texcoords.push_back(texcoord);
1580 }
1581
1582 for (int i = 0; i < poly_count; ++i) {
1583 if (!read_data_line(line)) {
1584 return load_failed("triangle data ended early");
1585 }
1586
1587 Triangle tri;
1588 int count = 0;
1589 std::istringstream polygon_line(line);
1590 if (!(polygon_line >> std::hex >> tri.state >> std::dec >> count) || count != 3 ||
1591 !(polygon_line >> tri.vert[0] >> tri.vert[1] >> tri.vert[2])) {
1592 return load_failed("invalid triangle data");
1593 }
1594 for (const int index : tri.vert) {
1595 if (index < 0 || index >= vertex_count) {
1596 return load_failed("triangle vertex index is out of range");
1597 }
1598 }
1599 loaded_vlist.push_back(tri);
1600 }
1601
1602 for (auto &triangle : loaded_vlist) {
1603 triangle.color = MXVK_RGB(rrand(0, 255), rrand(0, 255), rrand(0, 255));
1604 }
1605
1606 object_name = std::move(name);
1607 num_vertices = vertex_count;
1608 num_polys = poly_count;
1609 local = std::move(loaded_local);
1610 trans = std::move(loaded_trans);
1611 texcoords = std::move(loaded_texcoords);
1612 vlist = std::move(loaded_vlist);
1613 world_pos = obj_pos;
1614 dir = rotation;
1615 ComputeRad();
1616 std::cout << "mxvk_math_eigen: PLG model ready (object='" << object_name << "', average radius=" << avg_rad << ", maximum radius=" << max_rad << ")\n";
1617 return true;
1618 }

◆ ModelToWorld() [1/2]

void mxvk::mxObject::ModelToWorld ( int type = 0)
inline

Convert local or transformed vertices to world space.

Definition at line 1730 of file mxvk_math.h.

1730 {
1731 if (type == 0) {
1732 trans.resize(local.size());
1733 for (std::size_t i = 0; i < local.size(); ++i) {
1734 trans[i] = local[i] + world_pos;
1735 }
1736 } else if (type == 1) {
1737 for (auto &vertex : trans) {
1738 vertex += world_pos;
1739 }
1740 }
1741 }

◆ ModelToWorld() [2/2]

void mxvk::mxObject::ModelToWorld ( int type = 0)
inline

Convert local or transformed vertices to world space.

Definition at line 1727 of file mxvk_math_eigen.hpp.

1727 {
1728 if (type == 0) {
1729 trans.resize(local.size());
1730 for (std::size_t i = 0; i < local.size(); ++i) {
1731 trans[i] = local[i] + world_pos;
1732 }
1733 } else if (type == 1) {
1734 for (auto &vertex : trans) {
1735 vertex += world_pos;
1736 }
1737 }
1738 }

◆ RemoveFaces() [1/2]

void mxvk::mxObject::RemoveFaces ( const vec4D & pos)
inline

Mark object polygons that face away from a view position.

Definition at line 1763 of file mxvk_math.h.

1763 {
1764 for (auto &poly : vlist) {
1765 if (poly.state == 0 || (poly.state & MX_BACKFACE) != 0 || (poly.state & MX_CULLED) != 0) {
1766 continue;
1767 }
1768 if (poly.vert[0] < 0 || poly.vert[1] < 0 || poly.vert[2] < 0 || static_cast<std::size_t>(poly.vert[0]) >= trans.size() || static_cast<std::size_t>(poly.vert[1]) >= trans.size() || static_cast<std::size_t>(poly.vert[2]) >= trans.size()) {
1769 continue;
1770 }
1771 const vec4D u = vec4D().Build(trans[static_cast<std::size_t>(poly.vert[0])], trans[static_cast<std::size_t>(poly.vert[1])]);
1772 const vec4D v = vec4D().Build(trans[static_cast<std::size_t>(poly.vert[0])], trans[static_cast<std::size_t>(poly.vert[2])]);
1773 const vec4D n = u.CrossProduct(v);
1774 const vec4D view = vec4D().Build(trans[static_cast<std::size_t>(poly.vert[0])], pos);
1775 if (n.DotProduct(view) <= 0.0f) {
1776 poly.state |= MX_BACKFACE;
1777 }
1778 }
1779 }
@ MX_CULLED
Object or polygon is culled.
Definition mxvk_math.h:1367
@ MX_BACKFACE
Polygon is marked as a backface.
Definition mxvk_math.h:1364

◆ RemoveFaces() [2/2]

void mxvk::mxObject::RemoveFaces ( const vec4D & pos)
inline

Mark object polygons that face away from a view position.

Definition at line 1760 of file mxvk_math_eigen.hpp.

1760 {
1761 for (auto &poly : vlist) {
1762 if (poly.state == 0 || (poly.state & MX_BACKFACE) != 0 || (poly.state & MX_CULLED) != 0) {
1763 continue;
1764 }
1765 if (poly.vert[0] < 0 || poly.vert[1] < 0 || poly.vert[2] < 0 || static_cast<std::size_t>(poly.vert[0]) >= trans.size() || static_cast<std::size_t>(poly.vert[1]) >= trans.size() || static_cast<std::size_t>(poly.vert[2]) >= trans.size()) {
1766 continue;
1767 }
1768 const vec4D u = vec4D().Build(trans[static_cast<std::size_t>(poly.vert[0])], trans[static_cast<std::size_t>(poly.vert[1])]);
1769 const vec4D v = vec4D().Build(trans[static_cast<std::size_t>(poly.vert[0])], trans[static_cast<std::size_t>(poly.vert[2])]);
1770 const vec4D n = u.CrossProduct(v);
1771 const vec4D view = vec4D().Build(trans[static_cast<std::size_t>(poly.vert[0])], pos);
1772 if (n.DotProduct(view) <= 0.0f) {
1773 poly.state |= MX_BACKFACE;
1774 }
1775 }
1776 }

◆ Reset() [1/2]

void mxvk::mxObject::Reset ( )
inline

Reset object and polygon state to active.

Definition at line 1799 of file mxvk_math.h.

1799 {
1800 for (auto &poly : vlist) {
1801 poly.state = MX_ACTIVE;
1802 }
1803 state = MX_ACTIVE;
1804 }
int state
Object state flags.
Definition mxvk_math.h:1442

◆ Reset() [2/2]

void mxvk::mxObject::Reset ( )
inline

Reset object and polygon state to active.

Definition at line 1796 of file mxvk_math_eigen.hpp.

1796 {
1797 for (auto &poly : vlist) {
1798 poly.state = MX_ACTIVE;
1799 }
1800 state = MX_ACTIVE;
1801 }

◆ SetState() [1/2]

void mxvk::mxObject::SetState ( int new_state)
inline

Replace the object state flags.

Definition at line 1823 of file mxvk_math.h.

1823 {
1824 state = new_state;
1825 }

◆ SetState() [2/2]

void mxvk::mxObject::SetState ( int new_state)
inline

Replace the object state flags.

Definition at line 1820 of file mxvk_math_eigen.hpp.

1820 {
1821 state = new_state;
1822 }

◆ TransformObject() [1/2]

void mxvk::mxObject::TransformObject ( const Mat4D & mrot,
int type = 0 )
inline

Apply a transform to local vertices, transformed vertices, or local-to-transformed output.

Definition at line 1744 of file mxvk_math.h.

1744 {
1745 auto transform = [&mrot](std::vector<vec4D> &vertices) {
1746 for (auto &vertex : vertices) {
1747 vertex = mrot.MulVec(vertex);
1748 }
1749 };
1750 if (type == 0) {
1751 transform(local);
1752 } else if (type == 1) {
1753 transform(trans);
1754 } else if (type == 2) {
1755 trans.resize(local.size());
1756 for (std::size_t i = 0; i < local.size(); ++i) {
1757 trans[i] = mrot.MulVec(local[i]);
1758 }
1759 }
1760 }

◆ TransformObject() [2/2]

void mxvk::mxObject::TransformObject ( const Mat4D & mrot,
int type = 0 )
inline

Apply a transform to local vertices, transformed vertices, or local-to-transformed output.

Definition at line 1741 of file mxvk_math_eigen.hpp.

1741 {
1742 auto transform = [&mrot](std::vector<vec4D> &vertices) {
1743 for (auto &vertex : vertices) {
1744 vertex = mrot.MulVec(vertex);
1745 }
1746 };
1747 if (type == 0) {
1748 transform(local);
1749 } else if (type == 1) {
1750 transform(trans);
1751 } else if (type == 2) {
1752 trans.resize(local.size());
1753 for (std::size_t i = 0; i < local.size(); ++i) {
1754 trans[i] = mrot.MulVec(local[i]);
1755 }
1756 }
1757 }

Member Data Documentation

◆ attr

int mxvk::mxObject::attr = 0

Object attributes.

Definition at line 1445 of file mxvk_math.h.

◆ avg_rad

float mxvk::mxObject::avg_rad = 0.0f

Average radius from the local origin.

Definition at line 1448 of file mxvk_math.h.

◆ dir

vec4D mxvk::mxObject::dir

Object direction.

Definition at line 1457 of file mxvk_math.h.

◆ local

std::vector< vec4D > mxvk::mxObject::local

Local-space vertices.

Definition at line 1475 of file mxvk_math.h.

◆ material_library_path

std::string mxvk::mxObject::material_library_path

Resolved path of the OBJ material library.

Definition at line 1493 of file mxvk_math.h.

◆ materials

std::vector< OBJMaterial > mxvk::mxObject::materials

Materials loaded from the OBJ material library.

Definition at line 1490 of file mxvk_math.h.

◆ max_rad

float mxvk::mxObject::max_rad = 0.0f

Maximum radius from the local origin.

Definition at line 1451 of file mxvk_math.h.

◆ num_polys

int mxvk::mxObject::num_polys = 0

Number of loaded polygons.

Definition at line 1472 of file mxvk_math.h.

◆ num_vertices

int mxvk::mxObject::num_vertices = 0

Number of loaded vertices.

Definition at line 1469 of file mxvk_math.h.

◆ object_name

std::string mxvk::mxObject::object_name

Object name loaded from the model file.

Definition at line 1487 of file mxvk_math.h.

◆ state

int mxvk::mxObject::state = MX_ACTIVE

Object state flags.

Definition at line 1442 of file mxvk_math.h.

◆ texcoords

std::vector< vec2D > mxvk::mxObject::texcoords

Optional texture coordinates corresponding to local-space vertices.

Definition at line 1481 of file mxvk_math.h.

◆ trans

std::vector< vec4D > mxvk::mxObject::trans

Transformed vertices.

Definition at line 1478 of file mxvk_math.h.

◆ ux

vec4D mxvk::mxObject::ux

Local X basis vector.

Definition at line 1460 of file mxvk_math.h.

◆ uy

vec4D mxvk::mxObject::uy

Local Y basis vector.

Definition at line 1463 of file mxvk_math.h.

◆ uz

vec4D mxvk::mxObject::uz

Local Z basis vector.

Definition at line 1466 of file mxvk_math.h.

◆ vlist

std::vector< Triangle > mxvk::mxObject::vlist

Indexed triangle list.

Definition at line 1484 of file mxvk_math.h.

◆ world_pos

vec4D mxvk::mxObject::world_pos

Object world position.

Definition at line 1454 of file mxvk_math.h.


The documentation for this class was generated from the following files: