<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2011 Francois Beaune
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "diagnosticsurfaceshader.h"

// appleseed.renderer headers.
#include "renderer/kernel/shading/ambientocclusion.h"
#include "renderer/kernel/shading/shadingcontext.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/kernel/shading/shadingresult.h"
#include "renderer/modeling/camera/camera.h"
#include "renderer/modeling/input/inputarray.h"
#include "renderer/modeling/input/source.h"
#include "renderer/modeling/material/material.h"
#include "renderer/modeling/scene/scene.h"
#include "renderer/utility/transformsequence.h"

// appleseed.foundation headers.
#include "foundation/image/colorspace.h"
#include "foundation/math/distance.h"
#include "foundation/math/frustum.h"
#include "foundation/math/hash.h"
#include "foundation/math/minmax.h"
#include "foundation/math/scalar.h"
#include "foundation/utility/containers/specializedarrays.h"

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    // Utility function to compute a color from a given normal vector.
    inline Color3f normal_to_color(const Vector3d& n)
    {
        assert(abs(n[0]) <= 1.0);
        assert(abs(n[1]) <= 1.0);
        assert(abs(n[2]) <= 1.0);

        return Color3f(
            static_cast<float>((n[0] + 1.0) * 0.5),
            static_cast<float>((n[1] + 1.0) * 0.5),
            static_cast<float>((n[2] + 1.0) * 0.5));
    }

    // Utility function to compute a color from a given integer value.
    template <typename T>
    inline Color3f integer_to_color(const T i)
    {
        const uint32 u = static_cast<uint32>(i);    // keep the low 32 bits

        const uint32 x = hashint32(u);
        const uint32 y = hashint32(u + 1);
        const uint32 z = hashint32(u + 2);

        return Color3f(
            static_cast<float>(x) * (1.0f / 4294967295.0f),
            static_cast<float>(y) * (1.0f / 4294967295.0f),
            static_cast<float>(z) * (1.0f / 4294967295.0f));
    }
}

//
// Diagnostic surface shader.
//

const char* Model = "diagnostic_surface_shader";

struct DiagnosticSurfaceShader::Impl
{
    ShadingMode                 m_shading_mode;
    double                      m_ao_max_distance;
    size_t                      m_ao_samples;
};

const KeyValuePair<const char*, DiagnosticSurfaceShader::ShadingMode>
    DiagnosticSurfaceShader::ShadingModeValues[] =
{
    { "coverage",               Coverage },
    { "barycentric",            Barycentric },
    { "uv",                     UV },
    { "geometric_normal",       GeometricNormal },
    { "shading_normal",         ShadingNormal },
    { "assembly_instances",     AssemblyInstances },
    { "object_instances",       ObjectInstances },
    { "regions",                Regions },
    { "triangles",              Triangles },
    { "materials",              Materials  },
    { "ambient_occlusion",      AmbientOcclusion },
    { "wireframe" ,             Wireframe }
};

const KeyValuePair<const char*, const char*> DiagnosticSurfaceShader::ShadingModeNames[] =
{
    { "coverage",               "Coverage" },
    { "barycentric",            "Barycentric Coordinates" },
    { "uv",                     "UV Coordinates" },
    { "geometric_normal",       "Geometric Normals" },
    { "shading_normal",         "Shading Normals" },
    { "assembly_instances",     "Assembly Instances" },
    { "object_instances",       "Object Instances" },
    { "regions",                "Regions" },
    { "triangles",              "Triangles" },
    { "materials",              "Materials" },
    { "ambient_occlusion",      "Ambient Occlusion" },
    { "wireframe" ,             "Wireframe" }
};

DiagnosticSurfaceShader::DiagnosticSurfaceShader(
    const char*             name,
    const ParamArray&       params)
  : SurfaceShader(name, params)
  , impl(new Impl())
{
    extract_parameters();
}

void DiagnosticSurfaceShader::release()
{
    delete this;
}

const char* DiagnosticSurfaceShader::get_model() const
{
    return Model;
}

void DiagnosticSurfaceShader::evaluate(
    SamplingContext&        sampling_context,
    const ShadingContext&   shading_context,
    const ShadingPoint&     shading_point,
    ShadingResult&          shading_result) const
{
    switch (impl->m_shading_mode)
    {
      // Shade according to pixel coverage
      case Coverage:
        shading_result.set_to_linear_rgb(Color3f(1.0f));
        break;

      // Shade according to barycentric coordinates.
      case Barycentric:
        {
            const Vector2d& bary = shading_point.get_bary();
            shading_result.set_to_linear_rgb(
                Color3f(
                    static_cast<float>(1.0 - bary[0] - bary[1]),
                    static_cast<float>(bary[0]),
                    static_cast<float>(bary[1])));
        }
        break;

      // Shade according to UV coordinates from UV set #0.
      case UV:
        {
            const Vector2d& uv0 = shading_point.get_uv(0);
            shading_result.set_to_linear_rgb(
                Color3f(
                    static_cast<float>(1.0 - uv0[0] - uv0[1]),
                    static_cast<float>(uv0[0]),
                    static_cast<float>(uv0[1])));
        }
        break;

      // Shade according to the geometric normal.
      case GeometricNormal:
        shading_result.set_to_linear_rgb(
            normal_to_color(shading_point.get_geometric_normal()));
        break;

      // Shade according to the shading normal.
      case ShadingNormal:
        shading_result.set_to_linear_rgb(
            normal_to_color(shading_point.get_shading_normal()));
        break;

      // Assign an unique color to each assembly instance.
      case AssemblyInstances:
        shading_result.set_to_linear_rgb(
            integer_to_color(shading_point.get_assembly_instance_uid()));
        break;

      // Assign an unique color to each object instance.
      case ObjectInstances:
        shading_result.set_to_linear_rgb(
            integer_to_color(shading_point.get_object_instance().get_uid()));
        break;

      // Assign an unique color to each region.
      case Regions:
        {
            const uint32 h =
                mix32(
                    static_cast<uint32>(shading_point.get_object_instance().get_uid()),
                    static_cast<uint32>(shading_point.get_region_index()));
            shading_result.set_to_linear_rgb(integer_to_color(h));
        }
        break;

      // Assign an unique color to each triangle.
      case Triangles:
        {
            const uint32 h =
                mix32(
                    static_cast<uint32>(shading_point.get_object_instance().get_uid()),
                    static_cast<uint32>(shading_point.get_region_index()),
                    static_cast<uint32>(shading_point.get_triangle_index()));
            shading_result.set_to_linear_rgb(integer_to_color(h));
        }
        break;

      // Assign an unique color to each material.
      case Materials:
        {
            const ObjectInstance& object_instance = shading_point.get_object_instance();
            const size_t pa_index = shading_point.get_primitive_attribute_index();
            const MaterialArray& materials = object_instance.get_materials();
            if (pa_index < materials.size())
            {
                assert(materials[pa_index]);
                shading_result.set_to_linear_rgb(
                    integer_to_color(materials[pa_index]->get_uid()));
            }
            else shading_result.set_to_solid_pink();
        }
        break;

      // Ambient occlusion.
      case AmbientOcclusion:
        {
            // Compute the occlusion.
            const double occlusion =
                compute_ambient_occlusion(
                    sampling_context,
                    sample_hemisphere_uniform<double>,
                    shading_context.get_intersector(),
                    shading_point.get_point(),
                    shading_point.get_geometric_normal(),
                    shading_point.get_shading_basis(),
                    impl->m_ao_max_distance,
                    impl->m_ao_samples,
                    &shading_point);

            // Return a gray scale value proportional to the accessibility.
            const float accessibility = static_cast<float>(1.0 - occlusion);
            shading_result.set_to_linear_rgb(Color3f(accessibility));
        }
        break;

      // Wireframe.
      case Wireframe:
        {
            // Film space thickness of the wires.
            const double SquareWireThickness = square(0.0005);

            // Initialize the shading result to the background color.
            shading_result.set_to_linear_rgba(Color4f(0.0f, 0.0f, 0.8f, 0.5f));

            // Retrieve the camera.
            const Scene& scene = shading_point.get_scene();
            const Camera& camera = *scene.get_camera();
            const double time = shading_point.get_ray().m_time;
            const Transformd camera_transform = camera.transform_sequence().evaluate(time);
            const Pyramid3d& view_pyramid = camera.get_view_pyramid();

            // Compute the film space coordinates of the intersection point.
            const Vector3d& point = shading_point.get_point();
            const Vector3d point_cs = camera_transform.transform_point_to_local(point);
            const Vector2d point_fs = camera.project(point_cs);

            // Compute the camera space coordinates of the triangle vertices.
            Vector3d v_cs[3];
            v_cs[0] = camera_transform.transform_point_to_local(shading_point.get_vertex(0));
            v_cs[1] = camera_transform.transform_point_to_local(shading_point.get_vertex(1));
            v_cs[2] = camera_transform.transform_point_to_local(shading_point.get_vertex(2));

            // Loop over the triangle edges.
            for (size_t i = 0; i < 3; ++i)
            {
                // Compute the end points of this edge.
                const size_t j = (i + 1) % 3;
                Vector3d vi_cs = v_cs[i];
                Vector3d vj_cs = v_cs[j];

                // Clip the edge against the view pyramid.
                if (!view_pyramid.clip(vi_cs, vj_cs))
                    continue;

                // Transform the edge to film space.
                const Vector2d vi_fs = camera.project(vi_cs);
                const Vector2d vj_fs = camera.project(vj_cs);

                // Compute the film space distance from the intersection point to the edge.
                const double d = square_distance_point_segment(point_fs, vi_fs, vj_fs);

                if (d < SquareWireThickness)
                {
                    shading_result.set_to_linear_rgba(Color4f(1.0f));
                    break;
                }
            }
        }
        break;

      // Invalid shader.
      default:
        assert(false);
        shading_result.clear();
        break;
    }
}

void DiagnosticSurfaceShader::extract_parameters()
{
    // Retrieve shading mode.
    const string mode_string = m_params.get_required<string>("mode", "coverage");
    const KeyValuePair<const char*, ShadingMode>* mode_pair =
        lookup_kvpair_array(ShadingModeValues, ShadingModeCount, mode_string);
    if (mode_pair)
    {
        impl->m_shading_mode = mode_pair->m_value;
    }
    else
    {
        RENDERER_LOG_ERROR(
            "invalid shading mode \"%s\", using default value \"coverage\"",
            mode_string.c_str());
        impl->m_shading_mode = Coverage;
    }

    // Retrieve ambient occlusion parameters.
    if (impl->m_shading_mode == AmbientOcclusion)
    {
        const ParamArray& ao_params = m_params.child("ambient_occlusion");
        impl->m_ao_max_distance = ao_params.get_optional<double>("max_distance", 1.0);
        impl->m_ao_samples = ao_params.get_optional<size_t>("samples", 16);
    }
}

//
// DiagnosticSurfaceShaderFactory class implementation.
//

const char* DiagnosticSurfaceShaderFactory::get_model() const
{
    return Model;
}

const char* DiagnosticSurfaceShaderFactory::get_human_readable_model() const
{
    return "Diagnostics";
}

DictionaryArray DiagnosticSurfaceShaderFactory::get_widget_definitions() const
{
    Dictionary model_items;

    for (int i = 0; i < DiagnosticSurfaceShader::ShadingModeCount; ++i)
    {
        const char* shading_mode_value = DiagnosticSurfaceShader::ShadingModeNames[i].m_key;
        const char* shading_mode_name = DiagnosticSurfaceShader::ShadingModeNames[i].m_value;
        model_items.insert(shading_mode_name, shading_mode_value);
    }

    DictionaryArray definitions;

    definitions.push_back(
        Dictionary()
            .insert("name", "mode")
            .insert("label", "Mode")
            .insert("widget", "dropdown_list")
            .insert("dropdown_items", model_items)
            .insert("use", "required")
            .insert("default", "coverage")
            .insert("on_change", "rebuild_form"));

    return definitions;
}

auto_release_ptr<SurfaceShader> DiagnosticSurfaceShaderFactory::create(
    const char*         name,
    const ParamArray&   params) const
{
    return
        auto_release_ptr<SurfaceShader>(
            new DiagnosticSurfaceShader(name, params));
}

}   // namespace renderer
<commit_msg>fixed typos, removed redundant comments.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2011 Francois Beaune
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "diagnosticsurfaceshader.h"

// appleseed.renderer headers.
#include "renderer/kernel/shading/ambientocclusion.h"
#include "renderer/kernel/shading/shadingcontext.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/kernel/shading/shadingresult.h"
#include "renderer/modeling/camera/camera.h"
#include "renderer/modeling/input/inputarray.h"
#include "renderer/modeling/input/source.h"
#include "renderer/modeling/material/material.h"
#include "renderer/modeling/scene/scene.h"
#include "renderer/utility/transformsequence.h"

// appleseed.foundation headers.
#include "foundation/image/colorspace.h"
#include "foundation/math/distance.h"
#include "foundation/math/frustum.h"
#include "foundation/math/hash.h"
#include "foundation/math/minmax.h"
#include "foundation/math/scalar.h"
#include "foundation/utility/containers/specializedarrays.h"

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    // Utility function to compute a color from a given normal vector.
    inline Color3f normal_to_color(const Vector3d& n)
    {
        assert(abs(n[0]) <= 1.0);
        assert(abs(n[1]) <= 1.0);
        assert(abs(n[2]) <= 1.0);

        return Color3f(
            static_cast<float>((n[0] + 1.0) * 0.5),
            static_cast<float>((n[1] + 1.0) * 0.5),
            static_cast<float>((n[2] + 1.0) * 0.5));
    }

    // Utility function to compute a color from a given integer value.
    template <typename T>
    inline Color3f integer_to_color(const T i)
    {
        const uint32 u = static_cast<uint32>(i);    // keep the low 32 bits

        const uint32 x = hashint32(u);
        const uint32 y = hashint32(u + 1);
        const uint32 z = hashint32(u + 2);

        return Color3f(
            static_cast<float>(x) * (1.0f / 4294967295.0f),
            static_cast<float>(y) * (1.0f / 4294967295.0f),
            static_cast<float>(z) * (1.0f / 4294967295.0f));
    }
}

//
// Diagnostic surface shader.
//

const char* Model = "diagnostic_surface_shader";

struct DiagnosticSurfaceShader::Impl
{
    ShadingMode                 m_shading_mode;
    double                      m_ao_max_distance;
    size_t                      m_ao_samples;
};

const KeyValuePair<const char*, DiagnosticSurfaceShader::ShadingMode>
    DiagnosticSurfaceShader::ShadingModeValues[] =
{
    { "coverage",               Coverage },
    { "barycentric",            Barycentric },
    { "uv",                     UV },
    { "geometric_normal",       GeometricNormal },
    { "shading_normal",         ShadingNormal },
    { "assembly_instances",     AssemblyInstances },
    { "object_instances",       ObjectInstances },
    { "regions",                Regions },
    { "triangles",              Triangles },
    { "materials",              Materials  },
    { "ambient_occlusion",      AmbientOcclusion },
    { "wireframe" ,             Wireframe }
};

const KeyValuePair<const char*, const char*> DiagnosticSurfaceShader::ShadingModeNames[] =
{
    { "coverage",               "Coverage" },
    { "barycentric",            "Barycentric Coordinates" },
    { "uv",                     "UV Coordinates" },
    { "geometric_normal",       "Geometric Normals" },
    { "shading_normal",         "Shading Normals" },
    { "assembly_instances",     "Assembly Instances" },
    { "object_instances",       "Object Instances" },
    { "regions",                "Regions" },
    { "triangles",              "Triangles" },
    { "materials",              "Materials" },
    { "ambient_occlusion",      "Ambient Occlusion" },
    { "wireframe" ,             "Wireframe" }
};

DiagnosticSurfaceShader::DiagnosticSurfaceShader(
    const char*             name,
    const ParamArray&       params)
  : SurfaceShader(name, params)
  , impl(new Impl())
{
    extract_parameters();
}

void DiagnosticSurfaceShader::release()
{
    delete this;
}

const char* DiagnosticSurfaceShader::get_model() const
{
    return Model;
}

void DiagnosticSurfaceShader::evaluate(
    SamplingContext&        sampling_context,
    const ShadingContext&   shading_context,
    const ShadingPoint&     shading_point,
    ShadingResult&          shading_result) const
{
    switch (impl->m_shading_mode)
    {
      // Shade according to pixel coverage
      case Coverage:
        shading_result.set_to_linear_rgb(Color3f(1.0f));
        break;

      // Shade according to barycentric coordinates.
      case Barycentric:
        {
            const Vector2d& bary = shading_point.get_bary();
            shading_result.set_to_linear_rgb(
                Color3f(
                    static_cast<float>(1.0 - bary[0] - bary[1]),
                    static_cast<float>(bary[0]),
                    static_cast<float>(bary[1])));
        }
        break;

      // Shade according to UV coordinates from UV set #0.
      case UV:
        {
            const Vector2d& uv0 = shading_point.get_uv(0);
            shading_result.set_to_linear_rgb(
                Color3f(
                    static_cast<float>(1.0 - uv0[0] - uv0[1]),
                    static_cast<float>(uv0[0]),
                    static_cast<float>(uv0[1])));
        }
        break;

      // Shade according to the geometric normal.
      case GeometricNormal:
        shading_result.set_to_linear_rgb(
            normal_to_color(shading_point.get_geometric_normal()));
        break;

      // Shade according to the shading normal.
      case ShadingNormal:
        shading_result.set_to_linear_rgb(
            normal_to_color(shading_point.get_shading_normal()));
        break;

      // Assign a unique color to each assembly instance.
      case AssemblyInstances:
        shading_result.set_to_linear_rgb(
            integer_to_color(shading_point.get_assembly_instance_uid()));
        break;

      // Assign a unique color to each object instance.
      case ObjectInstances:
        shading_result.set_to_linear_rgb(
            integer_to_color(shading_point.get_object_instance().get_uid()));
        break;

      // Assign a unique color to each region.
      case Regions:
        {
            const uint32 h =
                mix32(
                    static_cast<uint32>(shading_point.get_object_instance().get_uid()),
                    static_cast<uint32>(shading_point.get_region_index()));
            shading_result.set_to_linear_rgb(integer_to_color(h));
        }
        break;

      // Assign a unique color to each triangle.
      case Triangles:
        {
            const uint32 h =
                mix32(
                    static_cast<uint32>(shading_point.get_object_instance().get_uid()),
                    static_cast<uint32>(shading_point.get_region_index()),
                    static_cast<uint32>(shading_point.get_triangle_index()));
            shading_result.set_to_linear_rgb(integer_to_color(h));
        }
        break;

      // Assign a unique color to each material.
      case Materials:
        {
            const ObjectInstance& object_instance = shading_point.get_object_instance();
            const size_t pa_index = shading_point.get_primitive_attribute_index();
            const MaterialArray& materials = object_instance.get_materials();
            if (pa_index < materials.size())
            {
                assert(materials[pa_index]);
                shading_result.set_to_linear_rgb(
                    integer_to_color(materials[pa_index]->get_uid()));
            }
            else shading_result.set_to_solid_pink();
        }
        break;

      case AmbientOcclusion:
        {
            // Compute the occlusion.
            const double occlusion =
                compute_ambient_occlusion(
                    sampling_context,
                    sample_hemisphere_uniform<double>,
                    shading_context.get_intersector(),
                    shading_point.get_point(),
                    shading_point.get_geometric_normal(),
                    shading_point.get_shading_basis(),
                    impl->m_ao_max_distance,
                    impl->m_ao_samples,
                    &shading_point);

            // Return a gray scale value proportional to the accessibility.
            const float accessibility = static_cast<float>(1.0 - occlusion);
            shading_result.set_to_linear_rgb(Color3f(accessibility));
        }
        break;

      case Wireframe:
        {
            // Film space thickness of the wires.
            const double SquareWireThickness = square(0.0005);

            // Initialize the shading result to the background color.
            shading_result.set_to_linear_rgba(Color4f(0.0f, 0.0f, 0.8f, 0.5f));

            // Retrieve the camera.
            const Scene& scene = shading_point.get_scene();
            const Camera& camera = *scene.get_camera();
            const double time = shading_point.get_ray().m_time;
            const Transformd camera_transform = camera.transform_sequence().evaluate(time);
            const Pyramid3d& view_pyramid = camera.get_view_pyramid();

            // Compute the film space coordinates of the intersection point.
            const Vector3d& point = shading_point.get_point();
            const Vector3d point_cs = camera_transform.transform_point_to_local(point);
            const Vector2d point_fs = camera.project(point_cs);

            // Compute the camera space coordinates of the triangle vertices.
            Vector3d v_cs[3];
            v_cs[0] = camera_transform.transform_point_to_local(shading_point.get_vertex(0));
            v_cs[1] = camera_transform.transform_point_to_local(shading_point.get_vertex(1));
            v_cs[2] = camera_transform.transform_point_to_local(shading_point.get_vertex(2));

            // Loop over the triangle edges.
            for (size_t i = 0; i < 3; ++i)
            {
                // Compute the end points of this edge.
                const size_t j = (i + 1) % 3;
                Vector3d vi_cs = v_cs[i];
                Vector3d vj_cs = v_cs[j];

                // Clip the edge against the view pyramid.
                if (!view_pyramid.clip(vi_cs, vj_cs))
                    continue;

                // Transform the edge to film space.
                const Vector2d vi_fs = camera.project(vi_cs);
                const Vector2d vj_fs = camera.project(vj_cs);

                // Compute the film space distance from the intersection point to the edge.
                const double d = square_distance_point_segment(point_fs, vi_fs, vj_fs);

                if (d < SquareWireThickness)
                {
                    shading_result.set_to_linear_rgba(Color4f(1.0f));
                    break;
                }
            }
        }
        break;

      // Invalid shader.
      default:
        assert(false);
        shading_result.clear();
        break;
    }
}

void DiagnosticSurfaceShader::extract_parameters()
{
    // Retrieve shading mode.
    const string mode_string = m_params.get_required<string>("mode", "coverage");
    const KeyValuePair<const char*, ShadingMode>* mode_pair =
        lookup_kvpair_array(ShadingModeValues, ShadingModeCount, mode_string);
    if (mode_pair)
    {
        impl->m_shading_mode = mode_pair->m_value;
    }
    else
    {
        RENDERER_LOG_ERROR(
            "invalid shading mode \"%s\", using default value \"coverage\"",
            mode_string.c_str());
        impl->m_shading_mode = Coverage;
    }

    // Retrieve ambient occlusion parameters.
    if (impl->m_shading_mode == AmbientOcclusion)
    {
        const ParamArray& ao_params = m_params.child("ambient_occlusion");
        impl->m_ao_max_distance = ao_params.get_optional<double>("max_distance", 1.0);
        impl->m_ao_samples = ao_params.get_optional<size_t>("samples", 16);
    }
}

//
// DiagnosticSurfaceShaderFactory class implementation.
//

const char* DiagnosticSurfaceShaderFactory::get_model() const
{
    return Model;
}

const char* DiagnosticSurfaceShaderFactory::get_human_readable_model() const
{
    return "Diagnostics";
}

DictionaryArray DiagnosticSurfaceShaderFactory::get_widget_definitions() const
{
    Dictionary model_items;

    for (int i = 0; i < DiagnosticSurfaceShader::ShadingModeCount; ++i)
    {
        const char* shading_mode_value = DiagnosticSurfaceShader::ShadingModeNames[i].m_key;
        const char* shading_mode_name = DiagnosticSurfaceShader::ShadingModeNames[i].m_value;
        model_items.insert(shading_mode_name, shading_mode_value);
    }

    DictionaryArray definitions;

    definitions.push_back(
        Dictionary()
            .insert("name", "mode")
            .insert("label", "Mode")
            .insert("widget", "dropdown_list")
            .insert("dropdown_items", model_items)
            .insert("use", "required")
            .insert("default", "coverage")
            .insert("on_change", "rebuild_form"));

    return definitions;
}

auto_release_ptr<SurfaceShader> DiagnosticSurfaceShaderFactory::create(
    const char*         name,
    const ParamArray&   params) const
{
    return
        auto_release_ptr<SurfaceShader>(
            new DiagnosticSurfaceShader(name, params));
}

}   // namespace renderer
<|endoftext|>


<commit_before>
#include <ionEngine.h>

void PrintShaderInfoLog(GLint const Shader)
{
	int InfoLogLength = 0;
	int CharsWritten = 0;

	glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, & InfoLogLength);

	if (InfoLogLength > 0)
	{
		GLchar * InfoLog = new GLchar[InfoLogLength];
		glGetShaderInfoLog(Shader, InfoLogLength, & CharsWritten, InfoLog);
		std::cout << "Shader Info Log:" << std::endl << InfoLog << std::endl;
		delete [] InfoLog;
	}
}

int main()
{
	SingletonPointer<CWindowManager> WindowManager;

	WindowManager->Init();
	CWindow * Window = WindowManager->CreateWindow(vec2i(640, 480), "TestGL", false);

	char const * VertexShaderSource =
		"	#version 150		\n"
		"	in vec2 position;	\n"
		"	void main()			\n"
		"	{					\n"
		"		gl_Position = vec4(position, 0.0, 1.0);	\n"
		"	}					\n";

	char const * FragmentShaderSource =
		"	#version 150			\n"
		"	out vec4 outColor;		\n"
		"	void main()				\n"
		"	{						\n"
		"		outColor = vec4(1.0, 1.0, 1.0, 1.0);	\n"
		"	}						\n";

	GLfloat const Vertices[] = {
		0.0f,  0.5f,
		0.5f, -0.5f,
		-0.5f, -0.5f
	};

	GLuint const Elements[] = {
		0, 1, 2,
		2, 3, 0
	};

	GLuint VAO;
	CheckedGLCall(glGenVertexArrays(1, & VAO));
	CheckedGLCall(glBindVertexArray(VAO));

	GLuint VBO;
	CheckedGLCall(glGenBuffers(1, & VBO));
	CheckedGLCall(glBindBuffer(GL_ARRAY_BUFFER, VBO));
	CheckedGLCall(glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW));

	GLuint EBO;
	CheckedGLCall(glGenBuffers(1, & EBO));
	CheckedGLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO));
	CheckedGLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Elements), Elements, GL_STATIC_DRAW));

	GLint Compiled;
	GLuint VertexShader = CheckedGLCall(glCreateShader(GL_VERTEX_SHADER));
	CheckedGLCall(glShaderSource(VertexShader, 1, & VertexShaderSource, NULL));
	CheckedGLCall(glCompileShader(VertexShader));
	CheckedGLCall(glGetShaderiv(VertexShader, GL_COMPILE_STATUS, & Compiled));
	if (! Compiled)
	{
		std::cerr << "Failed to compile vertex shader!" << std::endl;
		PrintShaderInfoLog(VertexShader);
	}

	GLuint FragmentShader = CheckedGLCall(glCreateShader(GL_FRAGMENT_SHADER));
	CheckedGLCall(glShaderSource(FragmentShader, 1, & FragmentShaderSource, NULL));
	CheckedGLCall(glCompileShader(FragmentShader));
	CheckedGLCall(glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, & Compiled));
	if (! Compiled)
	{
		std::cerr << "Failed to compile fragment shader!" << std::endl;
		PrintShaderInfoLog(FragmentShader);
	}

	GLuint ShaderProgram = CheckedGLCall(glCreateProgram());
	CheckedGLCall(glAttachShader(ShaderProgram, VertexShader));
	CheckedGLCall(glAttachShader(ShaderProgram, FragmentShader));
	CheckedGLCall(glBindFragDataLocation(ShaderProgram, 0, "outColor"));
	CheckedGLCall(glLinkProgram(ShaderProgram));
	CheckedGLCall(glUseProgram(ShaderProgram));

	GLint PositionAttribute = CheckedGLCall(glGetAttribLocation(ShaderProgram, "position"));
	CheckedGLCall(glVertexAttribPointer(PositionAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0));
	CheckedGLCall(glEnableVertexAttribArray(PositionAttribute));

	while (! WindowManager->ShouldClose())
	{
		WindowManager->PollEvents();

		CheckedGLCall(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
		CheckedGLCall(glDrawArrays(GL_TRIANGLES, 0, 3));
		Window->SwapBuffers();
	}

	CheckedGLCall(glDeleteProgram(ShaderProgram));
	CheckedGLCall(glDeleteShader(FragmentShader));
	CheckedGLCall(glDeleteShader(VertexShader));

	CheckedGLCall(glDeleteBuffers(1, & EBO));
	CheckedGLCall(glDeleteBuffers(1, & VBO));
	CheckedGLCall(glDeleteVertexArrays(1, & VAO));

	return 0;
}
<commit_msg>+ Actually using EBO in GL test<commit_after>
#include <ionEngine.h>

void PrintShaderInfoLog(GLint const Shader)
{
	int InfoLogLength = 0;
	int CharsWritten = 0;

	glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, & InfoLogLength);

	if (InfoLogLength > 0)
	{
		GLchar * InfoLog = new GLchar[InfoLogLength];
		glGetShaderInfoLog(Shader, InfoLogLength, & CharsWritten, InfoLog);
		std::cout << "Shader Info Log:" << std::endl << InfoLog << std::endl;
		delete [] InfoLog;
	}
}

int main()
{
	SingletonPointer<CWindowManager> WindowManager;

	WindowManager->Init();
	CWindow * Window = WindowManager->CreateWindow(vec2i(640, 480), "TestGL", false);

	char const * VertexShaderSource =
		"	#version 150		\n"
		"	in vec2 position;	\n"
		"	void main()			\n"
		"	{					\n"
		"		gl_Position = vec4(position, 0.0, 1.0);	\n"
		"	}					\n";

	char const * FragmentShaderSource =
		"	#version 150			\n"
		"	out vec4 outColor;		\n"
		"	void main()				\n"
		"	{						\n"
		"		outColor = vec4(1.0, 1.0, 1.0, 1.0);	\n"
		"	}						\n";

	GLfloat const Vertices[] = {
		0.0f,  0.5f,
		0.5f, -0.5f,
		-0.5f, -0.5f
	};

	GLuint const Elements[] = {
		0, 1, 2
	};

	GLuint VAO;
	CheckedGLCall(glGenVertexArrays(1, & VAO));
	CheckedGLCall(glBindVertexArray(VAO));

	GLuint VBO;
	CheckedGLCall(glGenBuffers(1, & VBO));
	CheckedGLCall(glBindBuffer(GL_ARRAY_BUFFER, VBO));
	CheckedGLCall(glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW));
	CheckedGLCall(glBindBuffer(GL_ARRAY_BUFFER, 0));

	GLuint EBO;
	CheckedGLCall(glGenBuffers(1, & EBO));
	CheckedGLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO));
	CheckedGLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Elements), Elements, GL_STATIC_DRAW));

	GLint Compiled;
	GLuint VertexShader = CheckedGLCall(glCreateShader(GL_VERTEX_SHADER));
	CheckedGLCall(glShaderSource(VertexShader, 1, & VertexShaderSource, NULL));
	CheckedGLCall(glCompileShader(VertexShader));
	CheckedGLCall(glGetShaderiv(VertexShader, GL_COMPILE_STATUS, & Compiled));
	if (! Compiled)
	{
		std::cerr << "Failed to compile vertex shader!" << std::endl;
		PrintShaderInfoLog(VertexShader);
	}

	GLuint FragmentShader = CheckedGLCall(glCreateShader(GL_FRAGMENT_SHADER));
	CheckedGLCall(glShaderSource(FragmentShader, 1, & FragmentShaderSource, NULL));
	CheckedGLCall(glCompileShader(FragmentShader));
	CheckedGLCall(glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, & Compiled));
	if (! Compiled)
	{
		std::cerr << "Failed to compile fragment shader!" << std::endl;
		PrintShaderInfoLog(FragmentShader);
	}

	GLuint ShaderProgram = CheckedGLCall(glCreateProgram());
	CheckedGLCall(glAttachShader(ShaderProgram, VertexShader));
	CheckedGLCall(glAttachShader(ShaderProgram, FragmentShader));
	CheckedGLCall(glBindFragDataLocation(ShaderProgram, 0, "outColor"));
	CheckedGLCall(glLinkProgram(ShaderProgram));
	CheckedGLCall(glUseProgram(ShaderProgram));

	GLint PositionAttribute = CheckedGLCall(glGetAttribLocation(ShaderProgram, "position"));
	CheckedGLCall(glEnableVertexAttribArray(PositionAttribute));

	CheckedGLCall(glBindBuffer(GL_ARRAY_BUFFER, VBO));
	CheckedGLCall(glVertexAttribPointer(PositionAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0));
	CheckedGLCall(glBindBuffer(GL_ARRAY_BUFFER, 0));

	while (! WindowManager->ShouldClose())
	{
		WindowManager->PollEvents();

		CheckedGLCall(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
		CheckedGLCall(glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0));
		Window->SwapBuffers();
	}

	CheckedGLCall(glDeleteProgram(ShaderProgram));
	CheckedGLCall(glDeleteShader(FragmentShader));
	CheckedGLCall(glDeleteShader(VertexShader));

	CheckedGLCall(glDeleteBuffers(1, & EBO));
	CheckedGLCall(glDeleteBuffers(1, & VBO));
	CheckedGLCall(glDeleteVertexArrays(1, & VAO));

	return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "xwalk/application/browser/linux/installed_applications_root.h"

#include <algorithm>
#include <string>
#include "base/bind.h"
#include "base/files/file_path.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "xwalk/application/browser/application_store.h"
#include "xwalk/dbus/property_exporter.h"
#include "xwalk/dbus/xwalk_service_name.h"
#include "xwalk/application/browser/linux/installed_application_object.h"

namespace {

// D-Bus Interface implemented by the root object of installed applications.
//
// Methods:
//
//   Install(string path) -> ObjectPath
//     Will install application at "path", that should be an absolute path to
//     the package file. If installation is successful, returns the ObjectPath
//     of the InstalledApplication object that represents it.
const char kInstalledApplicationsRootDBusInterface[] =
    "org.crosswalkproject.InstalledApplicationsRoot";

const char kInstalledApplicationsRootDBusError[] =
    "org.crosswalkproject.InstalledApplicationsRoot.Error";

const dbus::ObjectPath kInstalledApplicationsRootPath("/installed");

}  // namespace

namespace xwalk {
namespace application {

// TODO(cmarcelo): Extract the ObjectManager bits into an ObjectManager<T> class
// and make InstalledApplicationsRoot a subclass of
// ObjectManager<InstalledApplicationObject>. The interface for T expects a
// PropertyExporter to be available.
InstalledApplicationsRoot::InstalledApplicationsRoot(
    scoped_refptr<dbus::Bus> bus, ApplicationService* service)
    : weak_factory_(this),
      application_service_(service),
      bus_(bus) {
  application_service_->AddObserver(this);

  root_object_ = bus_->GetExportedObject(kInstalledApplicationsRootPath);
  root_object_->ExportMethod(
      "org.freedesktop.DBus.ObjectManager", "GetManagedObjects",
      base::Bind(&InstalledApplicationsRoot::OnGetManagedObjects,
                 weak_factory_.GetWeakPtr()),
      base::Bind(&InstalledApplicationsRoot::OnExported,
                 weak_factory_.GetWeakPtr()));

  root_object_->ExportMethod(
      kInstalledApplicationsRootDBusInterface, "Install",
      base::Bind(&InstalledApplicationsRoot::OnInstall,
                 weak_factory_.GetWeakPtr()),
      base::Bind(&InstalledApplicationsRoot::OnExported,
                 weak_factory_.GetWeakPtr()));

  CreateInitialObjects();
}

InstalledApplicationsRoot::~InstalledApplicationsRoot() {
  application_service_->RemoveObserver(this);
}

void InstalledApplicationsRoot::OnApplicationInstalled(
    const std::string& app_id) {
  scoped_refptr<const Application> app(
      application_service_->GetApplicationByID(app_id));
  installed_apps_.push_back(CreateObject(app));

  // TODO(cmarcelo): Emit InterfacesAdded() signal.
}

namespace {

struct MatchAppID {
 public:
  explicit MatchAppID(const std::string& app_id) : app_id_(app_id) {}
  bool operator()(const InstalledApplicationObject* object) {
    return app_id_ == object->app_id();
  }
  const std::string app_id_;
};

}  // namespace

void InstalledApplicationsRoot::OnApplicationUninstalled(
    const std::string& app_id) {
  ScopedVector<InstalledApplicationObject>::iterator it = std::find_if(
      installed_apps_.begin(), installed_apps_.end(), MatchAppID(app_id));
  if (it == installed_apps_.end()) {
    LOG(WARNING) << "Notified about uninstallation of unknown app_id.";
    return;
  }

  // We need to explicitly unregister the exported object.
  bus_->UnregisterExportedObject((*it)->path());

  // Since this is a ScopedVector, erasing will actually destroy the value.
  installed_apps_.erase(it);

  // TODO(cmarcelo): Emit InterfacesRemoved() signal.
}

void InstalledApplicationsRoot::CreateInitialObjects() {
  ApplicationStore::ApplicationMap* apps =
      application_service_->GetInstalledApplications();
  ApplicationStore::ApplicationMap::iterator it;
  for (it = apps->begin(); it != apps->end(); ++it)
    installed_apps_.push_back(CreateObject(it->second));
}

InstalledApplicationObject* InstalledApplicationsRoot::CreateObject(
    scoped_refptr<const Application> app) {
  InstalledApplicationObject* object =
      new InstalledApplicationObject(bus_, kInstalledApplicationsRootPath, app);
  // See comment in InstalledApplicationsRoot::OnUninstall().
  object->ExportUninstallMethod(
      base::Bind(&InstalledApplicationsRoot::OnUninstall,
                 weak_factory_.GetWeakPtr(),
                 base::Unretained(object)),
      base::Bind(&InstalledApplicationsRoot::OnExported,
                 weak_factory_.GetWeakPtr()));
  return object;
}

void InstalledApplicationsRoot::OnGetManagedObjects(
    dbus::MethodCall* method_call,
    dbus::ExportedObject::ResponseSender response_sender) {
  scoped_ptr<dbus::Response> response =
      dbus::Response::FromMethodCall(method_call);
  dbus::MessageWriter writer(response.get());

  dbus::MessageWriter dict_writer(NULL);
  writer.OpenArray("{oa{sa{sv}}}", &dict_writer);

  ScopedVector<InstalledApplicationObject>::const_iterator it;
  for (it = installed_apps_.begin(); it != installed_apps_.end(); ++it) {
    InstalledApplicationObject* installed_app = *it;
    dbus::MessageWriter entry_writer(NULL);
    dict_writer.OpenDictEntry(&entry_writer);
    entry_writer.AppendObjectPath(installed_app->path());
    installed_app->AppendAllPropertiesToWriter(&entry_writer);
    dict_writer.CloseContainer(&entry_writer);
  }

  writer.CloseContainer(&dict_writer);
  response_sender.Run(response.Pass());
}

namespace {

scoped_ptr<dbus::Response> CreateError(dbus::MethodCall* method_call,
                                       const std::string& message) {
    scoped_ptr<dbus::ErrorResponse> error_response =
        dbus::ErrorResponse::FromMethodCall(
            method_call, kInstalledApplicationsRootDBusError, message);
    return error_response.PassAs<dbus::Response>();
}

}  // namespace

void InstalledApplicationsRoot::OnInstall(
    dbus::MethodCall* method_call,
    dbus::ExportedObject::ResponseSender response_sender) {
  dbus::MessageReader reader(method_call);
  std::string file_path_str;
  if (!reader.PopString(&file_path_str)) {
    scoped_ptr<dbus::Response> response =
        CreateError(method_call, "Error parsing message.");
    response_sender.Run(response.Pass());
    return;
  }

  const base::FilePath file_path(file_path_str);
  if (!file_path.IsAbsolute()) {
    scoped_ptr<dbus::Response> response =
        CreateError(method_call, "Path to install must be absolute.");
    response_sender.Run(response.Pass());
    return;
  }

  std::string app_id;
  if (!application_service_->Install(file_path, &app_id)) {
    scoped_ptr<dbus::Response> response =
        CreateError(method_call,
                    "Error installing application with path: " + file_path_str);
    response_sender.Run(response.Pass());
    return;
  }

  ScopedVector<InstalledApplicationObject>::iterator it = std::find_if(
      installed_apps_.begin(), installed_apps_.end(), MatchAppID(app_id));
  CHECK(it != installed_apps_.end());

  scoped_ptr<dbus::Response> response =
      dbus::Response::FromMethodCall(method_call);
  dbus::MessageWriter writer(response.get());
  writer.AppendObjectPath((*it)->path());
  response_sender.Run(response.Pass());
}

// InstalledApplicationsRoot implements the callback exposed in the child
// objects interface, we bind the actual child to the first parameter. There are
// two reasons to do this: we save the need of creating WeakPtrFactories for all
// individual objects, and we ensure that is safe to destroy the object when
// handling the callback -- which is done by our OnApplicationUninstalled
// implementation.
void InstalledApplicationsRoot::OnUninstall(
    InstalledApplicationObject* installed_app_object,
    dbus::MethodCall* method_call,
    dbus::ExportedObject::ResponseSender response_sender) {
  if (!application_service_->Uninstall(installed_app_object->app_id())) {
    scoped_ptr<dbus::ErrorResponse> error_response =
        dbus::ErrorResponse::FromMethodCall(
            method_call, kInstalledApplicationDBusError,
            "Error trying to uninstall application with id "
            + installed_app_object->app_id());
    response_sender.Run(error_response.PassAs<dbus::Response>());
    return;
  }

  scoped_ptr<dbus::Response> response =
      dbus::Response::FromMethodCall(method_call);
  response_sender.Run(response.Pass());
}

void InstalledApplicationsRoot::OnExported(
    const std::string& interface_name,
    const std::string& method_name,
    bool success) {
  if (!success) {
    LOG(WARNING) << "Error exporting method '" << interface_name
                 << "." << method_name << "' in '"
                 << kInstalledApplicationsRootPath.value() << "'.";
  }
}

}  // namespace application
}  // namespace xwalk
<commit_msg>[Applications][D-Bus] Emit InterfacesAdded signal when app is installed<commit_after>// Copyright (c) 2013 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "xwalk/application/browser/linux/installed_applications_root.h"

#include <algorithm>
#include <string>
#include "base/bind.h"
#include "base/files/file_path.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "xwalk/application/browser/application_store.h"
#include "xwalk/dbus/property_exporter.h"
#include "xwalk/dbus/xwalk_service_name.h"
#include "xwalk/application/browser/linux/installed_application_object.h"

namespace {

// D-Bus Interface implemented by the root object of installed applications.
//
// Methods:
//
//   Install(string path) -> ObjectPath
//     Will install application at "path", that should be an absolute path to
//     the package file. If installation is successful, returns the ObjectPath
//     of the InstalledApplication object that represents it.
const char kInstalledApplicationsRootDBusInterface[] =
    "org.crosswalkproject.InstalledApplicationsRoot";

const char kInstalledApplicationsRootDBusError[] =
    "org.crosswalkproject.InstalledApplicationsRoot.Error";

const char kDBusObjectManagerInterface[] = "org.freedesktop.DBus.ObjectManager";

const dbus::ObjectPath kInstalledApplicationsRootPath("/installed");

}  // namespace

namespace xwalk {
namespace application {

// TODO(cmarcelo): Extract the ObjectManager bits into an ObjectManager<T> class
// and make InstalledApplicationsRoot a subclass of
// ObjectManager<InstalledApplicationObject>. The interface for T expects a
// PropertyExporter to be available.
InstalledApplicationsRoot::InstalledApplicationsRoot(
    scoped_refptr<dbus::Bus> bus, ApplicationService* service)
    : weak_factory_(this),
      application_service_(service),
      bus_(bus) {
  application_service_->AddObserver(this);

  root_object_ = bus_->GetExportedObject(kInstalledApplicationsRootPath);
  root_object_->ExportMethod(
      kDBusObjectManagerInterface, "GetManagedObjects",
      base::Bind(&InstalledApplicationsRoot::OnGetManagedObjects,
                 weak_factory_.GetWeakPtr()),
      base::Bind(&InstalledApplicationsRoot::OnExported,
                 weak_factory_.GetWeakPtr()));

  root_object_->ExportMethod(
      kInstalledApplicationsRootDBusInterface, "Install",
      base::Bind(&InstalledApplicationsRoot::OnInstall,
                 weak_factory_.GetWeakPtr()),
      base::Bind(&InstalledApplicationsRoot::OnExported,
                 weak_factory_.GetWeakPtr()));

  CreateInitialObjects();
}

InstalledApplicationsRoot::~InstalledApplicationsRoot() {
  application_service_->RemoveObserver(this);
}

void InstalledApplicationsRoot::OnApplicationInstalled(
    const std::string& app_id) {
  scoped_refptr<const Application> app(
      application_service_->GetApplicationByID(app_id));
  InstalledApplicationObject* object = CreateObject(app);

  installed_apps_.push_back(object);

  dbus::Signal interfaces_added(kDBusObjectManagerInterface, "InterfacesAdded");
  dbus::MessageWriter writer(&interfaces_added);
  writer.AppendObjectPath(object->path());

  object->AppendAllPropertiesToWriter(&writer);

  root_object_->SendSignal(&interfaces_added);
}

namespace {

struct MatchAppID {
 public:
  explicit MatchAppID(const std::string& app_id) : app_id_(app_id) {}
  bool operator()(const InstalledApplicationObject* object) {
    return app_id_ == object->app_id();
  }
  const std::string app_id_;
};

}  // namespace

void InstalledApplicationsRoot::OnApplicationUninstalled(
    const std::string& app_id) {
  ScopedVector<InstalledApplicationObject>::iterator it = std::find_if(
      installed_apps_.begin(), installed_apps_.end(), MatchAppID(app_id));
  if (it == installed_apps_.end()) {
    LOG(WARNING) << "Notified about uninstallation of unknown app_id.";
    return;
  }

  // We need to explicitly unregister the exported object.
  bus_->UnregisterExportedObject((*it)->path());

  // Since this is a ScopedVector, erasing will actually destroy the value.
  installed_apps_.erase(it);

  // TODO(cmarcelo): Emit InterfacesRemoved() signal.
}

void InstalledApplicationsRoot::CreateInitialObjects() {
  ApplicationStore::ApplicationMap* apps =
      application_service_->GetInstalledApplications();
  ApplicationStore::ApplicationMap::iterator it;
  for (it = apps->begin(); it != apps->end(); ++it)
    installed_apps_.push_back(CreateObject(it->second));
}

InstalledApplicationObject* InstalledApplicationsRoot::CreateObject(
    scoped_refptr<const Application> app) {
  InstalledApplicationObject* object =
      new InstalledApplicationObject(bus_, kInstalledApplicationsRootPath, app);
  // See comment in InstalledApplicationsRoot::OnUninstall().
  object->ExportUninstallMethod(
      base::Bind(&InstalledApplicationsRoot::OnUninstall,
                 weak_factory_.GetWeakPtr(),
                 base::Unretained(object)),
      base::Bind(&InstalledApplicationsRoot::OnExported,
                 weak_factory_.GetWeakPtr()));
  return object;
}

void InstalledApplicationsRoot::OnGetManagedObjects(
    dbus::MethodCall* method_call,
    dbus::ExportedObject::ResponseSender response_sender) {
  scoped_ptr<dbus::Response> response =
      dbus::Response::FromMethodCall(method_call);
  dbus::MessageWriter writer(response.get());

  dbus::MessageWriter dict_writer(NULL);
  writer.OpenArray("{oa{sa{sv}}}", &dict_writer);

  ScopedVector<InstalledApplicationObject>::const_iterator it;
  for (it = installed_apps_.begin(); it != installed_apps_.end(); ++it) {
    InstalledApplicationObject* installed_app = *it;
    dbus::MessageWriter entry_writer(NULL);
    dict_writer.OpenDictEntry(&entry_writer);
    entry_writer.AppendObjectPath(installed_app->path());
    installed_app->AppendAllPropertiesToWriter(&entry_writer);
    dict_writer.CloseContainer(&entry_writer);
  }

  writer.CloseContainer(&dict_writer);
  response_sender.Run(response.Pass());
}

namespace {

scoped_ptr<dbus::Response> CreateError(dbus::MethodCall* method_call,
                                       const std::string& message) {
    scoped_ptr<dbus::ErrorResponse> error_response =
        dbus::ErrorResponse::FromMethodCall(
            method_call, kInstalledApplicationsRootDBusError, message);
    return error_response.PassAs<dbus::Response>();
}

}  // namespace

void InstalledApplicationsRoot::OnInstall(
    dbus::MethodCall* method_call,
    dbus::ExportedObject::ResponseSender response_sender) {
  dbus::MessageReader reader(method_call);
  std::string file_path_str;
  if (!reader.PopString(&file_path_str)) {
    scoped_ptr<dbus::Response> response =
        CreateError(method_call, "Error parsing message.");
    response_sender.Run(response.Pass());
    return;
  }

  const base::FilePath file_path(file_path_str);
  if (!file_path.IsAbsolute()) {
    scoped_ptr<dbus::Response> response =
        CreateError(method_call, "Path to install must be absolute.");
    response_sender.Run(response.Pass());
    return;
  }

  std::string app_id;
  if (!application_service_->Install(file_path, &app_id)) {
    scoped_ptr<dbus::Response> response =
        CreateError(method_call,
                    "Error installing application with path: " + file_path_str);
    response_sender.Run(response.Pass());
    return;
  }

  ScopedVector<InstalledApplicationObject>::iterator it = std::find_if(
      installed_apps_.begin(), installed_apps_.end(), MatchAppID(app_id));
  CHECK(it != installed_apps_.end());

  scoped_ptr<dbus::Response> response =
      dbus::Response::FromMethodCall(method_call);
  dbus::MessageWriter writer(response.get());
  writer.AppendObjectPath((*it)->path());
  response_sender.Run(response.Pass());
}

// InstalledApplicationsRoot implements the callback exposed in the child
// objects interface, we bind the actual child to the first parameter. There are
// two reasons to do this: we save the need of creating WeakPtrFactories for all
// individual objects, and we ensure that is safe to destroy the object when
// handling the callback -- which is done by our OnApplicationUninstalled
// implementation.
void InstalledApplicationsRoot::OnUninstall(
    InstalledApplicationObject* installed_app_object,
    dbus::MethodCall* method_call,
    dbus::ExportedObject::ResponseSender response_sender) {
  if (!application_service_->Uninstall(installed_app_object->app_id())) {
    scoped_ptr<dbus::ErrorResponse> error_response =
        dbus::ErrorResponse::FromMethodCall(
            method_call, kInstalledApplicationDBusError,
            "Error trying to uninstall application with id "
            + installed_app_object->app_id());
    response_sender.Run(error_response.PassAs<dbus::Response>());
    return;
  }

  scoped_ptr<dbus::Response> response =
      dbus::Response::FromMethodCall(method_call);
  response_sender.Run(response.Pass());
}

void InstalledApplicationsRoot::OnExported(
    const std::string& interface_name,
    const std::string& method_name,
    bool success) {
  if (!success) {
    LOG(WARNING) << "Error exporting method '" << interface_name
                 << "." << method_name << "' in '"
                 << kInstalledApplicationsRootPath.value() << "'.";
  }
}

}  // namespace application
}  // namespace xwalk
<|endoftext|>


<commit_before>/**
 * @file hrectbound_impl.hpp
 *
 * Implementation of hyper-rectangle bound policy class.
 * Template parameter Power is the metric to use; use 2 for Euclidean (L2).
 *
 * @experimental
 */
#ifndef __MLPACK_CORE_TREE_HRECTBOUND_IMPL_HPP
#define __MLPACK_CORE_TREE_HRECTBOUND_IMPL_HPP

#include <math.h>

// In case it has not been included yet.
#include "hrectbound.hpp"

namespace mlpack {
namespace bound {

/**
 * Empty constructor.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::HRectBound() :
    dim(0),
    bounds(NULL),
    minWidth(0)
{ /* Nothing to do. */ }

/**
 * Initializes to specified dimensionality with each dimension the empty
 * set.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::HRectBound(const size_t dimension) :
    dim(dimension),
    bounds(new math::Range[dim]),
    minWidth(0)
{ /* Nothing to do. */ }

/***
 * Copy constructor necessary to prevent memory leaks.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::HRectBound(const HRectBound& other) :
    dim(other.Dim()),
    bounds(new math::Range[dim]),
    minWidth(other.MinWidth())
{
  // Copy other bounds over.
  for (size_t i = 0; i < dim; i++)
    bounds[i] = other[i];
}

/***
 * Same as the copy constructor.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>& HRectBound<Power, TakeRoot>::operator=(
    const HRectBound& other)
{
  if (dim != other.Dim())
  {
    // Reallocation is necessary.
    if (bounds)
      delete[] bounds;

    dim = other.Dim();
    bounds = new math::Range[dim];
  }

  // Now copy each of the bound values.
  for (size_t i = 0; i < dim; i++)
    bounds[i] = other[i];

  minWidth = other.MinWidth();

  return *this;
}

/**
 * Destructor: clean up memory.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::~HRectBound()
{
  if (bounds)
    delete[] bounds;
}

/**
 * Resets all dimensions to the empty set.
 */
template<int Power, bool TakeRoot>
void HRectBound<Power, TakeRoot>::Clear()
{
  for (size_t i = 0; i < dim; i++)
    bounds[i] = math::Range();
  minWidth = 0;
}

/***
 * Calculates the centroid of the range, placing it into the given vector.
 *
 * @param centroid Vector which the centroid will be written to.
 */
template<int Power, bool TakeRoot>
void HRectBound<Power, TakeRoot>::Centroid(arma::vec& centroid) const
{
  // Set size correctly if necessary.
  if (!(centroid.n_elem == dim))
    centroid.set_size(dim);

  for (size_t i = 0; i < dim; i++)
    centroid(i) = bounds[i].Mid();
}

/**
 * Calculates minimum bound-to-point squared distance.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
double HRectBound<Power, TakeRoot>::MinDistance(
    const VecType& point,
    typename boost::enable_if<IsVector<VecType> >* /* junk */) const
{
  Log::Assert(point.n_elem == dim);

  double sum = 0;

  double lower, higher;
  for (size_t d = 0; d < dim; d++)
  {
    lower = bounds[d].Lo() - point[d];
    higher = point[d] - bounds[d].Hi();

    // Since only one of 'lower' or 'higher' is negative, if we add each's
    // absolute value to itself and then sum those two, our result is the
    // nonnegative half of the equation times two; then we raise to power Power.
    sum += pow((lower + fabs(lower)) + (higher + fabs(higher)), (double) Power);
  }

  // Now take the Power'th root (but make sure our result is squared if it needs
  // to be); then cancel out the constant of 2 (which may have been squared now)
  // that was introduced earlier.  The compiler should optimize out the if
  // statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power) / 2.0;
  else
    return sum / pow(2.0, Power);
}

/**
 * Calculates minimum bound-to-bound squared distance.
 */
template<int Power, bool TakeRoot>
double HRectBound<Power, TakeRoot>::MinDistance(const HRectBound& other) const
{
  Log::Assert(dim == other.dim);

  double sum = 0;
  const math::Range* mbound = bounds;
  const math::Range* obound = other.bounds;

  double lower, higher;
  for (size_t d = 0; d < dim; d++)
  {
    lower = obound->Lo() - mbound->Hi();
    higher = mbound->Lo() - obound->Hi();
    // We invoke the following:
    //   x + fabs(x) = max(x * 2, 0)
    //   (x * 2)^2 / 4 = x^2
    sum += pow((lower + fabs(lower)) + (higher + fabs(higher)), (double) Power);

    // Move bound pointers.
    mbound++;
    obound++;
  }

  // The compiler should optimize out this if statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power) / 2.0;
  else
    return sum / pow(2.0, Power);
}

/**
 * Calculates maximum bound-to-point squared distance.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
double HRectBound<Power, TakeRoot>::MaxDistance(
    const VecType& point,
    typename boost::enable_if<IsVector<VecType> >* /* junk */) const
{
  double sum = 0;

  Log::Assert(point.n_elem == dim);

  for (size_t d = 0; d < dim; d++)
  {
    double v = std::max(fabs(point[d] - bounds[d].Lo()),
        fabs(bounds[d].Hi() - point[d]));
    sum += pow(v, (double) Power);
  }

  // The compiler should optimize out this if statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power);
  else
    return sum;
}

/**
 * Computes maximum distance.
 */
template<int Power, bool TakeRoot>
double HRectBound<Power, TakeRoot>::MaxDistance(const HRectBound& other) const
{
  double sum = 0;

  Log::Assert(dim == other.dim);

  double v;
  for (size_t d = 0; d < dim; d++)
  {
    v = std::max(fabs(other.bounds[d].Hi() - bounds[d].Lo()),
        fabs(bounds[d].Hi() - other.bounds[d].Lo()));
    sum += pow(v, (double) Power); // v is non-negative.
  }

  // The compiler should optimize out this if statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power);
  else
    return sum;
}

/**
 * Calculates minimum and maximum bound-to-bound squared distance.
 */
template<int Power, bool TakeRoot>
math::Range HRectBound<Power, TakeRoot>::RangeDistance(const HRectBound& other)
    const
{
  double loSum = 0;
  double hiSum = 0;

  Log::Assert(dim == other.dim);

  double v1, v2, vLo, vHi;
  for (size_t d = 0; d < dim; d++)
  {
    v1 = other.bounds[d].Lo() - bounds[d].Hi();
    v2 = bounds[d].Lo() - other.bounds[d].Hi();
    // One of v1 or v2 is negative.
    if (v1 >= v2)
    {
      vHi = -v2; // Make it nonnegative.
      vLo = (v1 > 0) ? v1 : 0; // Force to be 0 if negative.
    }
    else
    {
      vHi = -v1; // Make it nonnegative.
      vLo = (v2 > 0) ? v2 : 0; // Force to be 0 if negative.
    }

    loSum += pow(vLo, (double) Power);
    hiSum += pow(vHi, (double) Power);
  }

  if (TakeRoot)
    return math::Range(pow(loSum, 1.0 / (double) Power),
                       pow(hiSum, 1.0 / (double) Power));
  else
    return math::Range(loSum, hiSum);
}

/**
 * Calculates minimum and maximum bound-to-point squared distance.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
math::Range HRectBound<Power, TakeRoot>::RangeDistance(
    const VecType& point,
    typename boost::enable_if<IsVector<VecType> >* /* junk */) const
{
  double loSum = 0;
  double hiSum = 0;

  Log::Assert(point.n_elem == dim);

  double v1, v2, vLo, vHi;
  for (size_t d = 0; d < dim; d++)
  {
    v1 = bounds[d].Lo() - point[d]; // Negative if point[d] > lo.
    v2 = point[d] - bounds[d].Hi(); // Negative if point[d] < hi.
    // One of v1 or v2 (or both) is negative.
    if (v1 >= 0) // point[d] <= bounds_[d].Lo().
    {
      vHi = -v2; // v2 will be larger but must be negated.
      vLo = v1;
    }
    else // point[d] is between lo and hi, or greater than hi.
    {
      if (v2 >= 0)
      {
        vHi = -v1; // v1 will be larger, but must be negated.
        vLo = v2;
      }
      else
      {
        vHi = -std::min(v1, v2); // Both are negative, but we need the larger.
        vLo = 0;
      }
    }

    loSum += pow(vLo, (double) Power);
    hiSum += pow(vHi, (double) Power);
  }

  if (TakeRoot)
    return math::Range(pow(loSum, 1.0 / (double) Power),
                       pow(hiSum, 1.0 / (double) Power));
  else
    return math::Range(loSum, hiSum);
}

/**
 * Expands this region to include a new point.
 */
template<int Power, bool TakeRoot>
template<typename MatType>
HRectBound<Power, TakeRoot>& HRectBound<Power, TakeRoot>::operator|=(
    const MatType& data)
{
  Log::Assert(data.n_rows == dim);

  arma::vec mins(min(data, 1));
  arma::vec maxs(max(data, 1));

  minWidth = DBL_MAX;
  for (size_t i = 0; i < dim; i++)
  {
    bounds[i] |= math::Range(mins[i], maxs[i]);
    const double width = bounds[i].Hi() - bounds[i].Lo();
    if (width < minWidth)
      minWidth = width;
  }

  return *this;
}

/**
 * Expands this region to encompass another bound.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>& HRectBound<Power, TakeRoot>::operator|=(
    const HRectBound& other)
{
  assert(other.dim == dim);

  minWidth = DBL_MAX;
  for (size_t i = 0; i < dim; i++)
  {
    bounds[i] |= other.bounds[i];
    const double width = bounds[i].Hi() - bounds[i].Lo();
    if (width < minWidth)
      minWidth = width;
  }

  return *this;
}

/**
 * Determines if a point is within this bound.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
bool HRectBound<Power, TakeRoot>::Contains(const VecType& point) const
{
  for (size_t i = 0; i < point.n_elem; i++)
  {
    if (!bounds[i].Contains(point(i)))
      return false;
  }

  return true;
}

/**
 * Returns the diameter of the hyperrectangle (that is, the longest diagonal).
 */
template<int Power, bool TakeRoot>
double HRectBound<Power, TakeRoot>::Diameter() const
{
  double d = 0;
  for (size_t i = 0; i < dim; ++i)
    d += std::pow(bounds[i].Hi() - bounds[i].Lo(), (double) Power);

  if (TakeRoot)
    return std::pow(d, 1.0 / (double) Power);
  else
    return d;
}

/**
 * Returns a string representation of this object.
 */
template<int Power, bool TakeRoot>
std::string HRectBound<Power, TakeRoot>::ToString() const
{
  std::ostringstream convert;
  convert << "HRectBound [" << this << "]" << std::endl;
  convert << "  Power: " << Power << std::endl;
  convert << "  TakeRoot: " << (TakeRoot ? "true" : "false") << std::endl;
  convert << "  Dimensionality: " << dim << std::endl;
  convert << "  Bounds: " << std::endl;
  for (size_t i = 0; i < dim; ++i)
    convert << util::Indent(bounds[i].ToString()) << std::endl;
  convert << "  Minimum width: " << minWidth << std::endl;

  return convert.str();
}

}; // namespace bound
}; // namespace mlpack

#endif // __MLPACK_CORE_TREE_HRECTBOUND_IMPL_HPP
<commit_msg>Use slightly safer Width().<commit_after>/**
 * @file hrectbound_impl.hpp
 *
 * Implementation of hyper-rectangle bound policy class.
 * Template parameter Power is the metric to use; use 2 for Euclidean (L2).
 *
 * @experimental
 */
#ifndef __MLPACK_CORE_TREE_HRECTBOUND_IMPL_HPP
#define __MLPACK_CORE_TREE_HRECTBOUND_IMPL_HPP

#include <math.h>

// In case it has not been included yet.
#include "hrectbound.hpp"

namespace mlpack {
namespace bound {

/**
 * Empty constructor.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::HRectBound() :
    dim(0),
    bounds(NULL),
    minWidth(0)
{ /* Nothing to do. */ }

/**
 * Initializes to specified dimensionality with each dimension the empty
 * set.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::HRectBound(const size_t dimension) :
    dim(dimension),
    bounds(new math::Range[dim]),
    minWidth(0)
{ /* Nothing to do. */ }

/***
 * Copy constructor necessary to prevent memory leaks.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::HRectBound(const HRectBound& other) :
    dim(other.Dim()),
    bounds(new math::Range[dim]),
    minWidth(other.MinWidth())
{
  // Copy other bounds over.
  for (size_t i = 0; i < dim; i++)
    bounds[i] = other[i];
}

/***
 * Same as the copy constructor.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>& HRectBound<Power, TakeRoot>::operator=(
    const HRectBound& other)
{
  if (dim != other.Dim())
  {
    // Reallocation is necessary.
    if (bounds)
      delete[] bounds;

    dim = other.Dim();
    bounds = new math::Range[dim];
  }

  // Now copy each of the bound values.
  for (size_t i = 0; i < dim; i++)
    bounds[i] = other[i];

  minWidth = other.MinWidth();

  return *this;
}

/**
 * Destructor: clean up memory.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>::~HRectBound()
{
  if (bounds)
    delete[] bounds;
}

/**
 * Resets all dimensions to the empty set.
 */
template<int Power, bool TakeRoot>
void HRectBound<Power, TakeRoot>::Clear()
{
  for (size_t i = 0; i < dim; i++)
    bounds[i] = math::Range();
  minWidth = 0;
}

/***
 * Calculates the centroid of the range, placing it into the given vector.
 *
 * @param centroid Vector which the centroid will be written to.
 */
template<int Power, bool TakeRoot>
void HRectBound<Power, TakeRoot>::Centroid(arma::vec& centroid) const
{
  // Set size correctly if necessary.
  if (!(centroid.n_elem == dim))
    centroid.set_size(dim);

  for (size_t i = 0; i < dim; i++)
    centroid(i) = bounds[i].Mid();
}

/**
 * Calculates minimum bound-to-point squared distance.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
double HRectBound<Power, TakeRoot>::MinDistance(
    const VecType& point,
    typename boost::enable_if<IsVector<VecType> >* /* junk */) const
{
  Log::Assert(point.n_elem == dim);

  double sum = 0;

  double lower, higher;
  for (size_t d = 0; d < dim; d++)
  {
    lower = bounds[d].Lo() - point[d];
    higher = point[d] - bounds[d].Hi();

    // Since only one of 'lower' or 'higher' is negative, if we add each's
    // absolute value to itself and then sum those two, our result is the
    // nonnegative half of the equation times two; then we raise to power Power.
    sum += pow((lower + fabs(lower)) + (higher + fabs(higher)), (double) Power);
  }

  // Now take the Power'th root (but make sure our result is squared if it needs
  // to be); then cancel out the constant of 2 (which may have been squared now)
  // that was introduced earlier.  The compiler should optimize out the if
  // statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power) / 2.0;
  else
    return sum / pow(2.0, Power);
}

/**
 * Calculates minimum bound-to-bound squared distance.
 */
template<int Power, bool TakeRoot>
double HRectBound<Power, TakeRoot>::MinDistance(const HRectBound& other) const
{
  Log::Assert(dim == other.dim);

  double sum = 0;
  const math::Range* mbound = bounds;
  const math::Range* obound = other.bounds;

  double lower, higher;
  for (size_t d = 0; d < dim; d++)
  {
    lower = obound->Lo() - mbound->Hi();
    higher = mbound->Lo() - obound->Hi();
    // We invoke the following:
    //   x + fabs(x) = max(x * 2, 0)
    //   (x * 2)^2 / 4 = x^2
    sum += pow((lower + fabs(lower)) + (higher + fabs(higher)), (double) Power);

    // Move bound pointers.
    mbound++;
    obound++;
  }

  // The compiler should optimize out this if statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power) / 2.0;
  else
    return sum / pow(2.0, Power);
}

/**
 * Calculates maximum bound-to-point squared distance.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
double HRectBound<Power, TakeRoot>::MaxDistance(
    const VecType& point,
    typename boost::enable_if<IsVector<VecType> >* /* junk */) const
{
  double sum = 0;

  Log::Assert(point.n_elem == dim);

  for (size_t d = 0; d < dim; d++)
  {
    double v = std::max(fabs(point[d] - bounds[d].Lo()),
        fabs(bounds[d].Hi() - point[d]));
    sum += pow(v, (double) Power);
  }

  // The compiler should optimize out this if statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power);
  else
    return sum;
}

/**
 * Computes maximum distance.
 */
template<int Power, bool TakeRoot>
double HRectBound<Power, TakeRoot>::MaxDistance(const HRectBound& other) const
{
  double sum = 0;

  Log::Assert(dim == other.dim);

  double v;
  for (size_t d = 0; d < dim; d++)
  {
    v = std::max(fabs(other.bounds[d].Hi() - bounds[d].Lo()),
        fabs(bounds[d].Hi() - other.bounds[d].Lo()));
    sum += pow(v, (double) Power); // v is non-negative.
  }

  // The compiler should optimize out this if statement entirely.
  if (TakeRoot)
    return pow(sum, 1.0 / (double) Power);
  else
    return sum;
}

/**
 * Calculates minimum and maximum bound-to-bound squared distance.
 */
template<int Power, bool TakeRoot>
math::Range HRectBound<Power, TakeRoot>::RangeDistance(const HRectBound& other)
    const
{
  double loSum = 0;
  double hiSum = 0;

  Log::Assert(dim == other.dim);

  double v1, v2, vLo, vHi;
  for (size_t d = 0; d < dim; d++)
  {
    v1 = other.bounds[d].Lo() - bounds[d].Hi();
    v2 = bounds[d].Lo() - other.bounds[d].Hi();
    // One of v1 or v2 is negative.
    if (v1 >= v2)
    {
      vHi = -v2; // Make it nonnegative.
      vLo = (v1 > 0) ? v1 : 0; // Force to be 0 if negative.
    }
    else
    {
      vHi = -v1; // Make it nonnegative.
      vLo = (v2 > 0) ? v2 : 0; // Force to be 0 if negative.
    }

    loSum += pow(vLo, (double) Power);
    hiSum += pow(vHi, (double) Power);
  }

  if (TakeRoot)
    return math::Range(pow(loSum, 1.0 / (double) Power),
                       pow(hiSum, 1.0 / (double) Power));
  else
    return math::Range(loSum, hiSum);
}

/**
 * Calculates minimum and maximum bound-to-point squared distance.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
math::Range HRectBound<Power, TakeRoot>::RangeDistance(
    const VecType& point,
    typename boost::enable_if<IsVector<VecType> >* /* junk */) const
{
  double loSum = 0;
  double hiSum = 0;

  Log::Assert(point.n_elem == dim);

  double v1, v2, vLo, vHi;
  for (size_t d = 0; d < dim; d++)
  {
    v1 = bounds[d].Lo() - point[d]; // Negative if point[d] > lo.
    v2 = point[d] - bounds[d].Hi(); // Negative if point[d] < hi.
    // One of v1 or v2 (or both) is negative.
    if (v1 >= 0) // point[d] <= bounds_[d].Lo().
    {
      vHi = -v2; // v2 will be larger but must be negated.
      vLo = v1;
    }
    else // point[d] is between lo and hi, or greater than hi.
    {
      if (v2 >= 0)
      {
        vHi = -v1; // v1 will be larger, but must be negated.
        vLo = v2;
      }
      else
      {
        vHi = -std::min(v1, v2); // Both are negative, but we need the larger.
        vLo = 0;
      }
    }

    loSum += pow(vLo, (double) Power);
    hiSum += pow(vHi, (double) Power);
  }

  if (TakeRoot)
    return math::Range(pow(loSum, 1.0 / (double) Power),
                       pow(hiSum, 1.0 / (double) Power));
  else
    return math::Range(loSum, hiSum);
}

/**
 * Expands this region to include a new point.
 */
template<int Power, bool TakeRoot>
template<typename MatType>
HRectBound<Power, TakeRoot>& HRectBound<Power, TakeRoot>::operator|=(
    const MatType& data)
{
  Log::Assert(data.n_rows == dim);

  arma::vec mins(min(data, 1));
  arma::vec maxs(max(data, 1));

  minWidth = DBL_MAX;
  for (size_t i = 0; i < dim; i++)
  {
    bounds[i] |= math::Range(mins[i], maxs[i]);
    const double width = bounds[i].Width();
    if (width < minWidth)
      minWidth = width;
  }

  return *this;
}

/**
 * Expands this region to encompass another bound.
 */
template<int Power, bool TakeRoot>
HRectBound<Power, TakeRoot>& HRectBound<Power, TakeRoot>::operator|=(
    const HRectBound& other)
{
  assert(other.dim == dim);

  minWidth = DBL_MAX;
  for (size_t i = 0; i < dim; i++)
  {
    bounds[i] |= other.bounds[i];
    const double width = bounds[i].Width();
    if (width < minWidth)
      minWidth = width;
  }

  return *this;
}

/**
 * Determines if a point is within this bound.
 */
template<int Power, bool TakeRoot>
template<typename VecType>
bool HRectBound<Power, TakeRoot>::Contains(const VecType& point) const
{
  for (size_t i = 0; i < point.n_elem; i++)
  {
    if (!bounds[i].Contains(point(i)))
      return false;
  }

  return true;
}

/**
 * Returns the diameter of the hyperrectangle (that is, the longest diagonal).
 */
template<int Power, bool TakeRoot>
double HRectBound<Power, TakeRoot>::Diameter() const
{
  double d = 0;
  for (size_t i = 0; i < dim; ++i)
    d += std::pow(bounds[i].Hi() - bounds[i].Lo(), (double) Power);

  if (TakeRoot)
    return std::pow(d, 1.0 / (double) Power);
  else
    return d;
}

/**
 * Returns a string representation of this object.
 */
template<int Power, bool TakeRoot>
std::string HRectBound<Power, TakeRoot>::ToString() const
{
  std::ostringstream convert;
  convert << "HRectBound [" << this << "]" << std::endl;
  convert << "  Power: " << Power << std::endl;
  convert << "  TakeRoot: " << (TakeRoot ? "true" : "false") << std::endl;
  convert << "  Dimensionality: " << dim << std::endl;
  convert << "  Bounds: " << std::endl;
  for (size_t i = 0; i < dim; ++i)
    convert << util::Indent(bounds[i].ToString()) << std::endl;
  convert << "  Minimum width: " << minWidth << std::endl;

  return convert.str();
}

}; // namespace bound
}; // namespace mlpack

#endif // __MLPACK_CORE_TREE_HRECTBOUND_IMPL_HPP
<|endoftext|>


<commit_before>#include "stdafx.h"

MeshRenderer meshRenderer;

static int MAX_INSTANCES = 10;

static const int BONE_SSBO_SIZE = sizeof(Mat) * 1000;
static const int PER_INSTANCE_UBO_SIZE = sizeof(RenderCommand) * MAX_INSTANCES;

enum SSBOBindingPoints {
	SBP_BONES = 5,
};

enum UBOBindingPoints {
	UBP_PER_INSTANCE_DATAS = 2,
};

enum SamplerBindingPoints {
	SBP_DIFFUSE = 4,
};

RenderMesh::RenderMesh()
{
	vbo = 0;
	ibo = 0;
}

RenderMesh::~RenderMesh()
{
	Destroy();
}

void RenderMesh::Destroy()
{
	afSafeDeleteBuffer(ibo);
	afSafeDeleteBuffer(vbo);
	afSafeDeleteVAO(vao);
}

void RenderMesh::Init(const Block& block)
{
	if (block.vertices.empty() || block.indices.empty()) {
		return;
	}

	int numVertices = block.vertices.size();
	int numIndices = block.indices.size();
	const AFIndex* indices = &block.indices[0];

	Destroy();

	int sizeVertex = numVertices * sizeof(MeshVertex);

	static const InputElement elements[] = {
		CInputElement(0, "POSITION", SF_R32G32B32_FLOAT, 0),
		CInputElement(0, "NORMAL", SF_R32G32B32_FLOAT, 12),
		CInputElement(0, "vColor", SF_R8G8B8A8_UNORM, 24),
		CInputElement(0, "vTexcoord", SF_R32G32_FLOAT, 28),
		CInputElement(0, "vBlendWeights", SF_R32G32B32_FLOAT, 36),
		CInputElement(0, "vBlendIndices", SF_R8G8B8A8_UINT, 48),
	};

	vbo = afCreateVertexBuffer(sizeVertex, &block.vertices[0]);
	ibo = afCreateIndexBuffer(indices, numIndices);

	materialMaps = block.materialMaps;
	VBOID verts[] = { vbo };
	GLsizei strides[] = { sizeof(MeshVertex) };
	int shaderId = meshRenderer.GetShaderId();
	vao = afCreateVAO(shaderId, elements, dimof(elements), block.indices.size(), verts, strides, ibo);
}

void RenderMesh::Draw(const RenderCommand& c, int instanceCount) const
{
	int shaderId = meshRenderer.GetShaderId();

	afEnableBackFaceCulling(true);
	glActiveTexture(GL_TEXTURE0 + SBP_DIFFUSE);
	glBindVertexArray(vao);
	for (auto it : materialMaps) {
		const Material* mat = matMan.Get(it.materialId);
		assert(mat);
		glBindTexture(GL_TEXTURE_2D, mat->tmid);

		GLuint count = it.faces * 3;
		GLuint start = it.faceStartIndex * 3;
		DrawElementsIndirectCommand cmd = { count, (GLuint)instanceCount, start, 0, 0 };
		glDrawElementsInstanced/*BaseVertex*/(GL_TRIANGLES,
			cmd.count,
			AFIndexTypeToDevice,
			(void*)cmd.firstIndex,
			cmd.instanceCount/*, cmd.baseVertex*/);
	}

	glBindTexture(GL_TEXTURE_2D, 0);
	glBindVertexArray(0);
}

MeshRenderer::MeshRenderer()
{
	renderMeshes.push_back(nullptr);	// render mesh ID must not be 0
}

MeshRenderer::~MeshRenderer()
{
	assert(renderMeshes.empty());
}

void MeshRenderer::Create()
{
	ssboForBoneMatrices = afCreateSSBO(BONE_SSBO_SIZE);
	uboForPerInstanceData = afCreateUBO(PER_INSTANCE_UBO_SIZE);

	shaderId = shaderMan.Create("skin.400");
	assert(shaderId);

	shaderMan.Apply(shaderId);

	afBindBufferToBindingPoint(ssboForBoneMatrices, SBP_BONES);
	afBindBufferToBindingPoint(uboForPerInstanceData, UBP_PER_INSTANCE_DATAS);
}

void MeshRenderer::Destroy()
{
	for (int i = 0; i < (int)renderMeshes.size(); i++) {
		RenderMesh* m = renderMeshes[i];
		delete m;
	}
	renderMeshes.clear();
	afSafeDeleteBuffer(ssboForBoneMatrices);
	afSafeDeleteBuffer(uboForPerInstanceData);
}

MRID MeshRenderer::CreateRenderMesh(const Block& block)
{
	RenderMesh* r = new RenderMesh;
	r->Init(block);
	renderMeshes.push_back(r);
	return renderMeshes.size() - 1;
}

void MeshRenderer::SafeDestroyRenderMesh(MRID& id)
{
	if (id >= renderMeshes.size()) {
		return;
	}
	if (id != INVALID_MRID) {
		SAFE_DELETE(renderMeshes[id]);
		id = INVALID_MRID;
	}
}

RenderMesh* MeshRenderer::GetMeshByMRID(MRID id)
{
	if (id >= renderMeshes.size()) {
		return nullptr;
	}
	RenderMesh* r = renderMeshes[id];
	if (!r) {
		return nullptr;
	}
	return r;
}

void MeshRenderer::DrawRenderMesh(MRID id, const Mat& worldMat, const Mat BoneMatrices[], int nBones, const Block& block)
{
	assert(GetMeshByMRID(id));
	assert(!block.materialMaps.empty());

	if (!renderCommands.empty() && id != renderCommands[0].meshId) {
		Flush();
	}
	if (renderCommands.size() == MAX_INSTANCES) {
		Flush();
	}

	RenderCommand c;
	c.matWorld = worldMat;
	c.meshId = id;
	c.materialId = block.materialMaps[0].materialId;
	c.boneStartIndex = renderBoneMatrices.size();
	c.nBones = nBones;

	renderCommands.push_back(c);

	renderBoneMatrices.resize(c.boneStartIndex + nBones);
	memcpy(&renderBoneMatrices[0] + c.boneStartIndex, &BoneMatrices[0], sizeof(Mat) * nBones);
}

void MeshRenderer::Flush()
{
	if (renderCommands.empty()) {
		return;
	}

	afWriteBuffer(ssboForBoneMatrices, &renderBoneMatrices[0], sizeof(Mat) * renderBoneMatrices.size());
	afWriteBuffer(uboForPerInstanceData, &renderCommands[0], sizeof(renderCommands[0]) * renderCommands.size());

	shaderMan.Apply(shaderId);

	Mat matV, matP;
	matrixMan.Get(MatrixMan::VIEW, matV);
	matrixMan.Get(MatrixMan::PROJ, matP);
	glUniformMatrix4fv(glGetUniformLocation(shaderId, "matV"), 1, GL_FALSE, &matV.m[0][0]);
	glUniformMatrix4fv(glGetUniformLocation(shaderId, "matP"), 1, GL_FALSE, &matP.m[0][0]);

	RenderCommand c = renderCommands[0];
	RenderMesh* r = GetMeshByMRID(c.meshId);
	assert(r);
	r->Draw(c, renderCommands.size());
	renderBoneMatrices.clear();
	renderCommands.clear();
}
<commit_msg>'firstIndex' must be in byte offset, not in number of indices!<commit_after>#include "stdafx.h"

MeshRenderer meshRenderer;

static int MAX_INSTANCES = 10;

static const int BONE_SSBO_SIZE = sizeof(Mat) * 1000;
static const int PER_INSTANCE_UBO_SIZE = sizeof(RenderCommand) * MAX_INSTANCES;

enum SSBOBindingPoints {
	SBP_BONES = 5,
};

enum UBOBindingPoints {
	UBP_PER_INSTANCE_DATAS = 2,
};

enum SamplerBindingPoints {
	SBP_DIFFUSE = 4,
};

RenderMesh::RenderMesh()
{
	vbo = 0;
	ibo = 0;
}

RenderMesh::~RenderMesh()
{
	Destroy();
}

void RenderMesh::Destroy()
{
	afSafeDeleteBuffer(ibo);
	afSafeDeleteBuffer(vbo);
	afSafeDeleteVAO(vao);
}

void RenderMesh::Init(const Block& block)
{
	if (block.vertices.empty() || block.indices.empty()) {
		return;
	}

	int numVertices = block.vertices.size();
	int numIndices = block.indices.size();
	const AFIndex* indices = &block.indices[0];

	Destroy();

	int sizeVertex = numVertices * sizeof(MeshVertex);

	static const InputElement elements[] = {
		CInputElement(0, "POSITION", SF_R32G32B32_FLOAT, 0),
		CInputElement(0, "NORMAL", SF_R32G32B32_FLOAT, 12),
		CInputElement(0, "vColor", SF_R8G8B8A8_UNORM, 24),
		CInputElement(0, "vTexcoord", SF_R32G32_FLOAT, 28),
		CInputElement(0, "vBlendWeights", SF_R32G32B32_FLOAT, 36),
		CInputElement(0, "vBlendIndices", SF_R8G8B8A8_UINT, 48),
	};

	vbo = afCreateVertexBuffer(sizeVertex, &block.vertices[0]);
	ibo = afCreateIndexBuffer(indices, numIndices);

	materialMaps = block.materialMaps;
	VBOID verts[] = { vbo };
	GLsizei strides[] = { sizeof(MeshVertex) };
	int shaderId = meshRenderer.GetShaderId();
	vao = afCreateVAO(shaderId, elements, dimof(elements), block.indices.size(), verts, strides, ibo);
}

void RenderMesh::Draw(const RenderCommand& c, int instanceCount) const
{
	int shaderId = meshRenderer.GetShaderId();

	afEnableBackFaceCulling(true);
	glActiveTexture(GL_TEXTURE0 + SBP_DIFFUSE);
	glBindVertexArray(vao);
	for (auto it : materialMaps) {
		const Material* mat = matMan.Get(it.materialId);
		assert(mat);
		glBindTexture(GL_TEXTURE_2D, mat->tmid);

		GLuint count = it.faces * 3;
		GLuint start = it.faceStartIndex * 3 * sizeof(AFIndex);
		DrawElementsIndirectCommand cmd = { count, (GLuint)instanceCount, start, 0, 0 };
		glDrawElementsInstanced/*BaseVertex*/(GL_TRIANGLES,
			cmd.count,
			AFIndexTypeToDevice,
			(void*)cmd.firstIndex,
			cmd.instanceCount/*, cmd.baseVertex*/);
	}

	glBindTexture(GL_TEXTURE_2D, 0);
	glBindVertexArray(0);
}

MeshRenderer::MeshRenderer()
{
	renderMeshes.push_back(nullptr);	// render mesh ID must not be 0
}

MeshRenderer::~MeshRenderer()
{
	assert(renderMeshes.empty());
}

void MeshRenderer::Create()
{
	ssboForBoneMatrices = afCreateSSBO(BONE_SSBO_SIZE);
	uboForPerInstanceData = afCreateUBO(PER_INSTANCE_UBO_SIZE);

	shaderId = shaderMan.Create("skin.400");
	assert(shaderId);

	shaderMan.Apply(shaderId);

	afBindBufferToBindingPoint(ssboForBoneMatrices, SBP_BONES);
	afBindBufferToBindingPoint(uboForPerInstanceData, UBP_PER_INSTANCE_DATAS);
}

void MeshRenderer::Destroy()
{
	for (int i = 0; i < (int)renderMeshes.size(); i++) {
		RenderMesh* m = renderMeshes[i];
		delete m;
	}
	renderMeshes.clear();
	afSafeDeleteBuffer(ssboForBoneMatrices);
	afSafeDeleteBuffer(uboForPerInstanceData);
}

MRID MeshRenderer::CreateRenderMesh(const Block& block)
{
	RenderMesh* r = new RenderMesh;
	r->Init(block);
	renderMeshes.push_back(r);
	return renderMeshes.size() - 1;
}

void MeshRenderer::SafeDestroyRenderMesh(MRID& id)
{
	if (id >= renderMeshes.size()) {
		return;
	}
	if (id != INVALID_MRID) {
		SAFE_DELETE(renderMeshes[id]);
		id = INVALID_MRID;
	}
}

RenderMesh* MeshRenderer::GetMeshByMRID(MRID id)
{
	if (id >= renderMeshes.size()) {
		return nullptr;
	}
	RenderMesh* r = renderMeshes[id];
	if (!r) {
		return nullptr;
	}
	return r;
}

void MeshRenderer::DrawRenderMesh(MRID id, const Mat& worldMat, const Mat BoneMatrices[], int nBones, const Block& block)
{
	assert(GetMeshByMRID(id));
	assert(!block.materialMaps.empty());

	if (!renderCommands.empty() && id != renderCommands[0].meshId) {
		Flush();
	}
	if (renderCommands.size() == MAX_INSTANCES) {
		Flush();
	}

	RenderCommand c;
	c.matWorld = worldMat;
	c.meshId = id;
	c.materialId = block.materialMaps[0].materialId;
	c.boneStartIndex = renderBoneMatrices.size();
	c.nBones = nBones;

	renderCommands.push_back(c);

	renderBoneMatrices.resize(c.boneStartIndex + nBones);
	memcpy(&renderBoneMatrices[0] + c.boneStartIndex, &BoneMatrices[0], sizeof(Mat) * nBones);
}

void MeshRenderer::Flush()
{
	if (renderCommands.empty()) {
		return;
	}

	afWriteBuffer(ssboForBoneMatrices, &renderBoneMatrices[0], sizeof(Mat) * renderBoneMatrices.size());
	afWriteBuffer(uboForPerInstanceData, &renderCommands[0], sizeof(renderCommands[0]) * renderCommands.size());

	shaderMan.Apply(shaderId);

	Mat matV, matP;
	matrixMan.Get(MatrixMan::VIEW, matV);
	matrixMan.Get(MatrixMan::PROJ, matP);
	glUniformMatrix4fv(glGetUniformLocation(shaderId, "matV"), 1, GL_FALSE, &matV.m[0][0]);
	glUniformMatrix4fv(glGetUniformLocation(shaderId, "matP"), 1, GL_FALSE, &matP.m[0][0]);

	RenderCommand c = renderCommands[0];
	RenderMesh* r = GetMeshByMRID(c.meshId);
	assert(r);
	r->Draw(c, renderCommands.size());
	renderBoneMatrices.clear();
	renderCommands.clear();
}
<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <string.h>
#include <math.h>
#include "field.h"

void Field::Open(int row, int column) {
    ww[row][column] += 10;
}
void Field::AllOpen() {
    for (int r = 1; r < height+1; r++) {
        for (int c = 1; c < width+1; c++) {
            Open(r, c);
        }
    }
}

void Field::RecursiveOpen(int row, int column) {
    Open(row, column);
    if (row == 0 || row == height+1 || column == 0 || column == width+1) {
        return;
    }
    if (0 <= ww[row-1][column-1] && ww[row-1][column-1] <= 8) {
        if (ww[row-1][column-1] == 0) {
            RecursiveOpen(row-1, column-1);
        } else {
            Open(row-1, column-1);
        }
    }
    if (0 <= ww[row-1][column] && ww[row-1][column] <= 8) {
        if (ww[row-1][column] == 0) {
            RecursiveOpen(row-1, column);
        } else {
            Open(row-1, column);
        }
    }
    if (0 <= ww[row-1][column+1] && ww[row-1][column+1] <= 8) {
        if (ww[row-1][column+1] == 0) {
            RecursiveOpen(row-1, column+1);
        } else {
            Open(row-1, column+1);
        }
    }
    if (0 <= ww[row][column-1] && ww[row][column-1] <= 8) {
        if (ww[row][column-1] == 0) {
            RecursiveOpen(row, column-1);
        } else {
            Open(row, column-1);
        }
    }
    if (0 <= ww[row][column+1] && ww[row][column+1] <= 8) {
        if (ww[row][column+1] == 0) {
            RecursiveOpen(row, column+1);
        } else {
            Open(row, column+1);
        }
    }
    if (0 <= ww[row+1][column-1] && ww[row+1][column-1] <= 8) {
        if (ww[row+1][column-1] == 0) {
            RecursiveOpen(row+1, column-1);
        } else {
            Open(row+1, column-1);
        }
    }
    if (0 <= ww[row+1][column] && ww[row+1][column] <= 8) {
        if (ww[row+1][column] == 0) {
            RecursiveOpen(row+1, column);
        } else {
            Open(row+1, column);
        }
    }
    if (0 <= ww[row+1][column+1] && ww[row+1][column+1] <= 8) {
        if (ww[row+1][column+1] == 0) {
            RecursiveOpen(row+1, column+1);
        } else {
            Open(row+1, column+1);
        }
    }
}

int Field::Choose(int row, int column) {
    row += 1;
    column += 1;
    if (ww[row][column] == 0) {
        RecursiveOpen(row, column);
    } else if (0 < ww[row][column] && ww[row][column] <= 8) {
        Open(row, column);
    } else if (ww[row][column] == -1){
        AllOpen();
        return 1;
    }
    return -1;
}

std::string Field::FieldString() {
    std::stringstream out, tmp;
    std::string header;
    while (header.length() < (int)log10((double)height)+2) {header += " ";}
    for (int c = 0; c < width; c++) {
        tmp << " " << c+1;
        while (tmp.str().length() < 4) {tmp << " ";}
        header += tmp.str();
        tmp.str("");
    }
    out << header + "\n";
    for (int r = 1; r < height+1; r++) {
        tmp << r;
        while (tmp.str().length() < (int)log10((double)height)+2) {tmp << " ";}
        out << tmp.str();
        tmp.str("");
        for (int c = 1; c < width+1; c++) {
            if (-1 <= ww[r][c] && ww[r][c] <= 8) {
                out << CLOSED;
            } else if (ww[r][c] == 10) {
                out << OPENED;
            } else if (10 < ww[r][c]) {
                out << "_" << ww[r][c]-10 << "_";
            } else if (ww[r][c] == 9) {
                out << MINE;
            }
            out << " ";
        }
        if (r < height) {
            out << "\n";
        }
    }

    return out.str() + ">> ";
}

int main() {
    Field *f1;
    f1 = new Field(10,10,10);
    for (int i = 1; i < 11; i++) {
        for (int j = 1; j < 11; j++) {
            std::cout << f1->ww[i][j] << " ";
        }
        std::cout << std::endl;
    }
    std::cout << f1->FieldString() << std::endl;
    std::cout << "aiueo\n" << std::endl;
    return 0;
}
<commit_msg>added loop<commit_after>#include <iostream>
#include <sstream>
#include <string.h>
#include <math.h>
#include "field.h"

void Field::Open(int row, int column) {
    ww[row][column] += 10;
}
void Field::AllOpen() {
    for (int r = 1; r < height+1; r++) {
        for (int c = 1; c < width+1; c++) {
            Open(r, c);
        }
    }
}

void Field::RecursiveOpen(int row, int column) {
    Open(row, column);
    if (row == 0 || row == height+1 || column == 0 || column == width+1) {
        return;
    }
    if (0 <= ww[row-1][column-1] && ww[row-1][column-1] <= 8) {
        if (ww[row-1][column-1] == 0) {
            RecursiveOpen(row-1, column-1);
        } else {
            Open(row-1, column-1);
        }
    }
    if (0 <= ww[row-1][column] && ww[row-1][column] <= 8) {
        if (ww[row-1][column] == 0) {
            RecursiveOpen(row-1, column);
        } else {
            Open(row-1, column);
        }
    }
    if (0 <= ww[row-1][column+1] && ww[row-1][column+1] <= 8) {
        if (ww[row-1][column+1] == 0) {
            RecursiveOpen(row-1, column+1);
        } else {
            Open(row-1, column+1);
        }
    }
    if (0 <= ww[row][column-1] && ww[row][column-1] <= 8) {
        if (ww[row][column-1] == 0) {
            RecursiveOpen(row, column-1);
        } else {
            Open(row, column-1);
        }
    }
    if (0 <= ww[row][column+1] && ww[row][column+1] <= 8) {
        if (ww[row][column+1] == 0) {
            RecursiveOpen(row, column+1);
        } else {
            Open(row, column+1);
        }
    }
    if (0 <= ww[row+1][column-1] && ww[row+1][column-1] <= 8) {
        if (ww[row+1][column-1] == 0) {
            RecursiveOpen(row+1, column-1);
        } else {
            Open(row+1, column-1);
        }
    }
    if (0 <= ww[row+1][column] && ww[row+1][column] <= 8) {
        if (ww[row+1][column] == 0) {
            RecursiveOpen(row+1, column);
        } else {
            Open(row+1, column);
        }
    }
    if (0 <= ww[row+1][column+1] && ww[row+1][column+1] <= 8) {
        if (ww[row+1][column+1] == 0) {
            RecursiveOpen(row+1, column+1);
        } else {
            Open(row+1, column+1);
        }
    }
}

int Field::Choose(int row, int column) {
    row += 1;
    column += 1;
    if (ww[row][column] == 0) {
        RecursiveOpen(row, column);
    } else if (0 < ww[row][column] && ww[row][column] <= 8) {
        Open(row, column);
    } else if (ww[row][column] == -1){
        AllOpen();
        return 1;
    }
    return -1;
}

std::string Field::FieldString() {
    std::stringstream out, tmp;
    std::string header;
    while (header.length() < (int)log10((double)height)+2) {header += " ";}
    for (int c = 0; c < width; c++) {
        tmp << " " << c+1;
        while (tmp.str().length() < 4) {tmp << " ";}
        header += tmp.str();
        tmp.str("");
    }
    out << header + "\n";
    for (int r = 1; r < height+1; r++) {
        tmp << r;
        while (tmp.str().length() < (int)log10((double)height)+2) {tmp << " ";}
        out << tmp.str();
        tmp.str("");
        for (int c = 1; c < width+1; c++) {
            if (-1 <= ww[r][c] && ww[r][c] <= 8) {
                out << CLOSED;
            } else if (ww[r][c] == 10) {
                out << OPENED;
            } else if (10 < ww[r][c]) {
                out << "_" << ww[r][c]-10 << "_";
            } else if (ww[r][c] == 9) {
                out << MINE;
            }
            out << " ";
        }
        if (r < height) {
            out << "\n";
        }
    }

    return out.str() + ">> ";
}

void InputLoop(Field* f) {
    std::string input, header;
    while (1) {
        std::cout << header << "\n" << f->FieldString() << std::endl;
        std::cin >> input; // need split
        }
}

int main() {
    Field *f1;
    f1 = new Field(10,10,10);
    InputLoop(f1);
    return 0;
}
<|endoftext|>