File: recastmesh.cpp

package info (click to toggle)
openmw 0.50.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 37,076 kB
  • sloc: cpp: 380,958; xml: 2,192; sh: 1,449; python: 911; makefile: 26; javascript: 5
file content (76 lines) | stat: -rw-r--r-- 2,967 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include "recastmesh.hpp"

#include "detourdebugdraw.hpp"

#include <components/detournavigator/recastmesh.hpp>
#include <components/detournavigator/recastmeshbuilder.hpp>
#include <components/detournavigator/settings.hpp>

#include <RecastDebugDraw.h>

#include <osg/Group>
#include <osg/Material>
#include <osg/PolygonOffset>

#include <algorithm>
#include <vector>

namespace
{
    std::vector<float> calculateNormals(const std::vector<float>& vertices, const std::vector<int>& indices)
    {
        std::vector<float> result(indices.size());
        for (std::size_t i = 0, n = indices.size(); i < n; i += 3)
        {
            const float* v0Ptr = &vertices[indices[i] * 3];
            const float* v1Ptr = &vertices[indices[i + 1] * 3];
            const float* v2Ptr = &vertices[indices[i + 2] * 3];
            const osg::Vec3f v0(v0Ptr[0], v0Ptr[1], v0Ptr[2]);
            const osg::Vec3f v1(v1Ptr[0], v1Ptr[1], v1Ptr[2]);
            const osg::Vec3f v2(v2Ptr[0], v2Ptr[1], v2Ptr[2]);
            const osg::Vec3f e0 = v1 - v0;
            const osg::Vec3f e1 = v2 - v0;
            osg::Vec3f normal = e0 ^ e1;
            normal.normalize();
            for (std::size_t j = 0; j < 3; ++j)
                result[i + j] = normal[j];
        }
        return result;
    }
}

namespace SceneUtil
{
    osg::ref_ptr<osg::Group> createRecastMeshGroup(const DetourNavigator::RecastMesh& recastMesh,
        const DetourNavigator::RecastSettings& settings, const osg::ref_ptr<osg::StateSet>& debugDrawStateSet)
    {
        using namespace DetourNavigator;

        const osg::ref_ptr<osg::Group> group(new osg::Group);

        DebugDraw debugDraw(*group, debugDrawStateSet, osg::Vec3f(0, 0, 0), 1.0f);
        const DetourNavigator::Mesh& mesh = recastMesh.getMesh();
        std::vector<int> indices = mesh.getIndices();
        std::vector<float> vertices = mesh.getVertices();

        for (const Heightfield& heightfield : recastMesh.getHeightfields())
        {
            const Mesh heightfieldMesh = makeMesh(heightfield);
            const int indexShift = static_cast<int>(vertices.size() / 3);
            std::copy(heightfieldMesh.getVertices().begin(), heightfieldMesh.getVertices().end(),
                std::back_inserter(vertices));
            std::transform(heightfieldMesh.getIndices().begin(), heightfieldMesh.getIndices().end(),
                std::back_inserter(indices), [&](int index) { return index + indexShift; });
        }

        for (std::size_t i = 0; i < vertices.size(); i += 3)
            std::swap(vertices[i + 1], vertices[i + 2]);

        const auto normals = calculateNormals(vertices, indices);
        const auto texScale = 1.0f / (settings.mCellSize * 10.0f);
        duDebugDrawTriMeshSlope(&debugDraw, vertices.data(), static_cast<int>(vertices.size() / 3), indices.data(),
            normals.data(), static_cast<int>(indices.size() / 3), settings.mMaxSlope, texScale);

        return group;
    }
}