<commit_before>/**
 * @copyright
 * ====================================================================
 *    Licensed to the Apache Software Foundation (ASF) under one
 *    or more contributor license agreements.  See the NOTICE file
 *    distributed with this work for additional information
 *    regarding copyright ownership.  The ASF licenses this file
 *    to you 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.
 * ====================================================================
 * @endcopyright
 *
 * @file LogMessageCallback.cpp
 * @brief Implementation of the class LogMessageCallback
 */

#include "LogMessageCallback.h"
#include "CreateJ.h"
#include "EnumMapper.h"
#include "JNIUtil.h"
#include "svn_time.h"
#include "svn_sorts.h"
#include "svn_compat.h"

/**
 * Create a LogMessageCallback object
 * @param jcallback the Java callback object.
 */
LogMessageCallback::LogMessageCallback(jobject jcallback)
{
  m_callback = jcallback;
}

/**
 * Destroy a LogMessageCallback object
 */
LogMessageCallback::~LogMessageCallback()
{
  // The m_callback does not need to be destroyed because it is the
  // passed in parameter to the Java SVNClientInterface.logMessages
  // method.
}

svn_error_t *
LogMessageCallback::callback(void *baton,
                             svn_log_entry_t *log_entry,
                             apr_pool_t *pool)
{
  if (baton)
    return ((LogMessageCallback *)baton)->singleMessage(log_entry, pool);

  return SVN_NO_ERROR;
}

/**
 * Callback called for a single log message
 */
svn_error_t *
LogMessageCallback::singleMessage(svn_log_entry_t *log_entry, apr_pool_t *pool)
{
  JNIEnv *env = JNIUtil::getEnv();

  // The method id will not change during the time this library is
  // loaded, so it can be cached.
  static jmethodID sm_mid = 0;
  if (sm_mid == 0)
    {
      jclass clazz = env->FindClass(JAVA_PACKAGE"/callback/LogMessageCallback");
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;

      sm_mid = env->GetMethodID(clazz,
                                "singleMessage",
                                "(Ljava/util/Set;JLjava/util/Map;Z)V");
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;

      env->DeleteLocalRef(clazz);
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;
    }

  jclass clazzCP = env->FindClass(JAVA_PACKAGE"/ChangePath");
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  static jmethodID midCP = 0;
  if (midCP == 0)
    {
      midCP = env->GetMethodID(clazzCP,
                               "<init>",
                               "(Ljava/lang/String;JLjava/lang/String;CIII)V");
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;
    }

  jobject jChangedPaths = NULL;
  if (log_entry->changed_paths)
    {
      apr_hash_index_t *hi;
      std::vector<jobject> jcps;

      for (hi = apr_hash_first(pool, log_entry->changed_paths);
           hi;
           hi = apr_hash_next(hi))
        {
          const char *path = (const char *) svn_apr_hash_index_key(hi);
          svn_log_changed_path2_t *log_item =
                    (svn_log_changed_path2_t *) svn_apr_hash_index_val(hi);

          jstring jpath = JNIUtil::makeJString(path);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          jstring jcopyFromPath =
            JNIUtil::makeJString(log_item->copyfrom_path);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          jlong jcopyFromRev = log_item->copyfrom_rev;
          jchar jaction = log_item->action;

          jobject cp = env->NewObject(clazzCP, midCP, jpath, jcopyFromRev,
                              jcopyFromPath, jaction,
                              EnumMapper::mapNodeKind(log_item->node_kind),
                              EnumMapper::mapTristate(log_item->text_modified),
                              EnumMapper::mapTristate(log_item->props_modified));
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          jcps.push_back(cp);

          env->DeleteLocalRef(jpath);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          env->DeleteLocalRef(jcopyFromPath);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;
        }

      jChangedPaths = CreateJ::Set(jcps);
    }

  jobject jrevprops = NULL;
  if (log_entry->revprops != NULL && apr_hash_count(log_entry->revprops) > 0)
    jrevprops = CreateJ::PropertyMap(log_entry->revprops, pool);

  env->CallVoidMethod(m_callback,
                      sm_mid,
                      jChangedPaths,
                      (jlong)log_entry->revision,
                      jrevprops,
                      (jboolean)log_entry->has_children);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  env->DeleteLocalRef(jChangedPaths);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  env->DeleteLocalRef(jrevprops);
  // No need to check for an exception here, because we return anyway.

  return SVN_NO_ERROR;
}
<commit_msg>JavaHL: Fix build errors introduced by r922003.<commit_after>/**
 * @copyright
 * ====================================================================
 *    Licensed to the Apache Software Foundation (ASF) under one
 *    or more contributor license agreements.  See the NOTICE file
 *    distributed with this work for additional information
 *    regarding copyright ownership.  The ASF licenses this file
 *    to you 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.
 * ====================================================================
 * @endcopyright
 *
 * @file LogMessageCallback.cpp
 * @brief Implementation of the class LogMessageCallback
 */

#include "LogMessageCallback.h"
#include "CreateJ.h"
#include "EnumMapper.h"
#include "JNIUtil.h"
#include "svn_time.h"
#include "svn_sorts.h"
#include "svn_compat.h"

/**
 * Create a LogMessageCallback object
 * @param jcallback the Java callback object.
 */
LogMessageCallback::LogMessageCallback(jobject jcallback)
{
  m_callback = jcallback;
}

/**
 * Destroy a LogMessageCallback object
 */
LogMessageCallback::~LogMessageCallback()
{
  // The m_callback does not need to be destroyed because it is the
  // passed in parameter to the Java SVNClientInterface.logMessages
  // method.
}

svn_error_t *
LogMessageCallback::callback(void *baton,
                             svn_log_entry_t *log_entry,
                             apr_pool_t *pool)
{
  if (baton)
    return ((LogMessageCallback *)baton)->singleMessage(log_entry, pool);

  return SVN_NO_ERROR;
}

/**
 * Callback called for a single log message
 */
svn_error_t *
LogMessageCallback::singleMessage(svn_log_entry_t *log_entry, apr_pool_t *pool)
{
  JNIEnv *env = JNIUtil::getEnv();

  // The method id will not change during the time this library is
  // loaded, so it can be cached.
  static jmethodID sm_mid = 0;
  if (sm_mid == 0)
    {
      jclass clazz = env->FindClass(JAVA_PACKAGE"/callback/LogMessageCallback");
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;

      sm_mid = env->GetMethodID(clazz,
                                "singleMessage",
                                "(Ljava/util/Set;JLjava/util/Map;Z)V");
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;

      env->DeleteLocalRef(clazz);
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;
    }

  jclass clazzCP = env->FindClass(JAVA_PACKAGE"/ChangePath");
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  static jmethodID midCP = 0;
  if (midCP == 0)
    {
      midCP = env->GetMethodID(clazzCP,
                               "<init>",
                               "(Ljava/lang/String;JLjava/lang/String;CIII)V");
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;
    }

  jobject jChangedPaths = NULL;
  if (log_entry->changed_paths)
    {
      apr_hash_index_t *hi;
      std::vector<jobject> jcps;

      for (hi = apr_hash_first(pool, log_entry->changed_paths);
           hi;
           hi = apr_hash_next(hi))
        {
          const char *path = (const char *) svn__apr_hash_index_key(hi);
          svn_log_changed_path2_t *log_item =
                    (svn_log_changed_path2_t *) svn__apr_hash_index_val(hi);

          jstring jpath = JNIUtil::makeJString(path);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          jstring jcopyFromPath =
            JNIUtil::makeJString(log_item->copyfrom_path);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          jlong jcopyFromRev = log_item->copyfrom_rev;
          jchar jaction = log_item->action;

          jobject cp = env->NewObject(clazzCP, midCP, jpath, jcopyFromRev,
                              jcopyFromPath, jaction,
                              EnumMapper::mapNodeKind(log_item->node_kind),
                              EnumMapper::mapTristate(log_item->text_modified),
                              EnumMapper::mapTristate(log_item->props_modified));
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          jcps.push_back(cp);

          env->DeleteLocalRef(jpath);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          env->DeleteLocalRef(jcopyFromPath);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;
        }

      jChangedPaths = CreateJ::Set(jcps);
    }

  jobject jrevprops = NULL;
  if (log_entry->revprops != NULL && apr_hash_count(log_entry->revprops) > 0)
    jrevprops = CreateJ::PropertyMap(log_entry->revprops, pool);

  env->CallVoidMethod(m_callback,
                      sm_mid,
                      jChangedPaths,
                      (jlong)log_entry->revision,
                      jrevprops,
                      (jboolean)log_entry->has_children);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  env->DeleteLocalRef(jChangedPaths);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  env->DeleteLocalRef(jrevprops);
  // No need to check for an exception here, because we return anyway.

  return SVN_NO_ERROR;
}
<|endoftext|>


<commit_before>#include <chrono>
#include <memory>
#include <iostream>
#include <SFML/Graphics.hpp>
#include <Wind/Engine/Entity/Entity.hpp>
#include <Wind/Engine/Engine/Engine.hpp>

int main()
{
	sf::RenderWindow window{{800, 600}, "Windtunnel"};
	window.setFramerateLimit(1000);

	// Basic particle shape
	sf::CircleShape particle_shape;
	particle_shape.setRadius(0.75f);
	particle_shape.setFillColor(sf::Color::Red);

	wind::Engine engine;

	// Create array of physics objects
	wind::Vector2u amount{30, 30};
	std::vector<std::shared_ptr<wind::Entity>> particles;
	particles.resize(amount.x*amount.y);
	std::cout<<"num_particles: "<<particles.size()<<std::endl;

	// Assign particle positions
	for(auto particle_index=0; particle_index < particles.size(); ++particle_index)
	{
		auto& particle = particles[particle_index];
		particle = std::make_shared<wind::Entity>();

		particle->position.x = particle_index%amount.y;
		particle->position.y = particle_index/amount.x;
		particle->position.x*= window.getSize().x/amount.x;
		particle->position.y*= window.getSize().y/amount.y;
		particle->mass = 10000.f;
		particle->gravity_exert=true;
		particle->gravity_affected=true;

		engine.add_entity(particle);
	}

	// Used for calculating frametimes
	auto frame_start = std::chrono::high_resolution_clock::now();
	while(window.isOpen())
	{
		auto frame_duration = std::chrono::high_resolution_clock::now() - frame_start;
		frame_start = std::chrono::high_resolution_clock::now();

		auto frame_duration_us = std::chrono::duration_cast<std::chrono::microseconds>(frame_duration);
		auto frametime_us = frame_duration_us.count();
		auto frametime_ms = frametime_us/1000.f;
		auto frametime_s  = frametime_ms/1000.f;

		window.setTitle(
			"Windtunnel :: [FPS] " + std::to_string(1.f/(frametime_s)) +
			"\t:: [Frametime] " + std::to_string(frametime_us) + "us"
		);

		sf::Event event;
		while(window.pollEvent(event))
		{
			switch(event.type)
			{
			case sf::Event::Closed:
				window.close();
				break;
			case sf::Event::KeyReleased:
				switch(event.key.code)
				{
				case sf::Keyboard::G:
					engine.gravity = !engine.gravity;
					break;
				default:
					break;
				}
			default:
				break;
			}
		}

		window.clear();

		engine.simulate(wind::Engine::StandardDuration(30.f));

		for(auto& particle : particles)
		{
			particle_shape.setPosition(particle->position.x, particle->position.y);
			window.draw(particle_shape);
		}
		window.display();

	}
}
<commit_msg>examples: testbench: Updated testbench to use new body framework<commit_after>#include <chrono>
#include <memory>
#include <iostream>
#include <SFML/Graphics.hpp>
#include <Wind/Engine/Body/Body.hpp>
#include <Wind/Engine/Shape/Shape.hpp>
#include <Wind/Engine/Shape/CircleShape.hpp>
#include <Wind/Engine/Entity/Entity.hpp>
#include <Wind/Engine/Engine/Engine.hpp>

int main()
{
	sf::RenderWindow window{{800, 600}, "Windtunnel"};
	window.setFramerateLimit(1000);

	// Basic particle shape
	sf::CircleShape particle_drawable;
	particle_drawable.setRadius(0.75f);
	particle_drawable.setFillColor(sf::Color::Red);

	wind::Engine engine;

	// Create array of physics objects
	wind::Vector2u amount{40, 40};
	std::vector<std::shared_ptr<wind::Entity>> particles;
	particles.resize(amount.x*amount.y);
	std::cout<<"num_particles: "<<particles.size()<<std::endl;

	// Create particle shapes and bodies
	std::shared_ptr<wind::Body> particle_body=std::make_shared<wind::Body>();
	std::shared_ptr<wind::Shape> particle_shape=std::make_shared<wind::CircleShape>(0.75f);
	particle_body->add_shape(particle_shape);

	// Assign particle positions
	for(auto particle_index=0; particle_index < particles.size(); ++particle_index)
	{
		auto& particle = particles[particle_index];
		particle = std::make_shared<wind::Entity>();

		particle->position.x = particle_index%amount.y;
		particle->position.y = particle_index/amount.x;
		particle->position.x*= window.getSize().x/amount.x;
		particle->position.y*= window.getSize().y/amount.y;
		particle->mass = 10000.f;
		particle->gravity_exert=true;
		particle->gravity_affected=true;

		particle->set_body(particle_body);

		engine.add_entity(particle);
	}

	// Used for calculating frametimes
	auto frame_start = std::chrono::high_resolution_clock::now();
	while(window.isOpen())
	{
		auto frame_duration = std::chrono::high_resolution_clock::now() - frame_start;
		frame_start = std::chrono::high_resolution_clock::now();

		auto frame_duration_us = std::chrono::duration_cast<std::chrono::microseconds>(frame_duration);
		auto frametime_us = frame_duration_us.count();
		auto frametime_ms = frametime_us/1000.f;
		auto frametime_s  = frametime_ms/1000.f;

		window.setTitle(
			"Windtunnel :: [FPS] " + std::to_string(1.f/(frametime_s)) +
			"\t:: [Frametime] " + std::to_string(frametime_us) + "us"
		);

		sf::Event event;
		while(window.pollEvent(event))
		{
			switch(event.type)
			{
			case sf::Event::Closed:
				window.close();
				break;
			case sf::Event::KeyReleased:
				switch(event.key.code)
				{
				case sf::Keyboard::G:
					engine.gravity = !engine.gravity;
					break;
				default:
					break;
				}
			default:
				break;
			}
		}

		window.clear();

		engine.simulate(wind::Engine::StandardDuration(30.f));

		for(auto& particle : particles)
		{
			particle_drawable.setPosition(particle->position.x, particle->position.y);
			window.draw(particle_drawable);
		}
		window.display();

	}
}
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2013 Torus Knot Software Ltd

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.
-----------------------------------------------------------------------------
*/
#include "OgreD3D9RenderSystem.h"
#include "OgreD3D9HardwareBufferManager.h"
#include "OgreD3D9HardwareVertexBuffer.h"
#include "OgreD3D9HardwareIndexBuffer.h"
#include "OgreD3D9VertexDeclaration.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreException.h"

namespace Ogre {
    //-----------------------------------------------------------------------
    D3D9HardwareBufferManagerBase::D3D9HardwareBufferManagerBase()
    {
    }
    //-----------------------------------------------------------------------
    D3D9HardwareBufferManagerBase::~D3D9HardwareBufferManagerBase()
    {
        destroyAllDeclarations();
        destroyAllBindings();
    }
    //-----------------------------------------------------------------------
    HardwareVertexBufferSharedPtr
    D3D9HardwareBufferManagerBase::
    createVertexBuffer(size_t vertexSize, size_t numVerts, HardwareBuffer::Usage usage,
		bool useShadowBuffer)
    {
		assert (numVerts > 0);
#if OGRE_D3D_MANAGE_BUFFERS
        // Override shadow buffer setting; managed buffers are automatically
        // backed by system memory
        // Don't override shadow buffer if discardable, since then we use
        // unmanaged buffers for speed (avoids write-through overhead)
		// Don't override if we use directX9EX, since then we don't have managed
		// pool. And creating non-write only default pool causes a performance warning.
		if (useShadowBuffer && !(usage & HardwareBuffer::HBU_DISCARDABLE) &&
			!D3D9RenderSystem::isDirectX9Ex())
		{
            useShadowBuffer = false;
            // Also drop any WRITE_ONLY so we can read direct
            if (usage == HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY)
            {
                usage = HardwareBuffer::HBU_DYNAMIC;
            }
            else if (usage == HardwareBuffer::HBU_STATIC_WRITE_ONLY)
            {
                usage = HardwareBuffer::HBU_STATIC;
            }
        }
#endif
		D3D9HardwareVertexBuffer* vbuf = OGRE_NEW D3D9HardwareVertexBuffer(
			this, vertexSize, numVerts, usage, false, useShadowBuffer);
		{
                    OGRE_LOCK_MUTEX(mVertexBuffersMutex);
			mVertexBuffers.insert(vbuf);
		}
        return HardwareVertexBufferSharedPtr(vbuf);
    }
    //-----------------------------------------------------------------------
	HardwareIndexBufferSharedPtr
    D3D9HardwareBufferManagerBase::
    createIndexBuffer(HardwareIndexBuffer::IndexType itype, size_t numIndexes,
        HardwareBuffer::Usage usage, bool useShadowBuffer)
    {
		assert (numIndexes > 0);
#if OGRE_D3D_MANAGE_BUFFERS
        // Override shadow buffer setting; managed buffers are automatically
        // backed by system memory
		// Don't override shadow buffer if discardable, since then we use
		// unmanaged buffers for speed (avoids write-through overhead)
		// Don't override if we use directX9EX, since then we don't have managed
		// pool. And creating non-write only default pool causes a performance warning.
		if (useShadowBuffer && !(usage & HardwareBuffer::HBU_DISCARDABLE) &&
			!D3D9RenderSystem::isDirectX9Ex())
		{
            useShadowBuffer = false;
            // Also drop any WRITE_ONLY so we can read direct
            if (usage == HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY)
            {
                usage = HardwareBuffer::HBU_DYNAMIC;
            }
            else if (usage == HardwareBuffer::HBU_STATIC_WRITE_ONLY)
            {
                usage = HardwareBuffer::HBU_STATIC;
            }
        }
#endif
		D3D9HardwareIndexBuffer* idx = OGRE_NEW D3D9HardwareIndexBuffer(
			this, itype, numIndexes, usage, false, useShadowBuffer);
		{
                    OGRE_LOCK_MUTEX(mIndexBuffersMutex);
			mIndexBuffers.insert(idx);
		}
		return HardwareIndexBufferSharedPtr(idx);

    }
    //-----------------------------------------------------------------------
    RenderToVertexBufferSharedPtr
        D3D9HardwareBufferManagerBase::createRenderToVertexBuffer()
    {
        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
            "Direct3D9 does not support render to vertex buffer objects",
            "D3D9HardwareBufferManagerBase::createRenderToVertexBuffer");
	}
	//---------------------------------------------------------------------
	HardwareUniformBufferSharedPtr
		D3D9HardwareBufferManagerBase::createUniformBuffer(size_t sizeBytes, HardwareBuffer::Usage usage, bool useShadowBuffer, const String& name)
	{
		OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
				"Uniform buffer not supported in Direct3D 9 RenderSystem.",
				"D3D9HardwareBufferManagerBase::createUniformBuffer");
	}
    //-----------------------------------------------------------------------
	HardwareCounterBufferSharedPtr
    D3D9HardwareBufferManagerBase::createCounterBuffer(size_t sizeBytes,
                                                          HardwareBuffer::Usage usage, bool useShadowBuffer, const String& name)
	{
        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                    "D3D9 does not support atomic counter buffers",
                    "D3D9HardwareBufferManagerBase::createCounterBuffer");
	}
    //-----------------------------------------------------------------------
    VertexDeclaration* D3D9HardwareBufferManagerBase::createVertexDeclarationImpl(void)
    {
        return OGRE_NEW D3D9VertexDeclaration();
    }
    //-----------------------------------------------------------------------
    void D3D9HardwareBufferManagerBase::destroyVertexDeclarationImpl(VertexDeclaration* decl)
    {
        OGRE_DELETE decl;
    }
}
<commit_msg>Fixed: Index & vertex buffer performance issue in Direct3D9Ex<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2013 Torus Knot Software Ltd

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.
-----------------------------------------------------------------------------
*/
#include "OgreD3D9RenderSystem.h"
#include "OgreD3D9HardwareBufferManager.h"
#include "OgreD3D9HardwareVertexBuffer.h"
#include "OgreD3D9HardwareIndexBuffer.h"
#include "OgreD3D9VertexDeclaration.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreException.h"

namespace Ogre {
    //-----------------------------------------------------------------------
    D3D9HardwareBufferManagerBase::D3D9HardwareBufferManagerBase()
    {
    }
    //-----------------------------------------------------------------------
    D3D9HardwareBufferManagerBase::~D3D9HardwareBufferManagerBase()
    {
        destroyAllDeclarations();
        destroyAllBindings();
    }
    //-----------------------------------------------------------------------
    HardwareVertexBufferSharedPtr
    D3D9HardwareBufferManagerBase::
    createVertexBuffer(size_t vertexSize, size_t numVerts, HardwareBuffer::Usage usage,
		bool useShadowBuffer)
    {
		assert (numVerts > 0);
#if OGRE_D3D_MANAGE_BUFFERS
        // Override shadow buffer setting; managed buffers are automatically
        // backed by system memory
        // Don't override shadow buffer if discardable, since then we use
        // unmanaged buffers for speed (avoids write-through overhead)
		// Don't override if we use directX9EX, since then we don't have managed
		// pool. And creating non-write only default pool causes a performance warning.
		if (useShadowBuffer && !(usage & HardwareBuffer::HBU_DISCARDABLE) &&
			!D3D9RenderSystem::isDirectX9Ex())
		{
            useShadowBuffer = false;
            // Also drop any WRITE_ONLY so we can read direct
            if (usage == HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY)
            {
                usage = HardwareBuffer::HBU_DYNAMIC;
            }
            else if (usage == HardwareBuffer::HBU_STATIC_WRITE_ONLY)
            {
                usage = HardwareBuffer::HBU_STATIC;
            }
        }
		//If we have write only buffers in DirectX9Ex we will turn on the discardable flag.
		//Otherwise Ogre will operates in far less framerate
		if (D3D9RenderSystem::isDirectX9Ex() && (usage & HardwareBuffer::HBU_WRITE_ONLY))
		{
			usage = (HardwareBuffer::Usage)
				((unsigned int)usage | (unsigned int)HardwareBuffer::HBU_DISCARDABLE);
		}
#endif
		D3D9HardwareVertexBuffer* vbuf = OGRE_NEW D3D9HardwareVertexBuffer(
			this, vertexSize, numVerts, usage, false, useShadowBuffer);
		{
                    OGRE_LOCK_MUTEX(mVertexBuffersMutex);
			mVertexBuffers.insert(vbuf);
		}
        return HardwareVertexBufferSharedPtr(vbuf);
    }
    //-----------------------------------------------------------------------
	HardwareIndexBufferSharedPtr
    D3D9HardwareBufferManagerBase::
    createIndexBuffer(HardwareIndexBuffer::IndexType itype, size_t numIndexes,
        HardwareBuffer::Usage usage, bool useShadowBuffer)
    {
		assert (numIndexes > 0);
#if OGRE_D3D_MANAGE_BUFFERS
        // Override shadow buffer setting; managed buffers are automatically
        // backed by system memory
		// Don't override shadow buffer if discardable, since then we use
		// unmanaged buffers for speed (avoids write-through overhead)
		// Don't override if we use directX9EX, since then we don't have managed
		// pool. And creating non-write only default pool causes a performance warning.
		if (useShadowBuffer && !(usage & HardwareBuffer::HBU_DISCARDABLE) &&
			!D3D9RenderSystem::isDirectX9Ex())
		{
            useShadowBuffer = false;
            // Also drop any WRITE_ONLY so we can read direct
            if (usage == HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY)
            {
                usage = HardwareBuffer::HBU_DYNAMIC;
            }
            else if (usage == HardwareBuffer::HBU_STATIC_WRITE_ONLY)
            {
                usage = HardwareBuffer::HBU_STATIC;
            }
        }
		//If we have write only buffers in DirectX9Ex we will turn on the discardable flag.
		//Otherwise Ogre will operates in far less framerate
		if (D3D9RenderSystem::isDirectX9Ex() && (usage & HardwareBuffer::HBU_WRITE_ONLY))
		{
			usage = (HardwareBuffer::Usage)
				((unsigned int)usage | (unsigned int)HardwareBuffer::HBU_DISCARDABLE);
		}
#endif
		D3D9HardwareIndexBuffer* idx = OGRE_NEW D3D9HardwareIndexBuffer(
			this, itype, numIndexes, usage, false, useShadowBuffer);
		{
                    OGRE_LOCK_MUTEX(mIndexBuffersMutex);
			mIndexBuffers.insert(idx);
		}
		return HardwareIndexBufferSharedPtr(idx);

    }
    //-----------------------------------------------------------------------
    RenderToVertexBufferSharedPtr
        D3D9HardwareBufferManagerBase::createRenderToVertexBuffer()
    {
        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
            "Direct3D9 does not support render to vertex buffer objects",
            "D3D9HardwareBufferManagerBase::createRenderToVertexBuffer");
	}
	//---------------------------------------------------------------------
	HardwareUniformBufferSharedPtr
		D3D9HardwareBufferManagerBase::createUniformBuffer(size_t sizeBytes, HardwareBuffer::Usage usage, bool useShadowBuffer, const String& name)
	{
		OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
				"Uniform buffer not supported in Direct3D 9 RenderSystem.",
				"D3D9HardwareBufferManagerBase::createUniformBuffer");
	}
    //-----------------------------------------------------------------------
	HardwareCounterBufferSharedPtr
    D3D9HardwareBufferManagerBase::createCounterBuffer(size_t sizeBytes,
                                                          HardwareBuffer::Usage usage, bool useShadowBuffer, const String& name)
	{
        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                    "D3D9 does not support atomic counter buffers",
                    "D3D9HardwareBufferManagerBase::createCounterBuffer");
	}
    //-----------------------------------------------------------------------
    VertexDeclaration* D3D9HardwareBufferManagerBase::createVertexDeclarationImpl(void)
    {
        return OGRE_NEW D3D9VertexDeclaration();
    }
    //-----------------------------------------------------------------------
    void D3D9HardwareBufferManagerBase::destroyVertexDeclarationImpl(VertexDeclaration* decl)
    {
        OGRE_DELETE decl;
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2019 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#ifndef ROSETTASTONE_ENTITY_HPP
#define ROSETTASTONE_ENTITY_HPP

#include <Rosetta/Cards/Card.hpp>
#include <Rosetta/Enchants/AuraEffects.hpp>

#include <map>

namespace RosettaStone
{
class Card;
class Game;
class Player;

//!
//! \brief Abstract entity structure that stores card data.
//!
//! This structure is base structure of all data-holding/action-performing/
//! visible or invisible objects in a RosettaStone.
//! An entity is defined as a collection of properties, called GameTags.
//!
class Entity
{
 public:
    //! Default constructor.
    Entity() = default;

    //! Constructs entity with given \p _owner and \p _card.
    //! \param _owner An owner of the card.
    //! \param _card A reference to the card.
    Entity(Player& _owner, Card& _card);

    //! Destructor.
    virtual ~Entity();

    //! Copy constructor.
    Entity(const Entity& ent);

    //! Move constructor.
    Entity(Entity&& ent) noexcept;

    //! Copy assignment operator.
    Entity& operator=(const Entity& ent);

    //! Move assignment operator.
    Entity& operator=(Entity&& ent) noexcept;

    //! Returns the owner of character.
    //! \return The owner of character.
    Player& GetOwner() const;

    //! Sets the owner of character.
    //! \param owner The owner of character.
    void SetOwner(Player& owner);

    //! Returns the value of game tag.
    //! \param tag The game tag of card.
    //! \return The value of game tag.
    int GetGameTag(GameTag tag) const;

    //! Sets game tag to the card.
    //! \param tag The game tag to indicate ability or condition.
    //! \param value The value to set for game tag.
    virtual void SetGameTag(GameTag tag, int value);

    //! Returns the value of cost.
    //! \return The value of cost.
    int GetCost() const;

    //! Sets the value of cost.
    //! \param cost The value of cost.
    void SetCost(int cost);

    //! Destroys character.
    virtual void Destroy();

    //! Creates entity from the card.
    //! \param player A player to get the card.
    //! \param card A card to draw.
    //! \return A pointer to entity that is allocated dynamically.
    static Entity* GetFromCard(Player& player, Card&& card);

    Card card;
    AuraEffects* auraEffects = nullptr;
    Aura* onGoingEffect = nullptr;

    std::size_t id = 0;
    std::size_t orderOfPlay = 0;

    bool isDestroyed = false;

 protected:
    Player* m_owner = nullptr;

    std::map<GameTag, int> m_gameTags;

 private:
    //! Releases dynamic allocated resources.
    void FreeMemory();
};
}  // namespace RosettaStone

#endif  // ROSETTASTONE_ENTITY_HPP
<commit_msg>feat(card-impl): Add variables 'activatedTrigger', 'appliedEnchantments'<commit_after>// Copyright (c) 2019 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#ifndef ROSETTASTONE_ENTITY_HPP
#define ROSETTASTONE_ENTITY_HPP

#include <Rosetta/Cards/Card.hpp>
#include <Rosetta/Enchants/AuraEffects.hpp>

#include <map>

namespace RosettaStone
{
class Card;
class Enchantment;
class Game;
class Player;

//!
//! \brief Abstract entity structure that stores card data.
//!
//! This structure is base structure of all data-holding/action-performing/
//! visible or invisible objects in a RosettaStone.
//! An entity is defined as a collection of properties, called GameTags.
//!
class Entity
{
 public:
    //! Default constructor.
    Entity() = default;

    //! Constructs entity with given \p _owner and \p _card.
    //! \param _owner An owner of the card.
    //! \param _card A reference to the card.
    Entity(Player& _owner, Card& _card);

    //! Destructor.
    virtual ~Entity();

    //! Copy constructor.
    Entity(const Entity& ent);

    //! Move constructor.
    Entity(Entity&& ent) noexcept;

    //! Copy assignment operator.
    Entity& operator=(const Entity& ent);

    //! Move assignment operator.
    Entity& operator=(Entity&& ent) noexcept;

    //! Returns the owner of character.
    //! \return The owner of character.
    Player& GetOwner() const;

    //! Sets the owner of character.
    //! \param owner The owner of character.
    void SetOwner(Player& owner);

    //! Returns the value of game tag.
    //! \param tag The game tag of card.
    //! \return The value of game tag.
    int GetGameTag(GameTag tag) const;

    //! Sets game tag to the card.
    //! \param tag The game tag to indicate ability or condition.
    //! \param value The value to set for game tag.
    virtual void SetGameTag(GameTag tag, int value);

    //! Returns the value of cost.
    //! \return The value of cost.
    int GetCost() const;

    //! Sets the value of cost.
    //! \param cost The value of cost.
    void SetCost(int cost);

    //! Destroys character.
    virtual void Destroy();

    //! Creates entity from the card.
    //! \param player A player to get the card.
    //! \param card A card to draw.
    //! \return A pointer to entity that is allocated dynamically.
    static Entity* GetFromCard(Player& player, Card&& card);

    Card card;
    AuraEffects* auraEffects = nullptr;
    Aura* onGoingEffect = nullptr;
    Trigger* activatedTrigger = nullptr;
    std::vector<Enchantment*> appliedEnchantments;

    std::size_t id = 0;
    std::size_t orderOfPlay = 0;

    bool isDestroyed = false;

 protected:
    Player* m_owner = nullptr;

    std::map<GameTag, int> m_gameTags;

 private:
    //! Releases dynamic allocated resources.
    void FreeMemory();
};
}  // namespace RosettaStone

#endif  // ROSETTASTONE_ENTITY_HPP
<|endoftext|>


<commit_before>#include <examples/zurg/slave/Heartbeat.h>

#include <examples/zurg/slave/SlaveConfig.h>

#include <examples/zurg/proto/master.pb.h>
#include <muduo/protorpc2/rpc2.pb.h>

#include <muduo/base/FileUtil.h>
#include <muduo/base/Logging.h>
#include <muduo/base/ProcessInfo.h>
#include <muduo/base/Timestamp.h>
#include <muduo/net/EventLoop.h>

namespace zurg
{

void ignoreCallback(const EmptyPtr&)
{
}

// unique_ptr is better
typedef boost::shared_ptr<muduo::FileUtil::SmallFile> SmallFilePtr;

class ProcFs : boost::noncopyable
{
 public:
  typedef std::map<muduo::StringPiece, SmallFilePtr> FileMap;

  // char* to save construction of string.
  int readTo(const char* filename, std::string* out)
  {
    FileMap::iterator it = files_.find(filename);
    if (it == files_.end())
    {
      SmallFilePtr ptr(new muduo::FileUtil::SmallFile(filename));
      it = files_.insert(std::make_pair(filename, ptr)).first;
    }
    assert (it != files_.end());
    int size = 0;
    int err = it->second->readToBuffer(&size);
    LOG_TRACE << filename << " " << err << " " << size;
    if (size > 0)
    {
      out->assign(it->second->buffer(), size);
    }
    return err;
  }

 private:
  FileMap files_;
};
}

extern const char* slave_version;

using namespace zurg;
using namespace muduo;
using namespace muduo::net;

Heartbeat::Heartbeat(muduo::net::EventLoop* loop,
                     const SlaveConfig& config,
                     MasterService_Stub* stub)
  : loop_(loop),
    name_(config.name_),
    port_(config.listenPort_),
    stub_(stub),
    procFs_(new ProcFs),
    beating_(false)
{
  loop_->runEvery(config.heartbeatInterval_, boost::bind(&Heartbeat::onTimer, this));
}

Heartbeat::~Heartbeat()
{
}

void Heartbeat::start()
{
  beating_ = true;
  beat(true);
}

void Heartbeat::stop()
{
  beating_ = false;
}

void Heartbeat::onTimer()
{
  if (beating_)
  {
    beat(false);
  }
}

#define FILL_HB(PROC_FILE, FIELD)               \
  if (procFs_->readTo(PROC_FILE, hb.mutable_##FIELD()) != 0)     \
      hb.clear_##FIELD();

void Heartbeat::beat(bool showStatic)
{
  LOG_DEBUG << (showStatic ? "full" : "");
  SlaveHeartbeat hb;
  hb.set_slave_name(name_);
  if (showStatic)
  {
    hb.set_host_name(ProcessInfo::hostname().c_str());
    if (port_ > 0)
    {
      hb.set_listen_port(port_);
    }
    hb.set_slave_pid(ProcessInfo::pid());
    hb.set_start_time_us(ProcessInfo::startTime().microSecondsSinceEpoch());
    hb.set_slave_version(slave_version);
    FILL_HB("/proc/cpuinfo", cpuinfo);
    FILL_HB("/proc/version", version);
    FILL_HB("/etc/mtab", etc_mtab);
  }
  hb.set_send_time_us(Timestamp::now().microSecondsSinceEpoch());

  FILL_HB("/proc/meminfo", meminfo);
  FILL_HB("/proc/stat", proc_stat);
  FILL_HB("/proc/loadavg", loadavg);
  FILL_HB("/proc/diskstats", diskstats);
  FILL_HB("/proc/net/dev", net_dev);
  FILL_HB("/proc/net/tcp", net_tcp);

  stub_->slaveHeartbeat(hb, ignoreCallback);
}
<commit_msg>strip heartbeat.<commit_after>#include <examples/zurg/slave/Heartbeat.h>

#include <examples/zurg/slave/SlaveConfig.h>

#include <examples/zurg/proto/master.pb.h>
#include <muduo/protorpc2/rpc2.pb.h>

#include <muduo/base/FileUtil.h>
#include <muduo/base/Logging.h>
#include <muduo/base/ProcessInfo.h>
#include <muduo/base/Timestamp.h>
#include <muduo/net/EventLoop.h>

namespace zurg
{

void ignoreCallback(const EmptyPtr&)
{
}

// unique_ptr is better
typedef boost::shared_ptr<muduo::FileUtil::SmallFile> SmallFilePtr;

class ProcFs : boost::noncopyable
{
 public:
  typedef std::map<muduo::StringPiece, SmallFilePtr> FileMap;

  // char* to save construction of string.
  int readTo(const char* filename, std::string* out)
  {
    FileMap::iterator it = files_.find(filename);
    if (it == files_.end())
    {
      SmallFilePtr ptr(new muduo::FileUtil::SmallFile(filename));
      it = files_.insert(std::make_pair(filename, ptr)).first;
    }
    assert (it != files_.end());
    int size = 0;
    int err = it->second->readToBuffer(&size);
    LOG_TRACE << filename << " " << err << " " << size;
    if (size > 0)
    {
      out->assign(it->second->buffer(), size);
    }
    return err;
  }

 private:
  FileMap files_;
};

void strip_cpuinfo(std::string* cpuinfo)
{
  // FIXME:
}

void strip_diskstats(std::string* diskstats)
{
  std::string result;
  result.reserve(diskstats->size());
  muduo::StringPiece zeros(" 0 0 0 0 0 0 0 0 0 0 0\n");

  const char* p = diskstats->c_str();
  const char* nl = NULL;
  while ( (nl = ::strchr(p, '\n')) != NULL)
  {
    int pos = static_cast<int>(nl - p + 1);

    muduo::StringPiece line(p, pos);
    if (line.size() > zeros.size())
    {
      muduo::StringPiece end(line.data() + line.size()-zeros.size(), zeros.size());
      if (end != zeros)
      {
        result.append(line.data(), line.size());
      }
    }

    p += pos;
  }
  assert(p == &*diskstats->end());
  diskstats->swap(result);
}

struct AreBothSpaces
{
  bool operator()(char x, char y) const
  {
    return x == ' ' && y == ' ';
  }
};

void strip_meminfo(std::string* meminfo)
{
  std::string::iterator it = std::unique(meminfo->begin(), meminfo->end(), AreBothSpaces());
  meminfo->erase(it, meminfo->end());
}

void strip_stat(std::string* proc_stat)
{
  const char* intr = ::strstr(proc_stat->c_str(), "\nintr ");
  if (intr != NULL)
  {
    const char* nl = ::strchr(intr + 1, '\n');
    assert(nl != NULL);

    muduo::StringPiece line(intr+1, static_cast<int>(nl-intr-1));
    const char* p = nl;
    while (p[-1] == '0' && p[-2] == ' ')
    {
      p -= 2;
    }

    ++p;
    proc_stat->erase(p - proc_stat->c_str(), nl-p);
  }
}

}

extern const char* slave_version;

using namespace zurg;
using namespace muduo;
using namespace muduo::net;

Heartbeat::Heartbeat(muduo::net::EventLoop* loop,
                     const SlaveConfig& config,
                     MasterService_Stub* stub)
  : loop_(loop),
    name_(config.name_),
    port_(config.listenPort_),
    stub_(stub),
    procFs_(new ProcFs),
    beating_(false)
{
  loop_->runEvery(config.heartbeatInterval_, boost::bind(&Heartbeat::onTimer, this));
}

Heartbeat::~Heartbeat()
{
}

void Heartbeat::start()
{
  beating_ = true;
  beat(true);
}

void Heartbeat::stop()
{
  beating_ = false;
}

void Heartbeat::onTimer()
{
  if (beating_)
  {
    beat(false);
  }
}

#define FILL_HB(PROC_FILE, FIELD)               \
  if (procFs_->readTo(PROC_FILE, hb.mutable_##FIELD()) != 0)     \
      hb.clear_##FIELD();

void Heartbeat::beat(bool showStatic)
{
  LOG_DEBUG << (showStatic ? "full" : "");
  SlaveHeartbeat hb;
  hb.set_slave_name(name_);
  if (showStatic)
  {
    hb.set_host_name(ProcessInfo::hostname().c_str());
    if (port_ > 0)
    {
      hb.set_listen_port(port_);
    }
    hb.set_slave_pid(ProcessInfo::pid());
    hb.set_start_time_us(ProcessInfo::startTime().microSecondsSinceEpoch());
    hb.set_slave_version(slave_version);
    FILL_HB("/proc/cpuinfo", cpuinfo);
    FILL_HB("/proc/version", version);
    FILL_HB("/etc/mtab", etc_mtab);
    strip_cpuinfo(hb.mutable_cpuinfo());
  }
  hb.set_send_time_us(Timestamp::now().microSecondsSinceEpoch());

  FILL_HB("/proc/meminfo", meminfo);
  FILL_HB("/proc/stat", proc_stat);
  FILL_HB("/proc/loadavg", loadavg);
  FILL_HB("/proc/diskstats", diskstats);
  FILL_HB("/proc/net/dev", net_dev);
  FILL_HB("/proc/net/tcp", net_tcp);
  strip_diskstats(hb.mutable_diskstats());
  strip_meminfo(hb.mutable_meminfo());
  strip_stat(hb.mutable_proc_stat());

  stub_->slaveHeartbeat(hb, ignoreCallback);
}
<|endoftext|>


<commit_before>/**************************************************************************************/
/*                                                                                */
/*  Visualization Library                                                             */
/*  http://www.visualizationlibrary.com                                               */
/*                                                                                */
/*  Copyright (c) 2005-2010, Michele Bosi                                             */
/*  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.                                   */
/*                                                                                */
/*  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 OR CONTRIBUTORS 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 "vl/VisualizationLibrary.hpp"
#include "vl/Light.hpp"
#include "vl/GLSL.hpp"

class App_GLSL_Bumpmapping: public BaseDemo
{
public:
  App_GLSL_Bumpmapping()
  {
  }

  void initEvent()
  {
    if (!GLEW_ARB_shading_language_100)
    {
      vl::Log::error("GL_ARB_shading_language_100 not supported.\n");
      vl::Time::sleep(3000);
      openglContext()->quitApplication();
      return;
    }

    BaseDemo::initEvent();

    // generate torus, with normals and uv coords
    vl::ref<vl::Geometry> model = vlut::makeTorus( vl::vec3(0,0,0), 10, 2, 25, 25, 2.0f );

    vl::ref<vl::Light> light = new vl::Light(0);

    vl::ref<vl::Effect> effect = new vl::Effect;
    effect->shader()->setRenderState( light.get() );
    effect->shader()->enable(vl::EN_LIGHTING);
    effect->shader()->enable(vl::EN_DEPTH_TEST);
    effect->shader()->enable(vl::EN_CULL_FACE);
    // effect->shader()->gocPolygonMode()->set(vl::PM_LINE, vl::PM_LINE);
    torus = sceneManager()->tree()->addActor( model.get(), effect.get(), NULL );

    vl::ref<vl::Texture> texture0 = new vl::Texture;
    texture0->setupTexture2D("images/normalmap.jpg");
    effect->shader()->gocTextureUnit(0)->setTexture(texture0.get());
    texture0->getTexParameter()->setAnisotropy(16.0);
    texture0->getTexParameter()->setMagFilter(vl::TPF_LINEAR);
    texture0->getTexParameter()->setMinFilter(vl::TPF_LINEAR_MIPMAP_LINEAR);

    glsl = effect->shader()->gocGLSLProgram();
    glsl->attachShader( new vl::GLSLVertexShader("/glsl/bumpmap.vs") );
    glsl->attachShader( new vl::GLSLFragmentShader("/glsl/bumpmap.fs") );
    vl::ref<vl::Uniform> sampler0 = new vl::Uniform;
    sampler0->setUniform(0);
    sampler0->setName("sampler0");
    glsl->setUniform( sampler0.get() );
    light_obj_space_pos = new vl::Uniform;
    light_obj_space_pos->setName("light_obj_space_pos");
    glsl->setUniform( light_obj_space_pos.get() );

    vl::ref<vl::ArrayFVec3> tangent = new vl::ArrayFVec3;
    vl::ref<vl::ArrayFVec3> bitangent = new vl::ArrayFVec3;
    tangent->resize( model->vertexArray()->size() );
    bitangent->resize( model->vertexArray()->size() );

    VL_CHECK( model->primitives()->at(0)->primitiveType() == vl::PT_QUADS );
    // tessellate torus quads
    std::vector<unsigned int> index_buffer;
    index_buffer.resize( model->primitives()->at(0)->triangleCount() * 3 );
    unsigned int* triangle = &index_buffer.front();
    for( size_t i=0; i<model->primitives()->at(0)->indexCount(); i+=4 )
    {
      size_t a = model->primitives()->at(0)->index(i+0);
      size_t b = model->primitives()->at(0)->index(i+1);
      size_t c = model->primitives()->at(0)->index(i+2);
      size_t d = model->primitives()->at(0)->index(i+3);

      VL_CHECK(a < model->vertexArray()->size());
      VL_CHECK(b < model->vertexArray()->size());
      VL_CHECK(c < model->vertexArray()->size());
      VL_CHECK(d < model->vertexArray()->size());

      triangle[0] = a;
      triangle[1] = b;
      triangle[2] = c;
      triangle += 3;

      triangle[0] = c;
      triangle[1] = d;
      triangle[2] = a;
      triangle += 3;
    }

    ComputeTangentSpace(
      model->vertexArray()->size(),
      (vl::fvec3*)model->vertexArray()->ptr(),
      (vl::fvec3*)model->normalArray()->ptr(),
      (vl::fvec2*)model->texCoordArray(0)->ptr(),
      model->primitives()->at(0)->triangleCount(),
      &index_buffer.front(),
      tangent->begin(),
      bitangent->begin() );

    glsl->linkProgram();
    int tangent_idx = glsl->getAttribLocation("tangent");
    int bitangent_idx = glsl->getAttribLocation("bitangent");
    model->setVertexAttributeArray(tangent_idx, false, false, tangent.get() );
    model->setVertexAttributeArray(bitangent_idx, false, false, bitangent.get() );

    /*
    // visualize tangent space
    vl::ref<vl::ArrayFVec3> ntb_verts = new vl::ArrayFVec3;
    ntb_verts->resize( model->vertexArray()->size() * 6 );

    vl::ref<vl::ArrayFVec4> ntb_cols = new vl::ArrayFVec4;
    ntb_cols->resize( model->vertexArray()->size() * 6 );

    vl::fvec3* verts = (vl::fvec3*)model->vertexArray()->ptr();
    vl::fvec3* norms = (vl::fvec3*)model->normalArray()->ptr();

    float tick_size = 0.5f;

    for( size_t i=0; i<model->vertexArray()->size(); ++i )
    {
      (*ntb_verts)[i*6 + 0] = verts[i];
      (*ntb_verts)[i*6 + 1] = verts[i] + norms[i] * tick_size;
      (*ntb_verts)[i*6 + 2] = verts[i];
      (*ntb_verts)[i*6 + 3] = verts[i] + (*tangent)[i] * tick_size;
      (*ntb_verts)[i*6 + 4] = verts[i];
      (*ntb_verts)[i*6 + 5] = verts[i] + (*bitangent)[i] * tick_size;

      (*ntb_cols)[i*6 + 0] = vlut::red;
      (*ntb_cols)[i*6 + 1] = vlut::red;
      (*ntb_cols)[i*6 + 2] = vlut::green;
      (*ntb_cols)[i*6 + 3] = vlut::green;
      (*ntb_cols)[i*6 + 4] = vlut::blue;
      (*ntb_cols)[i*6 + 5] = vlut::blue;
    }

    vl::ref<vl::Geometry> NTBGeom = new vl::Geometry;
    NTBGeom->setVertexArray( ntb_verts.get() );
    NTBGeom->setColorArray( ntb_cols.get() );
    NTBGeom->primitives()->push_back( new vl::DrawArrays(vl::PT_LINES, 0, ntb_verts->size() ) );
    sceneManager()->tree()->addActor( NTBGeom.get(), effect.get(), NULL );
    */

    // ... testa con oggetto che ruota per i fatti suoi ...
    // ... ripulisci implementazione: passa direttamente la matrice buona.

    // FIXME
    //MAKE UTILITY CLASSES:
    //+ Compute Tangent Space
    //+ Tangent Space Geometry Visualizer (vert, norm, tang, btang, norm_col, tang_col, btang_col, width).
    //  +--> Exposes the effect used and the vertex and color buffer and primitive lump generated.
    //+ Index Buffer Tessellator -> returns a triangle list UINT out of any primitive type.
    //  +--> Convert to triangles utility function.
    //+ Generate & Distribute your bump map.
    //- why do we need to negate the bitangent? =|> ask OpenGL.org
    //- implementa normalization cubemap
    //- GLSL shaders sono in uno stato da fare schifo, non li dovresti ridistribuire cosi
    //- 3DS support fix
    //- Primitives: texture coordinates generation OFF by default.
  }

  // Based on:
  // Lengyel, Eric. Computing Tangent Space Basis Vectors for an Arbitrary Mesh. Terathon Software 3D Graphics Library, 2001.
  // http://www.terathon.com/code/tangent.html
  void ComputeTangentSpace(
    size_t vert_count,
    const vl::fvec3 *vertex,
    const vl::fvec3* normal,
    const vl::fvec2 *texcoord,
    size_t tri_count,
    const unsigned int *triangles,
    vl::fvec3 *tangent,
    vl::fvec3 *bitangent )
  {
      std::vector<vl::fvec3> tan1;
      std::vector<vl::fvec3> tan2;
      tan1.resize(vert_count);
      tan2.resize(vert_count);

      for ( size_t a = 0; a < tri_count; ++a, triangles+=3 )
      {
          unsigned int i1 = triangles[0];
          unsigned int i2 = triangles[1];
          unsigned int i3 = triangles[2];

          VL_CHECK(i1 < vert_count );
          VL_CHECK(i2 < vert_count );
          VL_CHECK(i3 < vert_count );

          const vl::fvec3& v1 = vertex[i1];
          const vl::fvec3& v2 = vertex[i2];
          const vl::fvec3& v3 = vertex[i3];

          const vl::fvec2& w1 = texcoord[i1];
          const vl::fvec2& w2 = texcoord[i2];
          const vl::fvec2& w3 = texcoord[i3];

          float x1 = v2.x() - v1.x();
          float x2 = v3.x() - v1.x();
          float y1 = v2.y() - v1.y();
          float y2 = v3.y() - v1.y();
          float z1 = v2.z() - v1.z();
          float z2 = v3.z() - v1.z();

          float s1 = w2.x() - w1.x();
          float s2 = w3.x() - w1.x();
          float t1 = w2.y() - w1.y();
          float t2 = w3.y() - w1.y();

          float r = 1.0F / (s1 * t2 - s2 * t1);
          vl::fvec3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
          vl::fvec3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);

          tan1[i1] += sdir;
          tan1[i2] += sdir;
          tan1[i3] += sdir;

          tan2[i1] += tdir;
          tan2[i2] += tdir;
          tan2[i3] += tdir;
      }

      for ( size_t a = 0; a < vert_count; a++)
      {
          const vl::fvec3& n = normal[a];
          const vl::fvec3& t = tan1[a];

          // Gram-Schmidt orthogonalize
          tangent[a] = (t - n * vl::dot(n, t)).normalize();

          // fixme???
          // Calculate handedness
          float w = (vl::dot(vl::cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F;

          bitangent[a] = vl::cross( n, tangent[a] ) * w;
      }
  }

  void run()
  {
    vl::fvec3 camera_pos = vl::VisualizationLibrary::rendering()->as<vl::Rendering>()->camera()->inverseViewMatrix().getT();
    vl::mat4 obj_mat;
    if (torus->transform())
      obj_mat = torus->transform()->worldMatrix();
    obj_mat.invert();
    vl::fvec3 camera_pos_obj_space = obj_mat * camera_pos;
    // light_obj_space_pos->setUniform( /*camera_pos_obj_space*/ vl::vec3(100,0,0) );
    light_obj_space_pos->setUniform( camera_pos_obj_space );
    // printf("camera_pos = %f %f %f\n", camera_pos.x(), camera_pos.y(), camera_pos.z() );
    // printf("camera_pos_obj_space = %f %f %f\n", camera_pos_obj_space.x(), camera_pos_obj_space.y(), camera_pos_obj_space.z() );
  }

  void shutdown() {}

protected:
    vl::ref<vl::GLSLProgram> glsl;
    vl::ref<vl::Uniform> light_obj_space_pos;
    vl::ref<vl::Actor> torus;

};

// Have fun!
<commit_msg>bitangent computed in vertex shader<commit_after>/**************************************************************************************/
/*                                                                                */
/*  Visualization Library                                                             */
/*  http://www.visualizationlibrary.com                                               */
/*                                                                                */
/*  Copyright (c) 2005-2010, Michele Bosi                                             */
/*  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.                                   */
/*                                                                                */
/*  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 OR CONTRIBUTORS 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 "vl/VisualizationLibrary.hpp"
#include "vl/Light.hpp"
#include "vl/GLSL.hpp"

class App_GLSL_Bumpmapping: public BaseDemo
{
public:
  App_GLSL_Bumpmapping()
  {
  }

  void initEvent()
  {
    if (!GLEW_ARB_shading_language_100)
    {
      vl::Log::error("GL_ARB_shading_language_100 not supported.\n");
      vl::Time::sleep(3000);
      openglContext()->quitApplication();
      return;
    }

    BaseDemo::initEvent();

    // generate torus, with normals and uv coords
    vl::ref<vl::Geometry> model = vlut::makeTorus( vl::vec3(0,0,0), 10, 2, 25, 25, 2.0f );

    vl::ref<vl::Light> light = new vl::Light(0);

    vl::ref<vl::Effect> effect = new vl::Effect;
    effect->shader()->setRenderState( light.get() );
    effect->shader()->enable(vl::EN_LIGHTING);
    effect->shader()->enable(vl::EN_DEPTH_TEST);
    effect->shader()->enable(vl::EN_CULL_FACE);
    // effect->shader()->gocPolygonMode()->set(vl::PM_LINE, vl::PM_LINE);
    torus = sceneManager()->tree()->addActor( model.get(), effect.get(), NULL );

    vl::ref<vl::Texture> texture0 = new vl::Texture;
    texture0->setupTexture2D("images/normalmap.jpg");
    effect->shader()->gocTextureUnit(0)->setTexture(texture0.get());
    texture0->getTexParameter()->setAnisotropy(16.0);
    texture0->getTexParameter()->setMagFilter(vl::TPF_LINEAR);
    texture0->getTexParameter()->setMinFilter(vl::TPF_LINEAR_MIPMAP_LINEAR);

    glsl = effect->shader()->gocGLSLProgram();
    glsl->attachShader( new vl::GLSLVertexShader("/glsl/bumpmap.vs") );
    glsl->attachShader( new vl::GLSLFragmentShader("/glsl/bumpmap.fs") );
    vl::ref<vl::Uniform> sampler0 = new vl::Uniform;
    sampler0->setUniform(0);
    sampler0->setName("sampler0");
    glsl->setUniform( sampler0.get() );
    light_obj_space_pos = new vl::Uniform;
    light_obj_space_pos->setName("light_obj_space_pos");
    glsl->setUniform( light_obj_space_pos.get() );

    vl::ref<vl::ArrayFVec3> tangent = new vl::ArrayFVec3;
    // vl::ref<vl::ArrayFVec3> bitangent = new vl::ArrayFVec3;
    tangent->resize( model->vertexArray()->size() );
    // bitangent->resize( model->vertexArray()->size() );

    VL_CHECK( model->primitives()->at(0)->primitiveType() == vl::PT_QUADS );
    // tessellate torus quads
    std::vector<unsigned int> index_buffer;
    index_buffer.resize( model->primitives()->at(0)->triangleCount() * 3 );
    unsigned int* triangle = &index_buffer.front();
    for( size_t i=0; i<model->primitives()->at(0)->indexCount(); i+=4 )
    {
      size_t a = model->primitives()->at(0)->index(i+0);
      size_t b = model->primitives()->at(0)->index(i+1);
      size_t c = model->primitives()->at(0)->index(i+2);
      size_t d = model->primitives()->at(0)->index(i+3);

      VL_CHECK(a < model->vertexArray()->size());
      VL_CHECK(b < model->vertexArray()->size());
      VL_CHECK(c < model->vertexArray()->size());
      VL_CHECK(d < model->vertexArray()->size());

      triangle[0] = a;
      triangle[1] = b;
      triangle[2] = c;
      triangle += 3;

      triangle[0] = c;
      triangle[1] = d;
      triangle[2] = a;
      triangle += 3;
    }

    computeTangentSpace(
      model->vertexArray()->size(),
      (vl::fvec3*)model->vertexArray()->ptr(),
      (vl::fvec3*)model->normalArray()->ptr(),
      (vl::fvec2*)model->texCoordArray(0)->ptr(),
      model->primitives()->at(0)->triangleCount(),
      &index_buffer.front(),
      tangent->begin(),
      NULL/*bitangent->begin()*/ );

    glsl->linkProgram();
    int tangent_idx = glsl->getAttribLocation("tangent");
    // int bitangent_idx = glsl->getAttribLocation("bitangent");
    model->setVertexAttributeArray(tangent_idx, false, false, tangent.get() );
    // model->setVertexAttributeArray(bitangent_idx, false, false, bitangent.get() );

    /*
    // visualize tangent space
    vl::ref<vl::ArrayFVec3> ntb_verts = new vl::ArrayFVec3;
    ntb_verts->resize( model->vertexArray()->size() * 6 );

    vl::ref<vl::ArrayFVec4> ntb_cols = new vl::ArrayFVec4;
    ntb_cols->resize( model->vertexArray()->size() * 6 );

    vl::fvec3* verts = (vl::fvec3*)model->vertexArray()->ptr();
    vl::fvec3* norms = (vl::fvec3*)model->normalArray()->ptr();

    float tick_size = 0.5f;

    for( size_t i=0; i<model->vertexArray()->size(); ++i )
    {
      (*ntb_verts)[i*6 + 0] = verts[i];
      (*ntb_verts)[i*6 + 1] = verts[i] + norms[i] * tick_size;
      (*ntb_verts)[i*6 + 2] = verts[i];
      (*ntb_verts)[i*6 + 3] = verts[i] + (*tangent)[i] * tick_size;
      (*ntb_verts)[i*6 + 4] = verts[i];
      (*ntb_verts)[i*6 + 5] = verts[i] + (*bitangent)[i] * tick_size;

      (*ntb_cols)[i*6 + 0] = vlut::red;
      (*ntb_cols)[i*6 + 1] = vlut::red;
      (*ntb_cols)[i*6 + 2] = vlut::green;
      (*ntb_cols)[i*6 + 3] = vlut::green;
      (*ntb_cols)[i*6 + 4] = vlut::blue;
      (*ntb_cols)[i*6 + 5] = vlut::blue;
    }

    vl::ref<vl::Geometry> NTBGeom = new vl::Geometry;
    NTBGeom->setVertexArray( ntb_verts.get() );
    NTBGeom->setColorArray( ntb_cols.get() );
    NTBGeom->primitives()->push_back( new vl::DrawArrays(vl::PT_LINES, 0, ntb_verts->size() ) );
    sceneManager()->tree()->addActor( NTBGeom.get(), effect.get(), NULL );
    */

    // ... testa con oggetto che ruota per i fatti suoi ...
    // ... ripulisci implementazione: passa direttamente la matrice buona.

    // FIXME
    //MAKE UTILITY CLASSES:
    //+ Compute Tangent Space
    //+ Tangent Space Geometry Visualizer (vert, norm, tang, btang, norm_col, tang_col, btang_col, width).
    //  +--> Exposes the effect used and the vertex and color buffer and primitive lump generated.
    //+ Index Buffer Tessellator -> returns a triangle list UINT out of any primitive type.
    //  +--> Convert to triangles utility function.
    //+ Generate & Distribute your bump map.
    //- why do we need to negate the bitangent? =|> ask OpenGL.org
    //- implementa normalization cubemap
    //- GLSL shaders sono in uno stato da fare schifo, non li dovresti ridistribuire cosi
    //- 3DS support fix
    //- Primitives: texture coordinates generation OFF by default.
  }

  // Based on:
  // Lengyel, Eric. Computing Tangent Space Basis Vectors for an Arbitrary Mesh. Terathon Software 3D Graphics Library, 2001.
  // http://www.terathon.com/code/tangent.html
  void computeTangentSpace(
    size_t vert_count,
    const vl::fvec3 *vertex,
    const vl::fvec3* normal,
    const vl::fvec2 *texcoord,
    size_t tri_count,
    const unsigned int *triangles,
    vl::fvec3 *tangent,
    vl::fvec3 *bitangent )
  {
      std::vector<vl::fvec3> tan1;
      std::vector<vl::fvec3> tan2;
      tan1.resize(vert_count);
      tan2.resize(vert_count);

      for ( size_t a = 0; a < tri_count; ++a, triangles+=3 )
      {
          unsigned int i1 = triangles[0];
          unsigned int i2 = triangles[1];
          unsigned int i3 = triangles[2];

          VL_CHECK(i1 < vert_count );
          VL_CHECK(i2 < vert_count );
          VL_CHECK(i3 < vert_count );

          const vl::fvec3& v1 = vertex[i1];
          const vl::fvec3& v2 = vertex[i2];
          const vl::fvec3& v3 = vertex[i3];

          const vl::fvec2& w1 = texcoord[i1];
          const vl::fvec2& w2 = texcoord[i2];
          const vl::fvec2& w3 = texcoord[i3];

          float x1 = v2.x() - v1.x();
          float x2 = v3.x() - v1.x();
          float y1 = v2.y() - v1.y();
          float y2 = v3.y() - v1.y();
          float z1 = v2.z() - v1.z();
          float z2 = v3.z() - v1.z();

          float s1 = w2.x() - w1.x();
          float s2 = w3.x() - w1.x();
          float t1 = w2.y() - w1.y();
          float t2 = w3.y() - w1.y();

          float r = 1.0F / (s1 * t2 - s2 * t1);
          vl::fvec3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
          vl::fvec3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);

          tan1[i1] += sdir;
          tan1[i2] += sdir;
          tan1[i3] += sdir;

          tan2[i1] += tdir;
          tan2[i2] += tdir;
          tan2[i3] += tdir;
      }

      for ( size_t a = 0; a < vert_count; a++)
      {
          const vl::fvec3& n = normal[a];
          const vl::fvec3& t = tan1[a];

          // Gram-Schmidt orthogonalize
          tangent[a] = (t - n * vl::dot(n, t)).normalize();

          if ( bitangent )
          {
            // Calculate handedness
            float w = (vl::dot(vl::cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F;
            bitangent[a] = vl::cross( n, tangent[a] ) * w;
          }
      }
  }

  void run()
  {
    vl::fvec3 camera_pos = vl::VisualizationLibrary::rendering()->as<vl::Rendering>()->camera()->inverseViewMatrix().getT();
    vl::mat4 obj_mat;
    if (torus->transform())
      obj_mat = torus->transform()->worldMatrix();
    obj_mat.invert();
    vl::fvec3 camera_pos_obj_space = obj_mat * camera_pos;
    // light_obj_space_pos->setUniform( /*camera_pos_obj_space*/ vl::vec3(100,0,0) );
    light_obj_space_pos->setUniform( camera_pos_obj_space );
    // printf("camera_pos = %f %f %f\n", camera_pos.x(), camera_pos.y(), camera_pos.z() );
    // printf("camera_pos_obj_space = %f %f %f\n", camera_pos_obj_space.x(), camera_pos_obj_space.y(), camera_pos_obj_space.z() );
  }

  void shutdown() {}

protected:
    vl::ref<vl::GLSLProgram> glsl;
    vl::ref<vl::Uniform> light_obj_space_pos;
    vl::ref<vl::Actor> torus;

};

// Have fun!
<|endoftext|>


<commit_before>//===-- UnreachableBlockElim.cpp - Remove unreachable blocks for codegen --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass is an extremely simple version of the SimplifyCFG pass.  Its sole
// job is to delete LLVM basic blocks that are not reachable from the entry
// node.  To do this, it performs a simple depth first traversal of the CFG,
// then deletes any unvisited nodes.
//
// Note that this pass is really a hack.  In particular, the instruction
// selectors for various targets should just not generate code for unreachable
// blocks.  Until LLVM has a more systematic way of defining instruction
// selectors, however, we cannot really expect them to handle additional
// complexity.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/Constant.h"
#include "llvm/Instructions.h"
#include "llvm/Function.h"
#include "llvm/Pass.h"
#include "llvm/Type.h"
#include "llvm/Analysis/ProfileInfo.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/CFG.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;

namespace {
  class UnreachableBlockElim : public FunctionPass {
    virtual bool runOnFunction(Function &F);
  public:
    static char ID; // Pass identification, replacement for typeid
    UnreachableBlockElim() : FunctionPass(ID) {}

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addPreserved<ProfileInfo>();
    }
  };
}
char UnreachableBlockElim::ID = 0;
INITIALIZE_PASS(UnreachableBlockElim, "unreachableblockelim",
                "Remove unreachable blocks from the CFG", false, false);

FunctionPass *llvm::createUnreachableBlockEliminationPass() {
  return new UnreachableBlockElim();
}

bool UnreachableBlockElim::runOnFunction(Function &F) {
  SmallPtrSet<BasicBlock*, 8> Reachable;

  // Mark all reachable blocks.
  for (df_ext_iterator<Function*, SmallPtrSet<BasicBlock*, 8> > I =
       df_ext_begin(&F, Reachable), E = df_ext_end(&F, Reachable); I != E; ++I)
    /* Mark all reachable blocks */;

  // Loop over all dead blocks, remembering them and deleting all instructions
  // in them.
  std::vector<BasicBlock*> DeadBlocks;
  for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
    if (!Reachable.count(I)) {
      BasicBlock *BB = I;
      DeadBlocks.push_back(BB);
      while (PHINode *PN = dyn_cast<PHINode>(BB->begin())) {
        PN->replaceAllUsesWith(Constant::getNullValue(PN->getType()));
        BB->getInstList().pop_front();
      }
      for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI)
        (*SI)->removePredecessor(BB);
      BB->dropAllReferences();
    }

  // Actually remove the blocks now.
  ProfileInfo *PI = getAnalysisIfAvailable<ProfileInfo>();
  for (unsigned i = 0, e = DeadBlocks.size(); i != e; ++i) {
    if (PI) PI->removeBlock(DeadBlocks[i]);
    DeadBlocks[i]->eraseFromParent();
  }

  return DeadBlocks.size();
}

namespace {
  class UnreachableMachineBlockElim : public MachineFunctionPass {
    virtual bool runOnMachineFunction(MachineFunction &F);
    virtual void getAnalysisUsage(AnalysisUsage &AU) const;
    MachineModuleInfo *MMI;
  public:
    static char ID; // Pass identification, replacement for typeid
    UnreachableMachineBlockElim() : MachineFunctionPass(ID) {}
  };
}
char UnreachableMachineBlockElim::ID = 0;

INITIALIZE_PASS(UnreachableMachineBlockElim, "unreachable-mbb-elimination",
  "Remove unreachable machine basic blocks", false, false);

char &llvm::UnreachableMachineBlockElimID = UnreachableMachineBlockElim::ID;

void UnreachableMachineBlockElim::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addPreserved<MachineLoopInfo>();
  AU.addPreserved<MachineDominatorTree>();
  MachineFunctionPass::getAnalysisUsage(AU);
}

bool UnreachableMachineBlockElim::runOnMachineFunction(MachineFunction &F) {
  SmallPtrSet<MachineBasicBlock*, 8> Reachable;

  MMI = getAnalysisIfAvailable<MachineModuleInfo>();
  MachineDominatorTree *MDT = getAnalysisIfAvailable<MachineDominatorTree>();
  MachineLoopInfo *MLI = getAnalysisIfAvailable<MachineLoopInfo>();

  // Mark all reachable blocks.
  for (df_ext_iterator<MachineFunction*, SmallPtrSet<MachineBasicBlock*, 8> >
       I = df_ext_begin(&F, Reachable), E = df_ext_end(&F, Reachable);
       I != E; ++I)
    /* Mark all reachable blocks */;

  // Loop over all dead blocks, remembering them and deleting all instructions
  // in them.
  std::vector<MachineBasicBlock*> DeadBlocks;
  for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) {
    MachineBasicBlock *BB = I;

    // Test for deadness.
    if (!Reachable.count(BB)) {
      DeadBlocks.push_back(BB);

      // Update dominator and loop info.
      if (MLI) MLI->removeBlock(BB);
      if (MDT && MDT->getNode(BB)) MDT->eraseNode(BB);

      while (BB->succ_begin() != BB->succ_end()) {
        MachineBasicBlock* succ = *BB->succ_begin();

        MachineBasicBlock::iterator start = succ->begin();
        while (start != succ->end() && start->isPHI()) {
          for (unsigned i = start->getNumOperands() - 1; i >= 2; i-=2)
            if (start->getOperand(i).isMBB() &&
                start->getOperand(i).getMBB() == BB) {
              start->RemoveOperand(i);
              start->RemoveOperand(i-1);
            }

          start++;
        }

        BB->removeSuccessor(BB->succ_begin());
      }
    }
  }

  // Actually remove the blocks now.
  for (unsigned i = 0, e = DeadBlocks.size(); i != e; ++i)
    DeadBlocks[i]->eraseFromParent();

  // Cleanup PHI nodes.
  for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) {
    MachineBasicBlock *BB = I;
    // Prune unneeded PHI entries.
    SmallPtrSet<MachineBasicBlock*, 8> preds(BB->pred_begin(),
                                             BB->pred_end());
    MachineBasicBlock::iterator phi = BB->begin();
    while (phi != BB->end() && phi->isPHI()) {
      for (unsigned i = phi->getNumOperands() - 1; i >= 2; i-=2)
        if (!preds.count(phi->getOperand(i).getMBB())) {
          phi->RemoveOperand(i);
          phi->RemoveOperand(i-1);
        }

      if (phi->getNumOperands() == 3) {
        unsigned Input = phi->getOperand(1).getReg();
        unsigned Output = phi->getOperand(0).getReg();

        MachineInstr* temp = phi;
        ++phi;
        temp->eraseFromParent();

        if (Input != Output)
          F.getRegInfo().replaceRegWith(Output, Input);

        continue;
      }

      ++phi;
    }
  }

  F.RenumberBlocks();

  return DeadBlocks.size();
}
<commit_msg>UnreachableBlockElim could incorrectly return false when it had not modified the CFG, but HAD modified some PHI nodes.  Fixes PR8174.<commit_after>//===-- UnreachableBlockElim.cpp - Remove unreachable blocks for codegen --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass is an extremely simple version of the SimplifyCFG pass.  Its sole
// job is to delete LLVM basic blocks that are not reachable from the entry
// node.  To do this, it performs a simple depth first traversal of the CFG,
// then deletes any unvisited nodes.
//
// Note that this pass is really a hack.  In particular, the instruction
// selectors for various targets should just not generate code for unreachable
// blocks.  Until LLVM has a more systematic way of defining instruction
// selectors, however, we cannot really expect them to handle additional
// complexity.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/Constant.h"
#include "llvm/Instructions.h"
#include "llvm/Function.h"
#include "llvm/Pass.h"
#include "llvm/Type.h"
#include "llvm/Analysis/ProfileInfo.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/CFG.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;

namespace {
  class UnreachableBlockElim : public FunctionPass {
    virtual bool runOnFunction(Function &F);
  public:
    static char ID; // Pass identification, replacement for typeid
    UnreachableBlockElim() : FunctionPass(ID) {}

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addPreserved<ProfileInfo>();
    }
  };
}
char UnreachableBlockElim::ID = 0;
INITIALIZE_PASS(UnreachableBlockElim, "unreachableblockelim",
                "Remove unreachable blocks from the CFG", false, false);

FunctionPass *llvm::createUnreachableBlockEliminationPass() {
  return new UnreachableBlockElim();
}

bool UnreachableBlockElim::runOnFunction(Function &F) {
  SmallPtrSet<BasicBlock*, 8> Reachable;

  // Mark all reachable blocks.
  for (df_ext_iterator<Function*, SmallPtrSet<BasicBlock*, 8> > I =
       df_ext_begin(&F, Reachable), E = df_ext_end(&F, Reachable); I != E; ++I)
    /* Mark all reachable blocks */;

  // Loop over all dead blocks, remembering them and deleting all instructions
  // in them.
  std::vector<BasicBlock*> DeadBlocks;
  for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
    if (!Reachable.count(I)) {
      BasicBlock *BB = I;
      DeadBlocks.push_back(BB);
      while (PHINode *PN = dyn_cast<PHINode>(BB->begin())) {
        PN->replaceAllUsesWith(Constant::getNullValue(PN->getType()));
        BB->getInstList().pop_front();
      }
      for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI)
        (*SI)->removePredecessor(BB);
      BB->dropAllReferences();
    }

  // Actually remove the blocks now.
  ProfileInfo *PI = getAnalysisIfAvailable<ProfileInfo>();
  for (unsigned i = 0, e = DeadBlocks.size(); i != e; ++i) {
    if (PI) PI->removeBlock(DeadBlocks[i]);
    DeadBlocks[i]->eraseFromParent();
  }

  return DeadBlocks.size();
}

namespace {
  class UnreachableMachineBlockElim : public MachineFunctionPass {
    virtual bool runOnMachineFunction(MachineFunction &F);
    virtual void getAnalysisUsage(AnalysisUsage &AU) const;
    MachineModuleInfo *MMI;
  public:
    static char ID; // Pass identification, replacement for typeid
    UnreachableMachineBlockElim() : MachineFunctionPass(ID) {}
  };
}
char UnreachableMachineBlockElim::ID = 0;

INITIALIZE_PASS(UnreachableMachineBlockElim, "unreachable-mbb-elimination",
  "Remove unreachable machine basic blocks", false, false);

char &llvm::UnreachableMachineBlockElimID = UnreachableMachineBlockElim::ID;

void UnreachableMachineBlockElim::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addPreserved<MachineLoopInfo>();
  AU.addPreserved<MachineDominatorTree>();
  MachineFunctionPass::getAnalysisUsage(AU);
}

bool UnreachableMachineBlockElim::runOnMachineFunction(MachineFunction &F) {
  SmallPtrSet<MachineBasicBlock*, 8> Reachable;
  bool ModifiedPHI = false;

  MMI = getAnalysisIfAvailable<MachineModuleInfo>();
  MachineDominatorTree *MDT = getAnalysisIfAvailable<MachineDominatorTree>();
  MachineLoopInfo *MLI = getAnalysisIfAvailable<MachineLoopInfo>();

  // Mark all reachable blocks.
  for (df_ext_iterator<MachineFunction*, SmallPtrSet<MachineBasicBlock*, 8> >
       I = df_ext_begin(&F, Reachable), E = df_ext_end(&F, Reachable);
       I != E; ++I)
    /* Mark all reachable blocks */;

  // Loop over all dead blocks, remembering them and deleting all instructions
  // in them.
  std::vector<MachineBasicBlock*> DeadBlocks;
  for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) {
    MachineBasicBlock *BB = I;

    // Test for deadness.
    if (!Reachable.count(BB)) {
      DeadBlocks.push_back(BB);

      // Update dominator and loop info.
      if (MLI) MLI->removeBlock(BB);
      if (MDT && MDT->getNode(BB)) MDT->eraseNode(BB);

      while (BB->succ_begin() != BB->succ_end()) {
        MachineBasicBlock* succ = *BB->succ_begin();

        MachineBasicBlock::iterator start = succ->begin();
        while (start != succ->end() && start->isPHI()) {
          for (unsigned i = start->getNumOperands() - 1; i >= 2; i-=2)
            if (start->getOperand(i).isMBB() &&
                start->getOperand(i).getMBB() == BB) {
              start->RemoveOperand(i);
              start->RemoveOperand(i-1);
            }

          start++;
        }

        BB->removeSuccessor(BB->succ_begin());
      }
    }
  }

  // Actually remove the blocks now.
  for (unsigned i = 0, e = DeadBlocks.size(); i != e; ++i)
    DeadBlocks[i]->eraseFromParent();

  // Cleanup PHI nodes.
  for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) {
    MachineBasicBlock *BB = I;
    // Prune unneeded PHI entries.
    SmallPtrSet<MachineBasicBlock*, 8> preds(BB->pred_begin(),
                                             BB->pred_end());
    MachineBasicBlock::iterator phi = BB->begin();
    while (phi != BB->end() && phi->isPHI()) {
      for (unsigned i = phi->getNumOperands() - 1; i >= 2; i-=2)
        if (!preds.count(phi->getOperand(i).getMBB())) {
          phi->RemoveOperand(i);
          phi->RemoveOperand(i-1);
          ModifiedPHI = true;
        }

      if (phi->getNumOperands() == 3) {
        unsigned Input = phi->getOperand(1).getReg();
        unsigned Output = phi->getOperand(0).getReg();

        MachineInstr* temp = phi;
        ++phi;
        temp->eraseFromParent();
        ModifiedPHI = true;

        if (Input != Output)
          F.getRegInfo().replaceRegWith(Output, Input);

        continue;
      }

      ++phi;
    }
  }

  F.RenumberBlocks();

  return (DeadBlocks.size() || ModifiedPHI);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>

using namespace std;

template <class T>
struct Node
{
	T element;
	Node<T> *left, *right, *pparent;
};

template <class T>
class BST {
private:
	Node<T> *root;
	int count;
public:
	BST();
	~BST();
	void deleteTree(Node<T> *Tree);
	void show(ostream&cout, const Node<T> *Tree) const;
	void add(const T&);
	bool search(const T&, Node<T> *Tree) const;
	void input(const string& file);
	void output(const string& file) const;
	Node<T>* MinElement(Node<T>* min);
	Node<T>* getroot() const;
	int getcount() const;
	Node<T>* del(Node<T>* parent, Node<T>* current, const T& val);
	bool delVal(const T& val);

};

template <typename T> BST<T>::BST() {
	root = NULL;
	count = 0;
}

template <typename T> BST<T>::~BST() {
	deleteTree(root);
}

template <typename T>void BST<T>::deleteTree(Node<T> *Tree) {
	if (!Tree)
		return;
	if (Tree->left) {
		deleteTree(Tree->left);
		Tree->left = nullptr;
	}

	if (Tree->right) {
		deleteTree(Tree->right);
		Tree->right = nullptr;
	}
	delete Tree;
}

template <typename T> void BST<T>::show(ostream&cout, const Node<T> *Tree) const{
	if (Tree != NULL) {

		cout << Tree->element << endl;;
		show(cout, Tree->left);
		show(cout, Tree->right);

	}
}

template <typename T> void BST<T>::add(const T &x) {
	Node<T>* daughter = new Node<T>;
	daughter->element = x;
	daughter->left = daughter->right = nullptr;
	Node<T>* parent = root;
	Node<T>* temp = root;

	while (temp)
	{
		parent = temp;
		if (x < temp->element)
			temp = temp->left;
		else temp = temp->right;
	}

	if (!parent)
		root = daughter;
	else {
		if (x < parent->element)
			parent->left = daughter;
		else
			parent->right = daughter;
	}
	count++;
}

template <typename T> Node<T>* BST<T>::getroot() const {
	return root;
}

template <typename T> int BST<T>::getcount() const {
	return count;
}

template <typename T> void BST<T>::input(const string& file)
ifstream fin(file);
	try
	{
		int temp;
		while (!fin.eof()) throw 1;
		{

			fin >> temp;
			add(temp);

		}
		fin.close();
	}
	catch (int i)
	{
		cout << "This file don't find" << endl;
	}

}

template <typename T> void BST<T>::output(const string& file) const {
	ofstream fout(file);
	show(fout, root);
	fout.close();
}

template <typename T> bool BST<T>::search(const T&x, Node<T>* Tree) const {
	if (Tree == nullptr)
		return false;
	if (x == Tree->element) {
		return true;
	}
	else if (x < Tree->element) {
		search(x, Tree->left);
	}
	else search(x, Tree->right);
}

template <typename T> Node<T>* BST<T>::MinElement(Node<T>* min) {
	if (min->left == nullptr)
		return min;
	else
		return MinElement(min->left);

}

template <typename T>
Node<T>* BST<T>::del(Node<T>* parent, Node<T>* current, const T& val)
{
	if (!current) return false;

	if (current->element == val)
	{
		if (current->left == NULL || current->right == NULL)
		{
			Node<T>* temp = current->left;
			if (current->right) temp = current->right;
			if (parent)
			{
				if (parent->left == current)
				{
					parent->left = temp;
				}
				else
				{
					parent->right = temp;
				}
			}
			else
			{
				this->root = temp;
			}
		}

		else
		{
			Node<T>* validSubs = current->right;
			while (validSubs->left)
			{
				validSubs = validSubs->left;
			}
			T temp = current->element;
			current->element = validSubs->element;
			validSubs->element = temp;
			return del(current, current->right, temp);

		}
		delete current;
		count--;
		return true;
	}

	if (current->element > val)

		return del(current, current->left, val);

	else

		return del(current, current->right, val);
}

template <typename T>
bool BST<T>::delVal(const T& val) {
	return this->del(NULL, root, val);
}
<commit_msg>Create BST.hpp<commit_after>#include <iostream>
#include <fstream>

using namespace std;

template <class T>
struct Node
{
	T element;
	Node<T> *left, *right, *pparent;
};

template <class T>
class BST {
private:
	Node<T> *root;
	int count;
public:
	BST();
	~BST();
	void deleteTree(Node<T> *Tree);
	void show(ostream&cout, const Node<T> *Tree) const;
	void add(const T&);
	bool search(const T&, Node<T> *Tree) const;
	void input(const string& file);
	void output(const string& file) const;
	Node<T>* MinElement(Node<T>* min);
	Node<T>* getroot() const;
	int getcount() const;
	Node<T>* del(Node<T>* parent, Node<T>* current, const T& val);
	bool delVal(const T& val);

};

template <typename T> BST<T>::BST() {
	root = NULL;
	count = 0;
}

template <typename T> BST<T>::~BST() {
	deleteTree(root);
}

template <typename T>void BST<T>::deleteTree(Node<T> *Tree) {
	if (!Tree)
		return;
	if (Tree->left) {
		deleteTree(Tree->left);
		Tree->left = nullptr;
	}

	if (Tree->right) {
		deleteTree(Tree->right);
		Tree->right = nullptr;
	}
	delete Tree;
}

template <typename T> void BST<T>::show(ostream&cout, const Node<T> *Tree) const{
	if (Tree != NULL) {

		cout << Tree->element << endl;;
		show(cout, Tree->left);
		show(cout, Tree->right);

	}
}

template <typename T> void BST<T>::add(const T &x) {
	Node<T>* daughter = new Node<T>;
	daughter->element = x;
	daughter->left = daughter->right = nullptr;
	Node<T>* parent = root;
	Node<T>* temp = root;

	while (temp)
	{
		parent = temp;
		if (x < temp->element)
			temp = temp->left;
		else temp = temp->right;
	}

	if (!parent)
		root = daughter;
	else {
		if (x < parent->element)
			parent->left = daughter;
		else
			parent->right = daughter;
	}
	count++;
}

template <typename T> Node<T>* BST<T>::getroot() const {
	return root;
}

template <typename T> int BST<T>::getcount() const {
	return count;
}

template <typename T> void BST<T>::input(const string& file) {
ifstream fin(file);
	try
	{
		int temp;
		while (!fin.eof()) throw 1;
		{

			fin >> temp;
			add(temp);

		}
		fin.close();
	}
	catch (int i)
	{
		cout << "This file don't find" << endl;
	}

}

template <typename T> void BST<T>::output(const string& file) const {
	ofstream fout(file);
	show(fout, root);
	fout.close();
}

template <typename T> bool BST<T>::search(const T&x, Node<T>* Tree) const {
	if (Tree == nullptr)
		return false;
	if (x == Tree->element) {
		return true;
	}
	else if (x < Tree->element) {
		search(x, Tree->left);
	}
	else search(x, Tree->right);
}

template <typename T> Node<T>* BST<T>::MinElement(Node<T>* min) {
	if (min->left == nullptr)
		return min;
	else
		return MinElement(min->left);

}

template <typename T>
Node<T>* BST<T>::del(Node<T>* parent, Node<T>* current, const T& val)
{
	if (!current) return false;

	if (current->element == val)
	{
		if (current->left == NULL || current->right == NULL)
		{
			Node<T>* temp = current->left;
			if (current->right) temp = current->right;
			if (parent)
			{
				if (parent->left == current)
				{
					parent->left = temp;
				}
				else
				{
					parent->right = temp;
				}
			}
			else
			{
				this->root = temp;
			}
		}

		else
		{
			Node<T>* validSubs = current->right;
			while (validSubs->left)
			{
				validSubs = validSubs->left;
			}
			T temp = current->element;
			current->element = validSubs->element;
			validSubs->element = temp;
			return del(current, current->right, temp);

		}
		delete current;
		count--;
		return true;
	}

	if (current->element > val)

		return del(current, current->left, val);

	else

		return del(current, current->right, val);
}

template <typename T>
bool BST<T>::delVal(const T& val) {
	return this->del(NULL, root, val);
}
<|endoftext|>


<commit_before>#pragma once

#include "cpputil.hh"
#include "ns.hh"
#include "gc.hh"
#include "atomic.hh"
#include "ref.hh"

u64 namehash(const strbuf<DIRSIZ>&);

struct file : public referenced {
  static file *alloc();
  file *dup();
  int stat(struct stat*);
  int read(char *addr, int n);
  ssize_t pread(char *addr, size_t n, off_t offset);
  int write(char *addr, int n);

  enum { FD_NONE, FD_PIPE, FD_INODE, FD_SOCKET } type;

  char readable;
  char writable;

  int socket;
  struct pipe *pipe;
  struct inode *ip;
  u32 off;
  NEW_DELETE_OPS(file);

private:
  file();

protected:
  virtual void onzero() const;
};

// in-core file system types

struct inode : public rcu_freed {
  u32 dev;           // Device number
  u32 inum;          // Inode number
  u32 gen;           // Generation number
  std::atomic<int> ref; // Reference count
  int flags;         // I_BUSY, I_VALID
  std::atomic<int> readbusy;
  struct condvar cv;
  struct spinlock lock;
  char lockname[16];
  std::atomic<xns<strbuf<DIRSIZ>, u32, namehash>*> dir;

  short type;         // copy of disk inode
  short major;
  short minor;
  short nlink;
  u32 size;
  u32 addrs[NDIRECT+1];

  inode();
  ~inode();
  virtual void do_gc() { delete this; }
  NEW_DELETE_OPS(inode)
};

#define I_BUSYR 0x1
#define I_BUSYW 0x2
#define I_VALID 0x4
#define I_FREE 0x8

// device implementations

struct devsw {
  int (*read)(struct inode*, char*, u32, u32);
  int (*write)(struct inode*, char*, u32, u32);
  void (*stat)(struct inode*, struct stat*);
};

extern struct devsw devsw[];

#define CONSOLE  1
#define NETIF    2
#define SAMPLER  3
#define DEVLOCKSTAT 4
<commit_msg>Misc file clean<commit_after>#pragma once

#include "cpputil.hh"
#include "ns.hh"
#include "gc.hh"
#include "atomic.hh"
#include "ref.hh"

u64 namehash(const strbuf<DIRSIZ>&);

struct file : public referenced {
  static file* alloc();
  file*        dup();
  int          stat(struct stat*);
  int          read(char *addr, int n);
  ssize_t      pread(char *addr, size_t n, off_t offset);
  int          write(char *addr, int n);

  enum { FD_NONE, FD_PIPE, FD_INODE, FD_SOCKET } type;

  char readable;
  char writable;

  int socket;
  struct pipe *pipe;
  struct inode *ip;
  u32 off;

private:
  file();
  file& operator=(const file&);
  file(const file& x);
  NEW_DELETE_OPS(file);

protected:
  virtual void onzero() const;
};

// in-core file system types

struct inode : public rcu_freed {
  u32 dev;           // Device number
  u32 inum;          // Inode number
  u32 gen;           // Generation number
  std::atomic<int> ref; // Reference count
  int flags;         // I_BUSY, I_VALID
  std::atomic<int> readbusy;
  struct condvar cv;
  struct spinlock lock;
  char lockname[16];
  std::atomic<xns<strbuf<DIRSIZ>, u32, namehash>*> dir;

  short type;         // copy of disk inode
  short major;
  short minor;
  short nlink;
  u32 size;
  u32 addrs[NDIRECT+1];

  inode();
  ~inode();
  virtual void do_gc() { delete this; }
  NEW_DELETE_OPS(inode)
};

#define I_BUSYR 0x1
#define I_BUSYW 0x2
#define I_VALID 0x4
#define I_FREE 0x8

// device implementations

struct devsw {
  int (*read)(struct inode*, char*, u32, u32);
  int (*write)(struct inode*, char*, u32, u32);
  void (*stat)(struct inode*, struct stat*);
};

extern struct devsw devsw[];

#define CONSOLE  1
#define NETIF    2
#define SAMPLER  3
#define DEVLOCKSTAT 4
<|endoftext|>