<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2017 Couchbase, Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#include "collections/manifest.h"
#include "tests/module_tests/collections/test_manifest.h"

#include <gtest/gtest.h>

#include <limits>

TEST(ManifestTest, validation) {
    std::vector<std::string> invalidManifests = {
            "", // empty
            "not json", // definitely not json
            R"({"uid"})", // illegal json

            R"({"uid":"0"
                "collections" : 0})", // illegal collections type

            // valid uid, no collections
            R"({"uid" : "0"})",

            // valid uid, invalid collections type
            R"({"uid" : "0",
                "collections":[0]})",

            // valid uid valid name, no collection uid
            R"({"uid" : "0",
                "collections":[{"name":"beer"}]})",

            // valid uid, valid collection uid, no collection name
            R"({"uid":"0",
                "collections":[{"uid":"1"}]})",

            // valid name, invalid collection uid (wrong type)
            R"({"uid":"0",
                "collections":[{"name":"beer", "uid":1}]})",

            // valid name, invalid collection uid (not hex)
            R"({"uid":"0",
                "collections":[{"name":"beer", "uid":"turkey"}]})",

            // invalid name (wrong type), valid uid
            R"({"uid" : "0",
                "collections":[{"name":1, "uid":"1"}]})",

            // illegal $ prefixed  name
            R"({"uid" : "0",
             "collections":[{"name":"$beer", "uid":"1"},
                            {"name":"brewery","uid":"2"}]})",

            // illegal _ prefixed  name
            R"({"uid" : "0",
               "collections":[{"name":"_beer", "uid":"1"},
                              {"name":"brewery","uid":"2"}]})",

            // duplicate collections
            R"({"uid" : "0",
                "collections":[{"name":"beer", "uid":"1"},
                               {"name":"beer", "uid":"2"}]})",

            // Invalid manifest UIDs
            // Missing UID
            R"({"collections":[{"name":"beer", "uid":"1"}]})",

            // UID wrong type
            R"({"uid" : 0,
                "collections":[{"name":"beer", "uid":"1"}]})",

            // UID cannot be converted to a value
            R"({"uid" : "thisiswrong",
                "collections":[{"name":"beer", "uid":"1"}]})",

            // UID cannot be converted to a value
            R"({"uid" : "12345678901234567890112111",
                "collections":[{"name":"beer", "uid":"1"}]})",

            // UID cannot be 0x prefixed
            R"({"uid" : "0x101",
                "collections":[{"name":"beer", "uid":"1"}]})",

            // collection cid cannot be 1
            R"({"uid" : "101",
                "collections":[{"name":"beer", "uid":"1"}]})",

            // collection cid too long
            R"({"uid" : "101",
                "collections":[{"name":"beer", "uid":"1234567890"}]})"};

    std::vector<std::string> validManifests = {
            R"({"uid" : "0", "collections":[]})",

            R"({"uid" : "0",
                "collections":[{"name":"$default","uid":"0"},
                               {"name":"beer", "uid":"3"},
                               {"name":"brewery","uid":"2"}]})",

            // beer & brewery have same UID, valid
            R"({"uid" : "0",
                "collections":[{"name":"$default","uid":"0"},
                               {"name":"beer", "uid":"2"},
                               {"name":"brewery","uid":"3"}]})",

            R"({"uid" : "0",
                "collections":[{"name":"beer", "uid":"3"},
                               {"name":"brewery","uid":"2"}]})",

            // Extra keys ignored at the moment
            R"({"extra":"key",
                 "uid" : "0",
                "collections":[{"name":"beer", "uid":"af"},
                               {"name":"brewery","uid":"2"}]})",

            // lower-case uid is fine
            R"({"uid" : "abcd1", "collections":[]})",
            // upper-case uid is fine
            R"({"uid" : "ABCD1", "collections":[]})",
            // mix-case uid is fine
            R"({"uid" : "AbCd1", "collections":[]})"};

    for (auto& manifest : invalidManifests) {
        try {
            Collections::Manifest m(manifest);
            EXPECT_TRUE(false)
                    << "No exception thrown for invalid manifest:" << manifest
                    << std::endl;
        } catch (std::exception&) {
        }
    }

    for (auto& manifest : validManifests) {
        try {
            Collections::Manifest m(manifest);
        } catch (std::exception& e) {
            EXPECT_TRUE(false)
                    << "Exception thrown for valid manifest:" << manifest
                    << std::endl
                    << " what:" << e.what();
        }
    }
}

TEST(ManifestTest, getUid) {
    std::vector<std::pair<Collections::uid_t, std::string>> validManifests = {
            {0,
             R"({"uid" : "0",
                "collections":[{"name":"beer", "uid":"3"},
                               {"name":"brewery","uid":"2"}]})"},
            {0xabcd,
             R"({"uid" : "ABCD",
                "collections":[{"name":"beer", "uid":"3"},
                               {"name":"brewery","uid":"2"}]})"},
            {0xabcd,
             R"({"uid" : "abcd",
                "collections":[{"name":"beer", "uid":"3"},
                               {"name":"brewery","uid":"2"}]})"},
            {0xabcd,
             R"({"uid" : "aBcD",
                "collections":[{"name":"beer", "uid":"3"},
                               {"name":"brewery","uid":"2"}]})"}};

    for (auto& manifest : validManifests) {
        Collections::Manifest m(manifest.second);
        EXPECT_EQ(manifest.first, m.getUid());
    }
}

TEST(ManifestTest, findCollection) {
    std::string manifest =
            R"({"uid" : "0",
                "collections":[{"name":"beer", "uid":"3"},
                               {"name":"brewery","uid":"2"},
                               {"name":"$default","uid":"0"}]})";
    std::vector<CollectionID> collectionT = {0, 3, 2};
    std::vector<CollectionID> collectionF = {5, 6, 7};

    Collections::Manifest m(manifest);

    for (auto& collection : collectionT) {
        EXPECT_NE(m.end(), m.find(collection));
    }

    for (auto& collection : collectionF) {
        EXPECT_EQ(m.end(), m.find(collection));
    }
}

// validate we can construct from JSON, call toJSON and get back valid JSON
// containing what went in.
TEST(ManifestTest, toJson) {
    std::vector<std::pair<std::string, std::vector<CollectionEntry::Entry>>>
            input = {
                    {"abcd", {}},
                    {"abcd",
                     {{CollectionEntry::defaultC},
                      {CollectionEntry::fruit},
                      {CollectionEntry::vegetable}}},
                    {"abcd",
                     {{CollectionEntry::fruit}, {CollectionEntry::vegetable}}},

            };

    for (auto& manifest : input) {
        CollectionsManifest cm(NoDefault{});
        for (auto& collection : manifest.second) {
            cm.add(collection);
        }
        cm.setUid(manifest.first);

        Collections::Manifest m(cm);
        auto json = nlohmann::json::parse(m.toJson());
        ASSERT_NE(json.end(), json.find("uid"));
        EXPECT_TRUE(json["uid"].is_string());
        EXPECT_EQ(manifest.first, json["uid"].get<std::string>());
        if (json.find("collections") != json.end()) {
            for (auto& entry : json["collections"]) {
                EXPECT_NE(
                        manifest.second.end(),
                        std::find_if(
                                manifest.second.begin(),
                                manifest.second.end(),
                                [entry](const CollectionEntry::Entry& e) {
                                    if (e.name == entry["name"]) {
                                        return std::to_string(e.uid) ==
                                               entry["uid"].get<std::string>();
                                    }
                                    return false;
                                }));
            }
        } else {
            EXPECT_EQ(0, manifest.second.size());
        }
    }
}
<commit_msg>MB-30547: Fix build break - skip Manifesttest::toJSON on Clang < 8<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2017 Couchbase, Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#include "collections/manifest.h"
#include "tests/module_tests/collections/test_manifest.h"

#include <gtest/gtest.h>

#include <limits>

TEST(ManifestTest, validation) {
    std::vector<std::string> invalidManifests = {
            "", // empty
            "not json", // definitely not json
            R"({"uid"})", // illegal json

            R"({"uid":"0"
                "collections" : 0})", // illegal collections type

            // valid uid, no collections
            R"({"uid" : "0"})",

            // valid uid, invalid collections type
            R"({"uid" : "0",
                "collections":[0]})",

            // valid uid valid name, no collection uid
            R"({"uid" : "0",
                "collections":[{"name":"beer"}]})",

            // valid uid, valid collection uid, no collection name
            R"({"uid":"0",
                "collections":[{"uid":"1"}]})",

            // valid name, invalid collection uid (wrong type)
            R"({"uid":"0",
                "collections":[{"name":"beer", "uid":1}]})",

            // valid name, invalid collection uid (not hex)
            R"({"uid":"0",
                "collections":[{"name":"beer", "uid":"turkey"}]})",

            // invalid name (wrong type), valid uid
            R"({"uid" : "0",
                "collections":[{"name":1, "uid":"1"}]})",

            // illegal $ prefixed  name
            R"({"uid" : "0",
             "collections":[{"name":"$beer", "uid":"1"},
                            {"name":"brewery","uid":"2"}]})",

            // illegal _ prefixed  name
            R"({"uid" : "0",
               "collections":[{"name":"_beer", "uid":"1"},
                              {"name":"brewery","uid":"2"}]})",

            // duplicate collections
            R"({"uid" : "0",
                "collections":[{"name":"beer", "uid":"1"},
                               {"name":"beer", "uid":"2"}]})",

            // Invalid manifest UIDs
            // Missing UID
            R"({"collections":[{"name":"beer", "uid":"1"}]})",

            // UID wrong type
            R"({"uid" : 0,
                "collections":[{"name":"beer", "uid":"1"}]})",

            // UID cannot be converted to a value
            R"({"uid" : "thisiswrong",
                "collections":[{"name":"beer", "uid":"1"}]})",

            // UID cannot be converted to a value
            R"({"uid" : "12345678901234567890112111",
                "collections":[{"name":"beer", "uid":"1"}]})",

            // UID cannot be 0x prefixed
            R"({"uid" : "0x101",
                "collections":[{"name":"beer", "uid":"1"}]})",

            // collection cid cannot be 1
            R"({"uid" : "101",
                "collections":[{"name":"beer", "uid":"1"}]})",

            // collection cid too long
            R"({"uid" : "101",
                "collections":[{"name":"beer", "uid":"1234567890"}]})"};

    std::vector<std::string> validManifests = {
            R"({"uid" : "0", "collections":[]})",

            R"({"uid" : "0",
                "collections":[{"name":"$default","uid":"0"},
                               {"name":"beer", "uid":"3"},
                               {"name":"brewery","uid":"2"}]})",

            // beer & brewery have same UID, valid
            R"({"uid" : "0",
                "collections":[{"name":"$default","uid":"0"},
                               {"name":"beer", "uid":"2"},
                               {"name":"brewery","uid":"3"}]})",

            R"({"uid" : "0",
                "collections":[{"name":"beer", "uid":"3"},
                               {"name":"brewery","uid":"2"}]})",

            // Extra keys ignored at the moment
            R"({"extra":"key",
                 "uid" : "0",
                "collections":[{"name":"beer", "uid":"af"},
                               {"name":"brewery","uid":"2"}]})",

            // lower-case uid is fine
            R"({"uid" : "abcd1", "collections":[]})",
            // upper-case uid is fine
            R"({"uid" : "ABCD1", "collections":[]})",
            // mix-case uid is fine
            R"({"uid" : "AbCd1", "collections":[]})"};

    for (auto& manifest : invalidManifests) {
        try {
            Collections::Manifest m(manifest);
            EXPECT_TRUE(false)
                    << "No exception thrown for invalid manifest:" << manifest
                    << std::endl;
        } catch (std::exception&) {
        }
    }

    for (auto& manifest : validManifests) {
        try {
            Collections::Manifest m(manifest);
        } catch (std::exception& e) {
            EXPECT_TRUE(false)
                    << "Exception thrown for valid manifest:" << manifest
                    << std::endl
                    << " what:" << e.what();
        }
    }
}

TEST(ManifestTest, getUid) {
    std::vector<std::pair<Collections::uid_t, std::string>> validManifests = {
            {0,
             R"({"uid" : "0",
                "collections":[{"name":"beer", "uid":"3"},
                               {"name":"brewery","uid":"2"}]})"},
            {0xabcd,
             R"({"uid" : "ABCD",
                "collections":[{"name":"beer", "uid":"3"},
                               {"name":"brewery","uid":"2"}]})"},
            {0xabcd,
             R"({"uid" : "abcd",
                "collections":[{"name":"beer", "uid":"3"},
                               {"name":"brewery","uid":"2"}]})"},
            {0xabcd,
             R"({"uid" : "aBcD",
                "collections":[{"name":"beer", "uid":"3"},
                               {"name":"brewery","uid":"2"}]})"}};

    for (auto& manifest : validManifests) {
        Collections::Manifest m(manifest.second);
        EXPECT_EQ(manifest.first, m.getUid());
    }
}

TEST(ManifestTest, findCollection) {
    std::string manifest =
            R"({"uid" : "0",
                "collections":[{"name":"beer", "uid":"3"},
                               {"name":"brewery","uid":"2"},
                               {"name":"$default","uid":"0"}]})";
    std::vector<CollectionID> collectionT = {0, 3, 2};
    std::vector<CollectionID> collectionF = {5, 6, 7};

    Collections::Manifest m(manifest);

    for (auto& collection : collectionT) {
        EXPECT_NE(m.end(), m.find(collection));
    }

    for (auto& collection : collectionF) {
        EXPECT_EQ(m.end(), m.find(collection));
    }
}

// MB-30547: Initialization of `input` below fails on Clang 7 - temporarily
// skip to fix build breakage.
#if !defined(__clang_major__) || __clang_major__ > 7
// validate we can construct from JSON, call toJSON and get back valid JSON
// containing what went in.
TEST(ManifestTest, toJson) {
    std::vector<std::pair<std::string, std::vector<CollectionEntry::Entry>>>
            input = {
                    {"abcd", {}},
                    {"abcd",
                     {{CollectionEntry::defaultC},
                      {CollectionEntry::fruit},
                      {CollectionEntry::vegetable}}},
                    {"abcd",
                     {{CollectionEntry::fruit}, {CollectionEntry::vegetable}}},

            };

    for (auto& manifest : input) {
        CollectionsManifest cm(NoDefault{});
        for (auto& collection : manifest.second) {
            cm.add(collection);
        }
        cm.setUid(manifest.first);

        Collections::Manifest m(cm);
        auto json = nlohmann::json::parse(m.toJson());
        ASSERT_NE(json.end(), json.find("uid"));
        EXPECT_TRUE(json["uid"].is_string());
        EXPECT_EQ(manifest.first, json["uid"].get<std::string>());
        if (json.find("collections") != json.end()) {
            for (auto& entry : json["collections"]) {
                EXPECT_NE(
                        manifest.second.end(),
                        std::find_if(
                                manifest.second.begin(),
                                manifest.second.end(),
                                [entry](const CollectionEntry::Entry& e) {
                                    if (e.name == entry["name"]) {
                                        return std::to_string(e.uid) ==
                                               entry["uid"].get<std::string>();
                                    }
                                    return false;
                                }));
            }
        } else {
            EXPECT_EQ(0, manifest.second.size());
        }
    }
}
#endif // !defined(__clang_major__) || __clang_major__ > 7
<|endoftext|>


<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-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014-2017 Francois Beaune, The appleseedhq Organization
//
// 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 "adaptivepixelrenderer.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/aov/aovsettings.h"
#include "renderer/kernel/aov/imagestack.h"
#include "renderer/kernel/aov/tilestack.h"
#include "renderer/kernel/rendering/final/variationtracker.h"
#include "renderer/kernel/rendering/isamplerenderer.h"
#include "renderer/kernel/rendering/pixelcontext.h"
#include "renderer/kernel/rendering/pixelrendererbase.h"
#include "renderer/kernel/rendering/shadingresultframebuffer.h"
#include "renderer/kernel/shading/shadingresult.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/utility/settingsparsing.h"

// appleseed.foundation headers.
#include "foundation/image/color.h"
#include "foundation/image/image.h"
#include "foundation/image/tile.h"
#include "foundation/math/aabb.h"
#include "foundation/math/hash.h"
#include "foundation/math/minmax.h"
#include "foundation/math/scalar.h"
#include "foundation/math/vector.h"
#include "foundation/platform/types.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/containers/dictionary.h"
#include "foundation/utility/statistics.h"

// Standard headers.
#include <algorithm>
#include <cassert>
#include <cmath>
#include <memory>

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Adaptive pixel renderer.
    //

    class AdaptivePixelRenderer
      : public PixelRendererBase
    {
      public:
        AdaptivePixelRenderer(
            const Frame&                frame,
            ISampleRendererFactory*     factory,
            const ParamArray&           params,
            const size_t                thread_index)
          : m_params(params)
          , m_sample_renderer(factory->create(thread_index))
        {
            if (m_params.m_diagnostics)
            {
                m_variation_aov_index = frame.create_extra_aov_image("variation");
                m_samples_aov_index = frame.create_extra_aov_image("samples");

                if ((thread_index == 0) && (m_variation_aov_index == size_t(~0) || m_samples_aov_index == size_t(~0)))
                {
                    RENDERER_LOG_WARNING(
                        "could not create some of the diagnostic aovs, maximum number of aovs (" FMT_SIZE_T ") reached.",
                        MaxAOVCount);
                }
            }
        }

        void print_settings() const override
        {
            RENDERER_LOG_INFO(
                "adaptive pixel renderer settings:\n"
                "  sampling mode                 %s\n"
                "  min samples                   " FMT_SIZE_T "\n"
                "  max samples                   " FMT_SIZE_T "\n"
                "  max variation                 %f\n"
                "  diagnostics                   %s",
                m_params.m_sampling_mode == SamplingContext::Mode::QMCMode ? "qmc" : "rng",
                m_params.m_min_samples,
                m_params.m_max_samples,
                m_params.m_max_variation,
                m_params.m_diagnostics ? "on" : "off");
        }

        void release() override
        {
            delete this;
        }

        void on_tile_begin(
            const Frame&                frame,
            Tile&                       tile,
            TileStack&                  aov_tiles) override
        {
            m_scratch_fb_half_width = truncate<int>(ceil(frame.get_filter().get_xradius()));
            m_scratch_fb_half_height = truncate<int>(ceil(frame.get_filter().get_yradius()));

            m_scratch_fb.reset(
                new ShadingResultFrameBuffer(
                    2 * m_scratch_fb_half_width + 1,
                    2 * m_scratch_fb_half_height + 1,
                    frame.aov_images().size(),
                    frame.get_filter()));

            if (m_params.m_diagnostics)
                m_diagnostics.reset(new Tile(tile.get_width(), tile.get_height(), 2, PixelFormatFloat));
        }

        void on_tile_end(
            const Frame&                frame,
            Tile&                       tile,
            TileStack&                  aov_tiles) override
        {
            if (m_params.m_diagnostics)
            {
                const size_t width = tile.get_width();
                const size_t height = tile.get_height();

                for (size_t y = 0; y < height; ++y)
                {
                    for (size_t x = 0; x < width; ++x)
                    {
                        Color<float, 2> values;
                        m_diagnostics->get_pixel(x, y, values);

                        if (m_variation_aov_index != size_t(~0))
                            aov_tiles.set_pixel(x, y, m_variation_aov_index, scalar_to_color(values[0]));

                        if (m_samples_aov_index != size_t(~0))
                            aov_tiles.set_pixel(x, y, m_samples_aov_index, scalar_to_color(values[1]));
                    }
                }
            }
        }

        void render_pixel(
            const Frame&                frame,
            Tile&                       tile,
            TileStack&                  aov_tiles,
            const AABB2i&               tile_bbox,
            const size_t                pass_hash,
            const Vector2i&             pi,
            const Vector2i&             pt,
            AOVAccumulatorContainer&    aov_accumulators,
            ShadingResultFrameBuffer&   framebuffer) override
        {
            const size_t aov_count = frame.aov_images().size();

            on_pixel_begin(pi, aov_accumulators);

            m_scratch_fb->clear();

            // Create a sampling context.
            const size_t frame_width = frame.image().properties().m_canvas_width;
            const size_t pixel_index = pi.y * frame_width + pi.x;
            const size_t instance = hash_uint32(static_cast<uint32>(pass_hash + pixel_index));
            SamplingContext::RNGType rng(pass_hash, instance);
            SamplingContext sampling_context(
                rng,
                m_params.m_sampling_mode,
                2,                          // number of dimensions
                0,                          // number of samples -- unknown
                instance);                  // initial instance number

            VariationTracker trackers[3];

            while (true)
            {
                trackers[0].reset_variation();
                trackers[1].reset_variation();
                trackers[2].reset_variation();

                // Don't exceed 'max' samples in total.
                assert(trackers[0].get_size() <= m_params.m_max_samples);
                const size_t remaining_samples = m_params.m_max_samples - trackers[0].get_size();
                if (remaining_samples == 0)
                    break;

                // Each batch contains 'min' samples.
                const size_t batch_size = min(m_params.m_min_samples, remaining_samples);

                for (size_t i = 0; i < batch_size; ++i)
                {
                    // Generate a uniform sample in [0,1)^2.
                    const Vector2d s = sampling_context.next2<Vector2d>();

                    // Compute the sample position in NDC.
                    const Vector2d sample_position = frame.get_sample_position(pi.x + s.x, pi.y + s.y);

                    // Create a pixel context that identifies the pixel and sample currently being rendered.
                    const PixelContext pixel_context(pi, sample_position);

                    // Render the sample.
                    ShadingResult shading_result(aov_count);
                    SamplingContext child_sampling_context(sampling_context);
                    m_sample_renderer->render_sample(
                        child_sampling_context,
                        pixel_context,
                        sample_position,
                        aov_accumulators,
                        shading_result);

                    // Ignore invalid samples.
                    if (!shading_result.is_valid())
                    {
                        signal_invalid_sample();
                        continue;
                    }

                    // Merge the sample into the scratch framebuffer.
                    m_scratch_fb->add(
                        static_cast<float>(m_scratch_fb_half_width + s.x),
                        static_cast<float>(m_scratch_fb_half_height + s.y),
                        shading_result);

                    // Update statistics for this pixel.
                    // todo: variation should be computed in a user-selectable color space, typically the target color space.
                    // todo: one tracker per AOV?
                    trackers[0].insert(shading_result.m_main[0]);
                    trackers[1].insert(shading_result.m_main[1]);
                    trackers[2].insert(shading_result.m_main[2]);
                }

                // Stop if the variation criterion is met.
                if (trackers[0].get_variation() <= m_params.m_max_variation &&
                    trackers[1].get_variation() <= m_params.m_max_variation &&
                    trackers[2].get_variation() <= m_params.m_max_variation)
                    break;
            }

            // Merge the scratch framebuffer into the output framebuffer.
            const float rcp_sample_count = 1.0f / trackers[0].get_size();
            for (int y = -m_scratch_fb_half_height; y <= m_scratch_fb_half_height; ++y)
            {
                for (int x = -m_scratch_fb_half_width; x <= m_scratch_fb_half_width; ++x)
                {
                    if (tile_bbox.contains(Vector2i(pt.x + x, pt.y + y)))
                    {
                        framebuffer.merge(                  // destination
                            pt.x + x,                       // destination X
                            pt.y + y,                       // destination Y
                            *m_scratch_fb.get(),            // source
                            m_scratch_fb_half_width + x,    // source X
                            m_scratch_fb_half_height + y,   // source Y
                            rcp_sample_count);              // scaling
                    }
                }
            }

            // Store diagnostics values in the diagnostics tile.
            if (m_params.m_diagnostics && tile_bbox.contains(pt))
            {
                Color<float, 2> values;

                values[0] =
                    saturate(
                        max(
                            trackers[0].get_variation(),
                            trackers[1].get_variation(),
                            trackers[2].get_variation())
                        / m_params.m_max_variation);

                values[1] =
                    m_params.m_min_samples == m_params.m_max_samples
                        ? 1.0f
                        : fit(
                            static_cast<float>(trackers[0].get_size()),
                            static_cast<float>(m_params.m_min_samples),
                            static_cast<float>(m_params.m_max_samples),
                            0.0f, 1.0f);

                m_diagnostics->set_pixel(pt.x, pt.y, values);
            }

            on_pixel_end(pi, aov_accumulators);
        }

        StatisticsVector get_statistics() const override
        {
            return m_sample_renderer->get_statistics();
        }

        size_t get_max_samples_per_pixel() const override
        {
            return m_params.m_max_samples;
        }

      private:
        struct Parameters
        {
            const SamplingContext::Mode     m_sampling_mode;
            const size_t                    m_min_samples;
            const size_t                    m_max_samples;
            const float                     m_max_variation;
            const bool                      m_diagnostics;

            explicit Parameters(const ParamArray& params)
              : m_sampling_mode(get_sampling_context_mode(params))
              , m_min_samples(params.get_required<size_t>("min_samples", 16))
              , m_max_samples(params.get_required<size_t>("max_samples", 256))
              , m_max_variation(pow(10.0f, -params.get_optional<float>("quality", 2.0f)))
              , m_diagnostics(params.get_optional<bool>("enable_diagnostics", false))
            {
            }
        };

        const Parameters                        m_params;
        auto_release_ptr<ISampleRenderer>       m_sample_renderer;
        size_t                                  m_variation_aov_index;
        size_t                                  m_samples_aov_index;
        int                                     m_scratch_fb_half_width;
        int                                     m_scratch_fb_half_height;
        unique_ptr<ShadingResultFrameBuffer>    m_scratch_fb;
        unique_ptr<Tile>                        m_diagnostics;

        static Color4f scalar_to_color(const float value)
        {
            static const Color4f Blue(0.0f, 0.0f, 1.0f, 1.0f);
            static const Color4f Red(1.0f, 0.0f, 0.0f, 1.0f);
            return lerp(Blue, Red, saturate(value));
        }
    };
}

//
// AdaptivePixelRendererFactory class implementation.
//

AdaptivePixelRendererFactory::AdaptivePixelRendererFactory(
    const Frame&                frame,
    ISampleRendererFactory*     factory,
    const ParamArray&           params)
  : m_frame(frame)
  , m_factory(factory)
  , m_params(params)
{
}

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

IPixelRenderer* AdaptivePixelRendererFactory::create(
    const size_t                thread_index)
{
    return new AdaptivePixelRenderer(
        m_frame,
        m_factory,
        m_params,
        thread_index);
}

Dictionary AdaptivePixelRendererFactory::get_params_metadata()
{
    Dictionary metadata;

    metadata.dictionaries().insert(
        "min_samples",
        Dictionary()
            .insert("type", "int")
            .insert("default", "16")
            .insert("label", "Min Samples")
            .insert("help", "Minimum number of anti-aliasing samples"));

    metadata.dictionaries().insert(
        "max_samples",
        Dictionary()
            .insert("type", "int")
            .insert("default", "256")
            .insert("label", "Max Samples")
            .insert("help", "Maximum number of anti-aliasing samples"));

    metadata.dictionaries().insert(
        "quality",
        Dictionary()
            .insert("type", "float")
            .insert("default", "2.0")
            .insert("label", "Quality")
            .insert("help", "Quality factor"));

    metadata.dictionaries().insert(
        "enable_diagnostics",
        Dictionary()
            .insert("type", "bool")
            .insert("default", "false")
            .insert("label", "Enable Diagnostics")
            .insert(
                "help",
                "Enable adaptive sampling diagnostics"));

    return metadata;
}

}   // namespace renderer
<commit_msg>Don't reset trackers when sampling is finished<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-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014-2017 Francois Beaune, The appleseedhq Organization
//
// 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 "adaptivepixelrenderer.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/aov/aovsettings.h"
#include "renderer/kernel/aov/imagestack.h"
#include "renderer/kernel/aov/tilestack.h"
#include "renderer/kernel/rendering/final/variationtracker.h"
#include "renderer/kernel/rendering/isamplerenderer.h"
#include "renderer/kernel/rendering/pixelcontext.h"
#include "renderer/kernel/rendering/pixelrendererbase.h"
#include "renderer/kernel/rendering/shadingresultframebuffer.h"
#include "renderer/kernel/shading/shadingresult.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/utility/settingsparsing.h"

// appleseed.foundation headers.
#include "foundation/image/color.h"
#include "foundation/image/image.h"
#include "foundation/image/tile.h"
#include "foundation/math/aabb.h"
#include "foundation/math/hash.h"
#include "foundation/math/minmax.h"
#include "foundation/math/scalar.h"
#include "foundation/math/vector.h"
#include "foundation/platform/types.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/containers/dictionary.h"
#include "foundation/utility/statistics.h"

// Standard headers.
#include <algorithm>
#include <cassert>
#include <cmath>
#include <memory>

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Adaptive pixel renderer.
    //

    class AdaptivePixelRenderer
      : public PixelRendererBase
    {
      public:
        AdaptivePixelRenderer(
            const Frame&                frame,
            ISampleRendererFactory*     factory,
            const ParamArray&           params,
            const size_t                thread_index)
          : m_params(params)
          , m_sample_renderer(factory->create(thread_index))
        {
            if (m_params.m_diagnostics)
            {
                m_variation_aov_index = frame.create_extra_aov_image("variation");
                m_samples_aov_index = frame.create_extra_aov_image("samples");

                if ((thread_index == 0) && (m_variation_aov_index == size_t(~0) || m_samples_aov_index == size_t(~0)))
                {
                    RENDERER_LOG_WARNING(
                        "could not create some of the diagnostic aovs, maximum number of aovs (" FMT_SIZE_T ") reached.",
                        MaxAOVCount);
                }
            }
        }

        void print_settings() const override
        {
            RENDERER_LOG_INFO(
                "adaptive pixel renderer settings:\n"
                "  sampling mode                 %s\n"
                "  min samples                   " FMT_SIZE_T "\n"
                "  max samples                   " FMT_SIZE_T "\n"
                "  max variation                 %f\n"
                "  diagnostics                   %s",
                m_params.m_sampling_mode == SamplingContext::Mode::QMCMode ? "qmc" : "rng",
                m_params.m_min_samples,
                m_params.m_max_samples,
                m_params.m_max_variation,
                m_params.m_diagnostics ? "on" : "off");
        }

        void release() override
        {
            delete this;
        }

        void on_tile_begin(
            const Frame&                frame,
            Tile&                       tile,
            TileStack&                  aov_tiles) override
        {
            m_scratch_fb_half_width = truncate<int>(ceil(frame.get_filter().get_xradius()));
            m_scratch_fb_half_height = truncate<int>(ceil(frame.get_filter().get_yradius()));

            m_scratch_fb.reset(
                new ShadingResultFrameBuffer(
                    2 * m_scratch_fb_half_width + 1,
                    2 * m_scratch_fb_half_height + 1,
                    frame.aov_images().size(),
                    frame.get_filter()));

            if (m_params.m_diagnostics)
                m_diagnostics.reset(new Tile(tile.get_width(), tile.get_height(), 2, PixelFormatFloat));
        }

        void on_tile_end(
            const Frame&                frame,
            Tile&                       tile,
            TileStack&                  aov_tiles) override
        {
            if (m_params.m_diagnostics)
            {
                const size_t width = tile.get_width();
                const size_t height = tile.get_height();

                for (size_t y = 0; y < height; ++y)
                {
                    for (size_t x = 0; x < width; ++x)
                    {
                        Color<float, 2> values;
                        m_diagnostics->get_pixel(x, y, values);

                        if (m_variation_aov_index != size_t(~0))
                            aov_tiles.set_pixel(x, y, m_variation_aov_index, scalar_to_color(values[0]));

                        if (m_samples_aov_index != size_t(~0))
                            aov_tiles.set_pixel(x, y, m_samples_aov_index, scalar_to_color(values[1]));
                    }
                }
            }
        }

        void render_pixel(
            const Frame&                frame,
            Tile&                       tile,
            TileStack&                  aov_tiles,
            const AABB2i&               tile_bbox,
            const size_t                pass_hash,
            const Vector2i&             pi,
            const Vector2i&             pt,
            AOVAccumulatorContainer&    aov_accumulators,
            ShadingResultFrameBuffer&   framebuffer) override
        {
            const size_t aov_count = frame.aov_images().size();

            on_pixel_begin(pi, aov_accumulators);

            m_scratch_fb->clear();

            // Create a sampling context.
            const size_t frame_width = frame.image().properties().m_canvas_width;
            const size_t pixel_index = pi.y * frame_width + pi.x;
            const size_t instance = hash_uint32(static_cast<uint32>(pass_hash + pixel_index));
            SamplingContext::RNGType rng(pass_hash, instance);
            SamplingContext sampling_context(
                rng,
                m_params.m_sampling_mode,
                2,                          // number of dimensions
                0,                          // number of samples -- unknown
                instance);                  // initial instance number

            VariationTracker trackers[3];

            while (true)
            {
                // Don't exceed 'max' samples in total.
                assert(trackers[0].get_size() <= m_params.m_max_samples);
                const size_t remaining_samples = m_params.m_max_samples - trackers[0].get_size();
                if (remaining_samples == 0)
                    break;

                trackers[0].reset_variation();
                trackers[1].reset_variation();
                trackers[2].reset_variation();

                // Each batch contains 'min' samples.
                const size_t batch_size = min(m_params.m_min_samples, remaining_samples);

                for (size_t i = 0; i < batch_size; ++i)
                {
                    // Generate a uniform sample in [0,1)^2.
                    const Vector2d s = sampling_context.next2<Vector2d>();

                    // Compute the sample position in NDC.
                    const Vector2d sample_position = frame.get_sample_position(pi.x + s.x, pi.y + s.y);

                    // Create a pixel context that identifies the pixel and sample currently being rendered.
                    const PixelContext pixel_context(pi, sample_position);

                    // Render the sample.
                    ShadingResult shading_result(aov_count);
                    SamplingContext child_sampling_context(sampling_context);
                    m_sample_renderer->render_sample(
                        child_sampling_context,
                        pixel_context,
                        sample_position,
                        aov_accumulators,
                        shading_result);

                    // Ignore invalid samples.
                    if (!shading_result.is_valid())
                    {
                        signal_invalid_sample();
                        continue;
                    }

                    // Merge the sample into the scratch framebuffer.
                    m_scratch_fb->add(
                        static_cast<float>(m_scratch_fb_half_width + s.x),
                        static_cast<float>(m_scratch_fb_half_height + s.y),
                        shading_result);

                    // Update statistics for this pixel.
                    // todo: variation should be computed in a user-selectable color space, typically the target color space.
                    // todo: one tracker per AOV?
                    trackers[0].insert(shading_result.m_main[0]);
                    trackers[1].insert(shading_result.m_main[1]);
                    trackers[2].insert(shading_result.m_main[2]);
                }

                // Stop if the variation criterion is met.
                if (trackers[0].get_variation() <= m_params.m_max_variation &&
                    trackers[1].get_variation() <= m_params.m_max_variation &&
                    trackers[2].get_variation() <= m_params.m_max_variation)
                    break;
            }

            // Merge the scratch framebuffer into the output framebuffer.
            const float rcp_sample_count = 1.0f / trackers[0].get_size();
            for (int y = -m_scratch_fb_half_height; y <= m_scratch_fb_half_height; ++y)
            {
                for (int x = -m_scratch_fb_half_width; x <= m_scratch_fb_half_width; ++x)
                {
                    if (tile_bbox.contains(Vector2i(pt.x + x, pt.y + y)))
                    {
                        framebuffer.merge(                  // destination
                            pt.x + x,                       // destination X
                            pt.y + y,                       // destination Y
                            *m_scratch_fb.get(),            // source
                            m_scratch_fb_half_width + x,    // source X
                            m_scratch_fb_half_height + y,   // source Y
                            rcp_sample_count);              // scaling
                    }
                }
            }

            // Store diagnostics values in the diagnostics tile.
            if (m_params.m_diagnostics && tile_bbox.contains(pt))
            {
                Color<float, 2> values;

                values[0] =
                    saturate(
                        max(
                            trackers[0].get_variation(),
                            trackers[1].get_variation(),
                            trackers[2].get_variation())
                        / m_params.m_max_variation);

                values[1] =
                    m_params.m_min_samples == m_params.m_max_samples
                        ? 1.0f
                        : fit(
                            static_cast<float>(trackers[0].get_size()),
                            static_cast<float>(m_params.m_min_samples),
                            static_cast<float>(m_params.m_max_samples),
                            0.0f, 1.0f);

                m_diagnostics->set_pixel(pt.x, pt.y, values);
            }

            on_pixel_end(pi, aov_accumulators);
        }

        StatisticsVector get_statistics() const override
        {
            return m_sample_renderer->get_statistics();
        }

        size_t get_max_samples_per_pixel() const override
        {
            return m_params.m_max_samples;
        }

      private:
        struct Parameters
        {
            const SamplingContext::Mode     m_sampling_mode;
            const size_t                    m_min_samples;
            const size_t                    m_max_samples;
            const float                     m_max_variation;
            const bool                      m_diagnostics;

            explicit Parameters(const ParamArray& params)
              : m_sampling_mode(get_sampling_context_mode(params))
              , m_min_samples(params.get_required<size_t>("min_samples", 16))
              , m_max_samples(params.get_required<size_t>("max_samples", 256))
              , m_max_variation(pow(10.0f, -params.get_optional<float>("quality", 2.0f)))
              , m_diagnostics(params.get_optional<bool>("enable_diagnostics", false))
            {
            }
        };

        const Parameters                        m_params;
        auto_release_ptr<ISampleRenderer>       m_sample_renderer;
        size_t                                  m_variation_aov_index;
        size_t                                  m_samples_aov_index;
        int                                     m_scratch_fb_half_width;
        int                                     m_scratch_fb_half_height;
        unique_ptr<ShadingResultFrameBuffer>    m_scratch_fb;
        unique_ptr<Tile>                        m_diagnostics;

        static Color4f scalar_to_color(const float value)
        {
            static const Color4f Blue(0.0f, 0.0f, 1.0f, 1.0f);
            static const Color4f Red(1.0f, 0.0f, 0.0f, 1.0f);
            return lerp(Blue, Red, saturate(value));
        }
    };
}

//
// AdaptivePixelRendererFactory class implementation.
//

AdaptivePixelRendererFactory::AdaptivePixelRendererFactory(
    const Frame&                frame,
    ISampleRendererFactory*     factory,
    const ParamArray&           params)
  : m_frame(frame)
  , m_factory(factory)
  , m_params(params)
{
}

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

IPixelRenderer* AdaptivePixelRendererFactory::create(
    const size_t                thread_index)
{
    return new AdaptivePixelRenderer(
        m_frame,
        m_factory,
        m_params,
        thread_index);
}

Dictionary AdaptivePixelRendererFactory::get_params_metadata()
{
    Dictionary metadata;

    metadata.dictionaries().insert(
        "min_samples",
        Dictionary()
            .insert("type", "int")
            .insert("default", "16")
            .insert("label", "Min Samples")
            .insert("help", "Minimum number of anti-aliasing samples"));

    metadata.dictionaries().insert(
        "max_samples",
        Dictionary()
            .insert("type", "int")
            .insert("default", "256")
            .insert("label", "Max Samples")
            .insert("help", "Maximum number of anti-aliasing samples"));

    metadata.dictionaries().insert(
        "quality",
        Dictionary()
            .insert("type", "float")
            .insert("default", "2.0")
            .insert("label", "Quality")
            .insert("help", "Quality factor"));

    metadata.dictionaries().insert(
        "enable_diagnostics",
        Dictionary()
            .insert("type", "bool")
            .insert("default", "false")
            .insert("label", "Enable Diagnostics")
            .insert(
                "help",
                "Enable adaptive sampling diagnostics"));

    return metadata;
}

}   // namespace renderer
<|endoftext|>


<commit_before>/* @doc Computation of the dynamic aspect for a robot.
   This class will load the description of a robot from a VRML file
   following the OpenHRP syntax. Using ForwardVelocity it is then
   possible specifying the angular velocity and the angular value
   to get the absolute position, and absolute velocity of each
   body separetly. Heavy rewriting from the original source
   of Adrien and Jean-Remy.

   This implantation is an updated based on a mixture between
   the code provided by Jean-Remy and Adrien.

   Copyright (c) 2005-2006,
   @author Olivier Stasse, Ramzi Sellouati, Jean-Remy Chardonnet, Adrien Escande, Abderrahmane Kheddar
   Copyright (c) 2007-2009
   @author Olivier Stasse, Oussama Kannoun, Fumio Kanehiro.
   JRL-Japan, CNRS/AIST

   All rights reserved.

   Please refers to file License.txt for details on the license.

*/

/*! System includes */
#include <iostream>
#include <sstream>
#include <fstream>
#include <string.h>

#include "Debug.h"

/*! Local library includes. */
#include "MatrixAbstractLayer/MatrixAbstractLayer.h"
#include "dynamicsJRLJapan/DynamicBody.h"
#include "DynMultiBodyPrivate.h"
#include "robotDynamics/jrlBody.h"

#include "fileReader.h"

using namespace dynamicsJRLJapan;

void DynMultiBodyPrivate::SpecifyTheRootLabel(int ID)
{
  labelTheRoot = ID;
  m_listOfBodies[ID]->setLabelMother(-1);

  // Right now it is assume that the first body is the world,
  // and that this body is related to another body.
  // Thus liaisons[ID].size() should be equal to one.

  if (liaisons[ID].size()!=1)
    {
      cout << "Wrong assumption concerning the initial body." << endl;
      return;
    }
  int ld = liaisons[ID][0].liaison;
  m_RootOfTheJointsTree = listeLiaisons[ld].aJoint;
  m_RootOfTheJointsTree->setLinkedBody(*m_listOfBodies[ID]);
  ODEBUG(" m_RootOfTheJointsTree->m_globalConfiguration"<<
	  m_RootOfTheJointsTree->initialPosition());
  //specify the type of the root joint

  // Start the vector of joints.
  m_JointVector.clear();
  m_JointVector.insert(m_JointVector.end(),m_RootOfTheJointsTree);
  int lVRMLID = m_RootOfTheJointsTree->getIDinActuated();
  if (m_NbOfVRMLIDs < lVRMLID)
    m_NbOfVRMLIDs = lVRMLID;

  // Find out the next body to be examine.
  ReLabelling(ID,ld);

  // Once finished we initialize the child and the sister.
  for(unsigned int i=0;i<m_listOfBodies.size();i++)
    {
      int lMother,lElderSister;
      if ((lMother=m_listOfBodies[i]->getLabelMother()) != -1)
        {

	  if ((lElderSister=m_listOfBodies[lMother]->child) == -1)
            {
	      // Mother, I am your daughter !
	      m_listOfBodies[lMother]->child = i;
            }
	  else
            {
	      // I have an elder sister !
	      while (m_listOfBodies[lElderSister]->sister != -1)
		// I have another elder sister !
		lElderSister = m_listOfBodies[lElderSister]->sister;
	      // I am your younger sister !
	      m_listOfBodies[lElderSister]->sister = i;
            }
        }
    }

  for (unsigned int i = 0; i< m_listOfBodies.size();i++)
    m_listOfBodies[i]->massCoef(m_listOfBodies[i]->mass()/mass());
}

void DynMultiBodyPrivate::UpdateBodyParametersFromJoint(int BodyID, int JointID, int LiaisonForFatherJoint)
// cID : corps identifier
// lD : liaison destination
{

  ODEBUG( "Update body :" << BodyID << " from Joint " << JointID);
  // Update the rotation axis.
  m_listOfBodies[BodyID]->a =  listeLiaisons[JointID].aJoint->axe();
  ODEBUG(" axe: " << m_listOfBodies[BodyID]->a);
  // Update the translation vector
  listeLiaisons[JointID].aJoint->getStaticTranslation(m_listOfBodies[BodyID]->b);
  ODEBUG(" JointID: " << JointID << "BodyID: " << BodyID << ", static translation: " << m_listOfBodies[BodyID]->b);
  // Update the rotation matrix
  listeLiaisons[JointID].aJoint->getStaticRotation(m_listOfBodies[BodyID]->R_static);
  ODEBUG(" Rotation matrix: " << endl << m_listOfBodies[BodyID]->R_static);
  listeLiaisons[JointID].aJoint->setLinkedBody(*m_listOfBodies[BodyID]);
  m_listOfBodies[BodyID]->joint( listeLiaisons[JointID].aJoint);

}

void DynMultiBodyPrivate::ReLabelling(int corpsCourant, int liaisonDeProvenance)
{
  // This one has been nicely clean-up
  for (unsigned int i=0; i<liaisons[corpsCourant].size(); i++)
    {
      int liaisonDestination = liaisons[corpsCourant][i].liaison;
      if ((liaisonDestination == liaisonDeProvenance) &&
	  (corpsCourant!=labelTheRoot))
	continue;

      int corps1 = listeLiaisons[liaisonDestination].indexCorps1;
      int corps2 = listeLiaisons[liaisonDestination].indexCorps2;
      int corpsMother,corpsSon;

      if ((corpsCourant == corps1) && (corpsCourant != corps2))
        {
	  corpsSon = corps2;
	  corpsMother = corps1;
        }
      else
        {
	  corpsSon = corps1;
	  corpsMother = corps2;
        }
      m_listOfBodies[corpsSon]->setLabelMother(corpsMother);

      if(listeLiaisons[liaisonDestination].aJoint->getIDinActuated()!=-1)
        {

	  // Update the connections between the Joints.
	  int lIDinActuated = listeLiaisons[liaisonDestination].aJoint->getIDinActuated();
	  if (lIDinActuated!=-1)
            {
	      ConvertIDInActuatedToBodyID[lIDinActuated] = corpsSon;
            }

	  listeLiaisons[liaisonDeProvenance].aJoint->addChildJoint(*listeLiaisons[liaisonDestination].aJoint);

	  listeLiaisons[liaisonDestination].aJoint->SetFatherJoint(listeLiaisons[liaisonDeProvenance].aJoint);

	  // Update the vector of joints.
	  ODEBUG("Inside Relabelling :" << listeLiaisons[liaisonDestination].aJoint->getName().c_str());
	  ODEBUG("JointRankFromName :" << JointRankFromName(listeLiaisons[liaisonDestination].aJoint));
	  if (JointRankFromName(listeLiaisons[liaisonDestination].aJoint)!=-1)
	    m_JointVector.insert(m_JointVector.end(),listeLiaisons[liaisonDestination].aJoint);

	  int lVRMLID = listeLiaisons[liaisonDestination].aJoint->getIDinActuated();
	  if (m_NbOfVRMLIDs < lVRMLID)
	    m_NbOfVRMLIDs = lVRMLID;

        }

      // TODO : It is important to do the relabelling after the
      // TODO : recursive call to the relabelling as set father build
      // TODO : up the JointFromRootToThis vector. Should be fixed at the Joint object level.
      ReLabelling(corpsSon, liaisonDestination);
      UpdateBodyParametersFromJoint(corpsSon,liaisonDestination,liaisonDeProvenance);

    }

}

void DynMultiBodyPrivate::CreatesTreeStructure(const char * option)
{
  m_listOfBodies.resize(listeCorps.size());
  DynamicBodyPrivate *dbody;
  for(unsigned int i=0;i<listeCorps.size();i++)
    {
      dbody = dynamic_cast<DynamicBodyPrivate *>(listeCorps[i]);
      if (!dbody)
        {
	  dbody = new DynamicBodyPrivate();
	  *dbody = *listeCorps[i];
        }
      m_listOfBodies[i] = dbody;
    }

  if (option!=0)
    {
      ReadSpecificities(option);
    }

  ConvertIDInActuatedToBodyID.resize(m_listOfBodies.size());
  SpecifyTheRootLabel(0);
  ComputeNumberOfJoints();
  BuildStateVectorToJointAndDOFs();
  BuildLinkFromActuatedIDs();
  UpdateTheSizeOfJointsJacobian();

  for(unsigned int i=0;i<m_JointVector.size();i++)
    {
      JointPrivate *aJP = dynamic_cast<JointPrivate *>(m_JointVector[i]);
      if (aJP!=0)
	aJP->computeLocalAndGlobalPose();
    }

  MAL_VECTOR_RESIZE(m_Configuration,m_NbDofs);
  MAL_VECTOR_RESIZE(m_Velocity,m_NbDofs);
  MAL_VECTOR_RESIZE(m_Acceleration,m_NbDofs);

  MAL_MATRIX_RESIZE(m_Forces ,m_NbDofs,3);
  MAL_MATRIX_RESIZE(m_Torques,m_NbDofs,3);

  MAL_VECTOR_RESIZE(m_pastConfiguration,m_NbDofs);
  MAL_VECTOR_RESIZE(m_pastVelocity,m_NbDofs);
}

void DynMultiBodyPrivate::InitializeFromJointsTree()
{
  /* The goal of this method is to recreate the undirected
     graph, to restart the sequence of initialization. */
  vector<Body *> vectorOfBodies;
  int Depth=0;
  int NbOfBodies=0;
  internalLink CurrentLink ;

  /* Initialize the reading. */

  // Default initialization to 30 bodies for one branch.
  vectorOfBodies.resize(30);
  vectorOfBodies[0] = new DynamicBodyPrivate();
  vectorOfBodies[0]->setLabel(NbOfBodies++);
  ajouterCorps(*vectorOfBodies[0]);
  Depth++;

  MAL_S3_VECTOR(,double) dummy;

  // Go through the Joints tree.
  JointPrivate *CurrentJoint = m_RootOfTheJointsTree;
  JointPrivate *NextCurrentJoint=0,*FatherJoint;
  double mi[9]={ 1.0,1.0,1.0, 1.0,1.0,1.0, 1.0,1.0,1.0};

  CurrentLink.label = 0;
  CurrentLink.aJoint = m_RootOfTheJointsTree;
  CurrentLink.indexCorps1 = 0;
  CurrentLink.indexCorps2 = 0;
  int lIDinActuated=-1;
  unsigned int lRank=0;

  while(CurrentJoint!=0)
    {
      // Deal with the current joint.

      // Update the joint value of the current link.
      CurrentLink.aJoint = CurrentJoint;

      // Update the joint ID value in case there is none.
      if (CurrentLink.aJoint->getIDinActuated()==-1)
	CurrentLink.aJoint->setIDinActuated(lIDinActuated);

      lIDinActuated++;

      if (m_FileLinkJointRank.size()==0)
        // Create a relation between the name and the rank.
        {
	  NameAndRank_t aNameAndRank;

	  if (CurrentLink.aJoint->getName() == "")
            {
	      char buf[64];
	      if (CurrentLink.aJoint->type() == JointPrivate::FIX_JOINT)
                {
		  sprintf(buf, "FIXED_%02d", lRank);
                }
	      else
                {
		  sprintf(buf, "JOINT_%02d", lRank);
                }
	      string name(buf);
	      CurrentLink.aJoint->setName(name);
            }
	  strcpy(aNameAndRank.LinkName,
		 (char *)CurrentLink.aJoint->getName().c_str());

	  aNameAndRank.RankInConfiguration = lRank;
	  m_LinksBetweenJointNamesAndRank.insert(m_LinksBetweenJointNamesAndRank.end(),
						 aNameAndRank);

	  lRank+= CurrentLink.aJoint->numberDof();
        }

      // Take care of the body.
      // extend the size of vectorOfBodies if necessary.
      if (Depth>(int)vectorOfBodies.size())
        {
	  Body *aBody=NULL;
	  vectorOfBodies.push_back(aBody);
        }

      /*
        If a body has already been attached to the joint,
        keep inertial information
      */
      DynamicBodyPrivate* lCurrentBody = NULL;
      CjrlBody* jrlBody = CurrentJoint->linkedBody();
      if (jrlBody != NULL) {
	lCurrentBody = dynamic_cast<DynamicBodyPrivate*>(jrlBody);

	if (lCurrentBody) {
	  lCurrentBody->localCenterOfMass(jrlBody->localCenterOfMass());
	}
	else if (DynamicBody* dBody = dynamic_cast<DynamicBody*>(jrlBody)) {
	  lCurrentBody = dBody->m_privateObj.get();
	} else {
	  std::cerr <<
	    "dynamicsJRLJapan: body is not of ab expected type."
		    << std::endl;
	  throw(0);
	}
      }
      else
        {
	  lCurrentBody = new DynamicBodyPrivate();
	  lCurrentBody->setInertie(mi);
	  lCurrentBody->setMasse(1.0);// 1 kg per default.
	  vector3d cm;cm[0] = cm[1] =cm[2]=0.0;
	  lCurrentBody->localCenterOfMass(cm);
        }
      vectorOfBodies[Depth] = lCurrentBody;
      lCurrentBody->setLabel(NbOfBodies++);
      string lCurrentBodyName=CurrentJoint->getName();
      lCurrentBodyName = "BODY_" + lCurrentBodyName;
      lCurrentBody->setName((char *)lCurrentBodyName.c_str());
      lCurrentBody->setLabelMother(vectorOfBodies[Depth-1]->getLabel());

      ajouterCorps(*lCurrentBody);
      ajouterLiaison(*vectorOfBodies[Depth-1],
		     *lCurrentBody,
		     CurrentLink);

      // Find the next one.
      // 1. A children.
      NextCurrentJoint = (dynamicsJRLJapan::JointPrivate *)CurrentJoint->childJoint(0);
      Depth++;

      // No child.
      if (NextCurrentJoint==0)
        {
	  // If a father exist.
	  FatherJoint = (dynamicsJRLJapan::JointPrivate *)CurrentJoint->parentJoint();
	  Depth--;

	  while( (FatherJoint!=0) &&
		 (NextCurrentJoint==0))
            {
	      // Find the location of the current node
	      // in the father tree.
	      int NbOfChildren= FatherJoint->countChildJoints();
	      int CurrentJointPosition=-1;
	      for(int li=0;li<NbOfChildren;li++)
		if (FatherJoint->childJoint(li)==CurrentJoint)
		  {
		    CurrentJointPosition = li;
		    break;
		  }

	      // If a sibling has not been explored
	      if(CurrentJointPosition<NbOfChildren-1)
                {
		  // take it !
		  NextCurrentJoint = (dynamicsJRLJapan::JointPrivate *)FatherJoint->
		    childJoint(CurrentJointPosition+1);
                }
	      else
                {
		  // otherwise move upward.
		  CurrentJoint =FatherJoint;
		  FatherJoint=(dynamicsJRLJapan::JointPrivate *)FatherJoint->parentJoint();
		  Depth--;
                }
            }
	  // If finally FatherJoint==0 then NextCurrentJoint too is equal to 0.

        }

      CurrentJoint=NextCurrentJoint;

    }

  /* Initialize the data structures needed for the Newton-Euler algorithm. */
  if (m_FileLinkJointRank.size()==0)
    CreatesTreeStructure(0);
  else
    CreatesTreeStructure(m_FileLinkJointRank.c_str());

}
<commit_msg>Cleanup and message.<commit_after>/* @doc Computation of the dynamic aspect for a robot.
   This class will load the description of a robot from a VRML file
   following the OpenHRP syntax. Using ForwardVelocity it is then
   possible specifying the angular velocity and the angular value
   to get the absolute position, and absolute velocity of each
   body separetly. Heavy rewriting from the original source
   of Adrien and Jean-Remy.

   This implantation is an updated based on a mixture between
   the code provided by Jean-Remy and Adrien.

   Copyright (c) 2005-2006,
   @author Olivier Stasse, Ramzi Sellouati, Jean-Remy Chardonnet, Adrien Escande, Abderrahmane Kheddar
   Copyright (c) 2007-2009
   @author Olivier Stasse, Oussama Kannoun, Fumio Kanehiro.
   JRL-Japan, CNRS/AIST

   All rights reserved.

   Please refers to file License.txt for details on the license.

*/

/*! System includes */
#include <iostream>
#include <sstream>
#include <fstream>
#include <string.h>

#include "Debug.h"

/*! Local library includes. */
#include "MatrixAbstractLayer/MatrixAbstractLayer.h"
#include "dynamicsJRLJapan/DynamicBody.h"
#include "DynMultiBodyPrivate.h"
#include "robotDynamics/jrlBody.h"

#include "fileReader.h"

using namespace dynamicsJRLJapan;

void DynMultiBodyPrivate::SpecifyTheRootLabel(int ID)
{
  labelTheRoot = ID;
  m_listOfBodies[ID]->setLabelMother(-1);

  // Right now it is assume that the first body is the world,
  // and that this body is related to another body.
  // Thus liaisons[ID].size() should be equal to one.

  if (liaisons[ID].size()!=1)
    {
      cout << "Wrong assumption concerning the initial body: " << liaisons[ID].size()<< endl;
      return;
    }
  int ld = liaisons[ID][0].liaison;
  m_RootOfTheJointsTree = listeLiaisons[ld].aJoint;
  m_RootOfTheJointsTree->setLinkedBody(*m_listOfBodies[ID]);
  ODEBUG(" m_RootOfTheJointsTree->m_globalConfiguration"<<
	  m_RootOfTheJointsTree->initialPosition());
  //specify the type of the root joint

  // Start the vector of joints.
  m_JointVector.clear();
  m_JointVector.insert(m_JointVector.end(),m_RootOfTheJointsTree);
  int lVRMLID = m_RootOfTheJointsTree->getIDinActuated();
  if (m_NbOfVRMLIDs < lVRMLID)
    m_NbOfVRMLIDs = lVRMLID;

  // Find out the next body to be examine.
  ReLabelling(ID,ld);

  // Once finished we initialize the child and the sister.
  for(unsigned int i=0;i<m_listOfBodies.size();i++)
    {
      int lMother,lElderSister;
      if ((lMother=m_listOfBodies[i]->getLabelMother()) != -1)
        {

	  if ((lElderSister=m_listOfBodies[lMother]->child) == -1)
            {
	      // Mother, I am your daughter !
	      m_listOfBodies[lMother]->child = i;
            }
	  else
            {
	      // I have an elder sister !
	      while (m_listOfBodies[lElderSister]->sister != -1)
		// I have another elder sister !
		lElderSister = m_listOfBodies[lElderSister]->sister;
	      // I am your younger sister !
	      m_listOfBodies[lElderSister]->sister = i;
            }
        }
    }

  for (unsigned int i = 0; i< m_listOfBodies.size();i++)
    m_listOfBodies[i]->massCoef(m_listOfBodies[i]->mass()/mass());
}

void DynMultiBodyPrivate::UpdateBodyParametersFromJoint(int BodyID, int JointID, int LiaisonForFatherJoint)
// cID : corps identifier
// lD : liaison destination
{

  ODEBUG( "Update body :" << BodyID << " from Joint " << JointID);
  // Update the rotation axis.
  m_listOfBodies[BodyID]->a =  listeLiaisons[JointID].aJoint->axe();
  ODEBUG(" axe: " << m_listOfBodies[BodyID]->a);
  // Update the translation vector
  listeLiaisons[JointID].aJoint->getStaticTranslation(m_listOfBodies[BodyID]->b);
  ODEBUG(" JointID: " << JointID << "BodyID: " << BodyID << ", static translation: " << m_listOfBodies[BodyID]->b);
  // Update the rotation matrix
  listeLiaisons[JointID].aJoint->getStaticRotation(m_listOfBodies[BodyID]->R_static);
  ODEBUG(" Rotation matrix: " << endl << m_listOfBodies[BodyID]->R_static);
  listeLiaisons[JointID].aJoint->setLinkedBody(*m_listOfBodies[BodyID]);
  m_listOfBodies[BodyID]->joint( listeLiaisons[JointID].aJoint);

}

void DynMultiBodyPrivate::ReLabelling(int corpsCourant, int liaisonDeProvenance)
{
  // This one has been nicely clean-up
  for (unsigned int i=0; i<liaisons[corpsCourant].size(); i++)
    {
      int liaisonDestination = liaisons[corpsCourant][i].liaison;
      if ((liaisonDestination == liaisonDeProvenance) &&
	  (corpsCourant!=labelTheRoot))
	continue;

      int corps1 = listeLiaisons[liaisonDestination].indexCorps1;
      int corps2 = listeLiaisons[liaisonDestination].indexCorps2;
      int corpsMother,corpsSon;

      if ((corpsCourant == corps1) && (corpsCourant != corps2))
        {
	  corpsSon = corps2;
	  corpsMother = corps1;
        }
      else
        {
	  corpsSon = corps1;
	  corpsMother = corps2;
        }
      m_listOfBodies[corpsSon]->setLabelMother(corpsMother);

      if(listeLiaisons[liaisonDestination].aJoint->getIDinActuated()!=-1)
        {

	  // Update the connections between the Joints.
	  int lIDinActuated = listeLiaisons[liaisonDestination].aJoint->getIDinActuated();
	  if (lIDinActuated!=-1)
            {
	      ConvertIDInActuatedToBodyID[lIDinActuated] = corpsSon;
            }

	  listeLiaisons[liaisonDeProvenance].aJoint->addChildJoint(*listeLiaisons[liaisonDestination].aJoint);

	  listeLiaisons[liaisonDestination].aJoint->SetFatherJoint(listeLiaisons[liaisonDeProvenance].aJoint);

	  // Update the vector of joints.
	  ODEBUG("Inside Relabelling :" << listeLiaisons[liaisonDestination].aJoint->getName().c_str());
	  ODEBUG("JointRankFromName :" << JointRankFromName(listeLiaisons[liaisonDestination].aJoint));
	  if (JointRankFromName(listeLiaisons[liaisonDestination].aJoint)!=-1)
	    m_JointVector.insert(m_JointVector.end(),listeLiaisons[liaisonDestination].aJoint);

	  int lVRMLID = listeLiaisons[liaisonDestination].aJoint->getIDinActuated();
	  if (m_NbOfVRMLIDs < lVRMLID)
	    m_NbOfVRMLIDs = lVRMLID;

        }

      // TODO : It is important to do the relabelling after the
      // TODO : recursive call to the relabelling as set father build
      // TODO : up the JointFromRootToThis vector. Should be fixed at the Joint object level.
      ReLabelling(corpsSon, liaisonDestination);
      UpdateBodyParametersFromJoint(corpsSon,liaisonDestination,liaisonDeProvenance);

    }

}

void DynMultiBodyPrivate::CreatesTreeStructure(const char * option)
{
  m_listOfBodies.resize(listeCorps.size());
  DynamicBodyPrivate *dbody;
  for(unsigned int i=0;i<listeCorps.size();i++)
    {
      dbody = dynamic_cast<DynamicBodyPrivate *>(listeCorps[i]);
      if (!dbody)
        {
	  dbody = new DynamicBodyPrivate();
	  *dbody = *listeCorps[i];
        }
      m_listOfBodies[i] = dbody;
    }

  if (option!=0)
    {
      ReadSpecificities(option);
    }

  ConvertIDInActuatedToBodyID.resize(m_listOfBodies.size());
  SpecifyTheRootLabel(0);
  ComputeNumberOfJoints();
  BuildStateVectorToJointAndDOFs();
  BuildLinkFromActuatedIDs();
  UpdateTheSizeOfJointsJacobian();

  for(unsigned int i=0;i<m_JointVector.size();i++)
    {
      JointPrivate *aJP = dynamic_cast<JointPrivate *>(m_JointVector[i]);
      if (aJP!=0)
	aJP->computeLocalAndGlobalPose();
    }

  MAL_VECTOR_RESIZE(m_Configuration,m_NbDofs);
  MAL_VECTOR_RESIZE(m_Velocity,m_NbDofs);
  MAL_VECTOR_RESIZE(m_Acceleration,m_NbDofs);

  MAL_MATRIX_RESIZE(m_Forces ,m_NbDofs,3);
  MAL_MATRIX_RESIZE(m_Torques,m_NbDofs,3);

  MAL_VECTOR_RESIZE(m_pastConfiguration,m_NbDofs);
  MAL_VECTOR_RESIZE(m_pastVelocity,m_NbDofs);
}

void DynMultiBodyPrivate::InitializeFromJointsTree()
{
  /* The goal of this method is to recreate the undirected
     graph, to restart the sequence of initialization. */
  vector<Body *> vectorOfBodies;
  int Depth=0;
  int NbOfBodies=0;
  internalLink CurrentLink ;

  /* Initialize the reading. */

  // Default initialization to 30 bodies for one branch.
  vectorOfBodies.resize(30);
  vectorOfBodies[0] = new DynamicBodyPrivate();
  vectorOfBodies[0]->setLabel(NbOfBodies++);
  ajouterCorps(*vectorOfBodies[0]);
  Depth++;

  // Go through the Joints tree.
  JointPrivate *CurrentJoint = m_RootOfTheJointsTree;
  JointPrivate *NextCurrentJoint=0,*FatherJoint;
  double mi[9]={ 1.0,1.0,1.0, 1.0,1.0,1.0, 1.0,1.0,1.0};

  CurrentLink.label = 0;
  CurrentLink.aJoint = m_RootOfTheJointsTree;
  CurrentLink.indexCorps1 = 0;
  CurrentLink.indexCorps2 = 0;
  int lIDinActuated=-1;
  unsigned int lRank=0;

  while(CurrentJoint!=0)
    {
      // Deal with the current joint.

      // Update the joint value of the current link.
      CurrentLink.aJoint = CurrentJoint;

      // Update the joint ID value in case there is none.
      if (CurrentLink.aJoint->getIDinActuated()==-1)
	CurrentLink.aJoint->setIDinActuated(lIDinActuated);

      lIDinActuated++;

      if (m_FileLinkJointRank.size()==0)
        // Create a relation between the name and the rank.
        {
	  NameAndRank_t aNameAndRank;

	  if (CurrentLink.aJoint->getName() == "")
            {
	      char buf[64];
	      if (CurrentLink.aJoint->type() == JointPrivate::FIX_JOINT)
                {
		  sprintf(buf, "FIXED_%02d", lRank);
                }
	      else
                {
		  sprintf(buf, "JOINT_%02d", lRank);
                }
	      string name(buf);
	      CurrentLink.aJoint->setName(name);
            }
	  strcpy(aNameAndRank.LinkName,
		 (char *)CurrentLink.aJoint->getName().c_str());

	  aNameAndRank.RankInConfiguration = lRank;
	  m_LinksBetweenJointNamesAndRank.insert(m_LinksBetweenJointNamesAndRank.end(),
						 aNameAndRank);

	  lRank+= CurrentLink.aJoint->numberDof();
        }

      // Take care of the body.
      // extend the size of vectorOfBodies if necessary.
      if (Depth>(int)vectorOfBodies.size())
        {
	  Body *aBody=NULL;
	  vectorOfBodies.push_back(aBody);
        }

      /*
        If a body has already been attached to the joint,
        keep inertial information
      */
      DynamicBodyPrivate* lCurrentBody = NULL;
      CjrlBody* jrlBody = CurrentJoint->linkedBody();
      if (jrlBody != NULL) {
	lCurrentBody = dynamic_cast<DynamicBodyPrivate*>(jrlBody);

	if (lCurrentBody) {
	  lCurrentBody->localCenterOfMass(jrlBody->localCenterOfMass());
	}
	else if (DynamicBody* dBody = dynamic_cast<DynamicBody*>(jrlBody)) {
	  lCurrentBody = dBody->m_privateObj.get();
	} else {
	  std::cerr <<
	    "dynamicsJRLJapan: body is not of ab expected type."
		    << std::endl;
	  throw(0);
	}
      }
      else
        {
	  lCurrentBody = new DynamicBodyPrivate();
	  lCurrentBody->setInertie(mi);
	  lCurrentBody->setMasse(1.0);// 1 kg per default.
	  vector3d cm;cm[0] = cm[1] =cm[2]=0.0;
	  lCurrentBody->localCenterOfMass(cm);
        }
      vectorOfBodies[Depth] = lCurrentBody;
      lCurrentBody->setLabel(NbOfBodies++);
      string lCurrentBodyName=CurrentJoint->getName();
      lCurrentBodyName = "BODY_" + lCurrentBodyName;
      lCurrentBody->setName((char *)lCurrentBodyName.c_str());
      lCurrentBody->setLabelMother(vectorOfBodies[Depth-1]->getLabel());

      ajouterCorps(*lCurrentBody);
      ajouterLiaison(*vectorOfBodies[Depth-1],
		     *lCurrentBody,
		     CurrentLink);

      // Find the next one.
      // 1. A children.
      NextCurrentJoint = (dynamicsJRLJapan::JointPrivate *)CurrentJoint->childJoint(0);
      Depth++;

      // No child.
      if (NextCurrentJoint==0)
        {
	  // If a father exist.
	  FatherJoint = (dynamicsJRLJapan::JointPrivate *)CurrentJoint->parentJoint();
	  Depth--;

	  while( (FatherJoint!=0) &&
		 (NextCurrentJoint==0))
            {
	      // Find the location of the current node
	      // in the father tree.
	      int NbOfChildren= FatherJoint->countChildJoints();
	      int CurrentJointPosition=-1;
	      for(int li=0;li<NbOfChildren;li++)
		if (FatherJoint->childJoint(li)==CurrentJoint)
		  {
		    CurrentJointPosition = li;
		    break;
		  }

	      // If a sibling has not been explored
	      if(CurrentJointPosition<NbOfChildren-1)
                {
		  // take it !
		  NextCurrentJoint = (dynamicsJRLJapan::JointPrivate *)FatherJoint->
		    childJoint(CurrentJointPosition+1);
                }
	      else
                {
		  // otherwise move upward.
		  CurrentJoint =FatherJoint;
		  FatherJoint=(dynamicsJRLJapan::JointPrivate *)FatherJoint->parentJoint();
		  Depth--;
                }
            }
	  // If finally FatherJoint==0 then NextCurrentJoint too is equal to 0.

        }

      CurrentJoint=NextCurrentJoint;

    }

  /* Initialize the data structures needed for the Newton-Euler algorithm. */
  if (m_FileLinkJointRank.size()==0)
    CreatesTreeStructure(0);
  else
    CreatesTreeStructure(m_FileLinkJointRank.c_str());

}
<|endoftext|>


<commit_before>/*
   Copyright (c) 2010, The Mineserver Project
   All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
  * Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
  * Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
  * Neither the name of the The Mineserver Project nor the
    names of its contributors may be used to endorse or promote products
    derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <string>
#include <map>

#include "constants.h"

std::map<std::string, std::string> defaultConf;
std::map<uint8_t, Drop*> BLOCKDROPS;

void initConstants()
{
  // Init configuration
  // General settings
  defaultConf.insert(std::pair<std::string, std::string>("ip", "0.0.0.0"));
  defaultConf.insert(std::pair<std::string, std::string>("port", "25565"));
  defaultConf.insert(std::pair<std::string, std::string>("server_name", "Minecraft server"));
  defaultConf.insert(std::pair<std::string, std::string>("user_limit", "20"));
  defaultConf.insert(std::pair<std::string, std::string>("show_version", "true"));
  defaultConf.insert(std::pair<std::string, std::string>("user_validation", "true"));
  defaultConf.insert(std::pair<std::string, std::string>("allow_connect_on_auth_timeout", "false"));

  // Messages
  defaultConf.insert(std::pair<std::string, std::string>("server_full_message", "Server is currently full"));
  defaultConf.insert(std::pair<std::string, std::string>("default_kick_message", "You have been kicked"));
  defaultConf.insert(std::pair<std::string, std::string>("wrong_protocol_message", "Wrong client protocol"));
  // File settings
  defaultConf.insert(std::pair<std::string, std::string>("commands_file", COMMANDS_FILE));
  defaultConf.insert(std::pair<std::string, std::string>("roles_file", ROLES_FILE));
  defaultConf.insert(std::pair<std::string, std::string>("motd_file", MOTD_FILE));
  defaultConf.insert(std::pair<std::string, std::string>("rules_file", RULES_FILE));
  defaultConf.insert(std::pair<std::string, std::string>("pid_file", PID_FILE));
  // Map settings
  defaultConf.insert(std::pair<std::string, std::string>("map_directory", "world"));
  defaultConf.insert(std::pair<std::string, std::string>("map_release_time", "90"));
  defaultConf.insert(std::pair<std::string, std::string>("map_generate_spawn", "true"));
  defaultConf.insert(std::pair<std::string, std::string>("map_generate_spawn_size", "6"));
  defaultConf.insert(std::pair<std::string, std::string>("map_generate_spawn_show_progress", "true"));
  defaultConf.insert(std::pair<std::string, std::string>("save_unchanged_chunks", "true"));
  defaultConf.insert(std::pair<std::string, std::string>("liquid_physics", "true"));
  defaultConf.insert(std::pair<std::string, std::string>("map_flatgrass", "false"));
  defaultConf.insert(std::pair<std::string, std::string>("ore_density", "24"));
  defaultConf.insert(std::pair<std::string, std::string>("sea_level", "63"));
  defaultConf.insert(std::pair<std::string, std::string>("add_beaches", "true"));
  defaultConf.insert(std::pair<std::string, std::string>("beach_extent", "7"));
  defaultConf.insert(std::pair<std::string, std::string>("beach_height", "2"));
  defaultConf.insert(std::pair<std::string, std::string>("add_caves", "false"));
  defaultConf.insert(std::pair<std::string, std::string>("cave_density", "2"));
  defaultConf.insert(std::pair<std::string, std::string>("cave_size", "1"));
  defaultConf.insert(std::pair<std::string, std::string>("cave_water", "false"));
  defaultConf.insert(std::pair<std::string, std::string>("cave_lava", "false"));
  defaultConf.insert(std::pair<std::string, std::string>("cave_ore", "false"));

  // Block drops (10000 = 100%)

  // Blocks that always drop one item
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_STONE, new Drop(BLOCK_COBBLESTONE, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_GRASS, new Drop(BLOCK_DIRT, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_DIRT, new Drop(BLOCK_DIRT, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_COBBLESTONE, new Drop(BLOCK_COBBLESTONE, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_WOOD, new Drop(BLOCK_WOOD, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_SAPLING, new Drop(BLOCK_SAPLING, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_SAND, new Drop(BLOCK_SAND, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_COAL_ORE, new Drop(ITEM_COAL, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_IRON_ORE, new Drop(BLOCK_IRON_ORE, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_GOLD_ORE, new Drop(BLOCK_GOLD_ORE, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_DIAMOND_ORE, new Drop(ITEM_DIAMOND, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_LOG, new Drop(BLOCK_LOG, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_CLOTH, new Drop(BLOCK_CLOTH, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_WOODEN_STAIRS, new Drop(BLOCK_WOOD, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_RED_ROSE, new Drop(BLOCK_RED_ROSE, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_YELLOW_FLOWER, new Drop(BLOCK_YELLOW_FLOWER, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_BROWN_MUSHROOM, new Drop(BLOCK_BROWN_MUSHROOM, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_RED_MUSHROOM, new Drop(BLOCK_RED_MUSHROOM, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_LADDER, new Drop(BLOCK_LADDER, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_CACTUS, new Drop(BLOCK_CACTUS, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_REED, new Drop(BLOCK_REED, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_PUMPKIN, new Drop(BLOCK_PUMPKIN, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_TORCH, new Drop(BLOCK_TORCH, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_REDSTONE_TORCH_OFF, new Drop(BLOCK_REDSTONE_TORCH_OFF, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_REDSTONE_TORCH_ON, new Drop(BLOCK_REDSTONE_TORCH_ON, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_LIGHTSTONE, new Drop(ITEM_LIGHTSTONE_DUST, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_BRICK, new Drop(ITEM_CLAY_BRICK, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_JUKEBOX, new Drop(BLOCK_JUKEBOX, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_NETHERSTONE, new Drop(BLOCK_NETHERSTONE, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_SLOW_SAND, new Drop(BLOCK_SLOW_SAND, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_JACK_O_LANTERN, new Drop(BLOCK_JACK_O_LANTERN, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_MINECART_TRACKS, new Drop(BLOCK_MINECART_TRACKS, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_MOSSY_COBBLESTONE, new Drop(BLOCK_MOSSY_COBBLESTONE, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_OBSIDIAN, new Drop(BLOCK_OBSIDIAN, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_STEP, new Drop(BLOCK_STEP, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_DOUBLE_STEP, new Drop(BLOCK_STEP, 10000, 1)));

  // Always drop but give more than one item
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_REDSTONE_ORE, new Drop(ITEM_REDSTONE, 10000, 4)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_CLAY, new Drop(ITEM_CLAY_BALLS, 10000, 4)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_SNOW_BLOCK, new Drop(ITEM_SNOWBALL, 10000, 4)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_FURNACE, new Drop(BLOCK_COBBLESTONE, 10000, 3)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_BURNING_FURNACE, new Drop(BLOCK_COBBLESTONE, 10000, 3)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_CHEST, new Drop(BLOCK_CHEST, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_WORKBENCH, new Drop(BLOCK_WORKBENCH, 10000, 1)));

  // Blocks that drop items by chance
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_GRAVEL, new Drop(ITEM_FLINT, 850, 1, new Drop(BLOCK_GRAVEL, 10000, 1))));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_LEAVES, new Drop(BLOCK_SAPLING, 1200, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_SIGN_POST, new Drop(ITEM_SIGN, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_WALL_SIGN, new Drop(ITEM_SIGN, 10000, 1)));

  // Blocks that drop nothing
//  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_TNT, new Drop(BLOCK_TNT, 10000, 0, true)));
//  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_GLASS, new Drop(BLOCK_GLASS, 10000, 0, true)));
//  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_MOB_SPAWNER, new Drop(BLOCK_MOB_SPAWNER, 10000, 0, true)));
}

void freeConstants()
{
  std::map<uint8_t, Drop*>::iterator it_a = BLOCKDROPS.begin();
  std::map<uint8_t, Drop*>::iterator it_b = BLOCKDROPS.end();
  for (;it_a!=it_b;++it_a)
  {
    delete it_a->second;
  }
}
<commit_msg>- Fixed CLOTH>GRAY_CLOTH typo ;)<commit_after>/*
   Copyright (c) 2010, The Mineserver Project
   All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
  * Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
  * Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
  * Neither the name of the The Mineserver Project nor the
    names of its contributors may be used to endorse or promote products
    derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <string>
#include <map>

#include "constants.h"

std::map<std::string, std::string> defaultConf;
std::map<uint8_t, Drop*> BLOCKDROPS;

void initConstants()
{
  // Init configuration
  // General settings
  defaultConf.insert(std::pair<std::string, std::string>("ip", "0.0.0.0"));
  defaultConf.insert(std::pair<std::string, std::string>("port", "25565"));
  defaultConf.insert(std::pair<std::string, std::string>("server_name", "Minecraft server"));
  defaultConf.insert(std::pair<std::string, std::string>("user_limit", "20"));
  defaultConf.insert(std::pair<std::string, std::string>("show_version", "true"));
  defaultConf.insert(std::pair<std::string, std::string>("user_validation", "true"));
  defaultConf.insert(std::pair<std::string, std::string>("allow_connect_on_auth_timeout", "false"));

  // Messages
  defaultConf.insert(std::pair<std::string, std::string>("server_full_message", "Server is currently full"));
  defaultConf.insert(std::pair<std::string, std::string>("default_kick_message", "You have been kicked"));
  defaultConf.insert(std::pair<std::string, std::string>("wrong_protocol_message", "Wrong client protocol"));
  // File settings
  defaultConf.insert(std::pair<std::string, std::string>("commands_file", COMMANDS_FILE));
  defaultConf.insert(std::pair<std::string, std::string>("roles_file", ROLES_FILE));
  defaultConf.insert(std::pair<std::string, std::string>("motd_file", MOTD_FILE));
  defaultConf.insert(std::pair<std::string, std::string>("rules_file", RULES_FILE));
  defaultConf.insert(std::pair<std::string, std::string>("pid_file", PID_FILE));
  // Map settings
  defaultConf.insert(std::pair<std::string, std::string>("map_directory", "world"));
  defaultConf.insert(std::pair<std::string, std::string>("map_release_time", "90"));
  defaultConf.insert(std::pair<std::string, std::string>("map_generate_spawn", "true"));
  defaultConf.insert(std::pair<std::string, std::string>("map_generate_spawn_size", "6"));
  defaultConf.insert(std::pair<std::string, std::string>("map_generate_spawn_show_progress", "true"));
  defaultConf.insert(std::pair<std::string, std::string>("save_unchanged_chunks", "true"));
  defaultConf.insert(std::pair<std::string, std::string>("liquid_physics", "true"));
  defaultConf.insert(std::pair<std::string, std::string>("map_flatgrass", "false"));
  defaultConf.insert(std::pair<std::string, std::string>("ore_density", "24"));
  defaultConf.insert(std::pair<std::string, std::string>("sea_level", "63"));
  defaultConf.insert(std::pair<std::string, std::string>("add_beaches", "true"));
  defaultConf.insert(std::pair<std::string, std::string>("beach_extent", "7"));
  defaultConf.insert(std::pair<std::string, std::string>("beach_height", "2"));
  defaultConf.insert(std::pair<std::string, std::string>("add_caves", "false"));
  defaultConf.insert(std::pair<std::string, std::string>("cave_density", "2"));
  defaultConf.insert(std::pair<std::string, std::string>("cave_size", "1"));
  defaultConf.insert(std::pair<std::string, std::string>("cave_water", "false"));
  defaultConf.insert(std::pair<std::string, std::string>("cave_lava", "false"));
  defaultConf.insert(std::pair<std::string, std::string>("cave_ore", "false"));

  // Block drops (10000 = 100%)

  // Blocks that always drop one item
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_STONE, new Drop(BLOCK_COBBLESTONE, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_GRASS, new Drop(BLOCK_DIRT, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_DIRT, new Drop(BLOCK_DIRT, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_COBBLESTONE, new Drop(BLOCK_COBBLESTONE, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_WOOD, new Drop(BLOCK_WOOD, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_SAPLING, new Drop(BLOCK_SAPLING, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_SAND, new Drop(BLOCK_SAND, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_COAL_ORE, new Drop(ITEM_COAL, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_IRON_ORE, new Drop(BLOCK_IRON_ORE, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_GOLD_ORE, new Drop(BLOCK_GOLD_ORE, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_DIAMOND_ORE, new Drop(ITEM_DIAMOND, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_LOG, new Drop(BLOCK_LOG, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_GRAY_CLOTH, new Drop(BLOCK_GRAY_CLOTH, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_WOODEN_STAIRS, new Drop(BLOCK_WOOD, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_RED_ROSE, new Drop(BLOCK_RED_ROSE, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_YELLOW_FLOWER, new Drop(BLOCK_YELLOW_FLOWER, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_BROWN_MUSHROOM, new Drop(BLOCK_BROWN_MUSHROOM, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_RED_MUSHROOM, new Drop(BLOCK_RED_MUSHROOM, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_LADDER, new Drop(BLOCK_LADDER, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_CACTUS, new Drop(BLOCK_CACTUS, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_REED, new Drop(BLOCK_REED, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_PUMPKIN, new Drop(BLOCK_PUMPKIN, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_TORCH, new Drop(BLOCK_TORCH, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_REDSTONE_TORCH_OFF, new Drop(BLOCK_REDSTONE_TORCH_OFF, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_REDSTONE_TORCH_ON, new Drop(BLOCK_REDSTONE_TORCH_ON, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_LIGHTSTONE, new Drop(ITEM_LIGHTSTONE_DUST, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_BRICK, new Drop(ITEM_CLAY_BRICK, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_JUKEBOX, new Drop(BLOCK_JUKEBOX, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_NETHERSTONE, new Drop(BLOCK_NETHERSTONE, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_SLOW_SAND, new Drop(BLOCK_SLOW_SAND, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_JACK_O_LANTERN, new Drop(BLOCK_JACK_O_LANTERN, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_MINECART_TRACKS, new Drop(BLOCK_MINECART_TRACKS, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_MOSSY_COBBLESTONE, new Drop(BLOCK_MOSSY_COBBLESTONE, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_OBSIDIAN, new Drop(BLOCK_OBSIDIAN, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_STEP, new Drop(BLOCK_STEP, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_DOUBLE_STEP, new Drop(BLOCK_STEP, 10000, 1)));

  // Always drop but give more than one item
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_REDSTONE_ORE, new Drop(ITEM_REDSTONE, 10000, 4)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_CLAY, new Drop(ITEM_CLAY_BALLS, 10000, 4)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_SNOW_BLOCK, new Drop(ITEM_SNOWBALL, 10000, 4)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_FURNACE, new Drop(BLOCK_COBBLESTONE, 10000, 3)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_BURNING_FURNACE, new Drop(BLOCK_COBBLESTONE, 10000, 3)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_CHEST, new Drop(BLOCK_CHEST, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_WORKBENCH, new Drop(BLOCK_WORKBENCH, 10000, 1)));

  // Blocks that drop items by chance
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_GRAVEL, new Drop(ITEM_FLINT, 850, 1, new Drop(BLOCK_GRAVEL, 10000, 1))));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_LEAVES, new Drop(BLOCK_SAPLING, 1200, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_SIGN_POST, new Drop(ITEM_SIGN, 10000, 1)));
  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_WALL_SIGN, new Drop(ITEM_SIGN, 10000, 1)));

  // Blocks that drop nothing
//  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_TNT, new Drop(BLOCK_TNT, 10000, 0, true)));
//  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_GLASS, new Drop(BLOCK_GLASS, 10000, 0, true)));
//  BLOCKDROPS.insert(std::pair<uint8_t, Drop*>(BLOCK_MOB_SPAWNER, new Drop(BLOCK_MOB_SPAWNER, 10000, 0, true)));
}

void freeConstants()
{
  std::map<uint8_t, Drop*>::iterator it_a = BLOCKDROPS.begin();
  std::map<uint8_t, Drop*>::iterator it_b = BLOCKDROPS.end();
  for (;it_a!=it_b;++it_a)
  {
    delete it_a->second;
  }
}
<|endoftext|>