Jump to content

  • Log In with Google      Sign In   
  • Create Account

TheComet

Member Since 02 Oct 2013
Offline Last Active Yesterday, 04:39 PM

#5188619 O(pow(N,12))

Posted by TheComet on 22 October 2014 - 04:01 PM

#include "main.h"
#include "renderSystem.h"
#include "largeAsteroid.h"

// To future Karl, or anybody who may have the joy of upkeeping this code.
// I am truly sorry.
#define ASTEROID_SIZE 50

AsteroidVoxel::AsteroidVoxel() :
	mExist( false )
{
}

AsteroidVoxelVertex::AsteroidVoxelVertex()
{
	mExist = true;
}

void AsteroidVoxelVertex::setVertex( u32 vertex )
{
	mVertex = vertex;
}

AsteroidVoxelVertex::~AsteroidVoxelVertex()
{
}

AsteroidData::AsteroidData()
{

	//This part is a pain, but initialize the mVoxelData array
	for( s32 x = 0; x < ASTEROID_SIZE; x++ )
	{
		for( s32 y = 0; y < ASTEROID_SIZE; y++ )
		{
			for( s32 z = 0; z < ASTEROID_SIZE; z++ )
			{
				mVoxelData[x][y][z].mExist = false;
			}
		}
	}

}

AsteroidData::~AsteroidData()
{

}

void AsteroidData::genTestShape()
{
	for( s32 x = 2; x < ASTEROID_SIZE - 2 ; x++ )
		for( s32 y = 2; y < ASTEROID_SIZE - 2; y++ )
			for( s32 z = 2; z < ASTEROID_SIZE - 2; z++ )
				mVoxelData[x][y][z].mExist = true;
}

void AsteroidData::generateBaseShape()
{
	// Set up random number generator.
	mt19937 generator;
	generator.seed( gRenderSystem->getOgreRoot()->getTimer()->getMilliseconds() * rand() % 100000 );

	Vec3 center( ASTEROID_SIZE / 2.0f , ASTEROID_SIZE / 2.0f, ASTEROID_SIZE / 2.0f );
	for( s32 x = 0; x < ASTEROID_SIZE; x++ )
		for( s32 y = 0; y < ASTEROID_SIZE; y++ )
			for( s32 z = 0; z < ASTEROID_SIZE; z++ )
				if( ( Vec3( x, y, z ) - center ).LengthSq() < ( ( ASTEROID_SIZE / 2.0f ) * ( ASTEROID_SIZE / 2.0f ) ) )
					mVoxelData[x][y][z].mExist = true;

	//Add craters.
	uniform_int_distribution<s32> craterImpacts( 2, 10 );
	uniform_real_distribution<f32> craterPosition( 0.0f, ASTEROID_SIZE );
	uniform_real_distribution<f32> craterRadius( ASTEROID_SIZE / 8.0f, ASTEROID_SIZE / 4.0f );

	u32 noCraterImpacts = craterImpacts( generator );

	for( u32 i = 0; i < noCraterImpacts; ++i )
	{
		Vec3 origin( craterPosition( generator ), craterPosition( generator ), craterPosition( generator ) );
		f32 lCraterRadius = craterRadius( generator );

		for( u32 x = 0; x < ASTEROID_SIZE; x++ )
			for( u32 y = 0; y < ASTEROID_SIZE; y++ )
				for( u32 z = 0; z < ASTEROID_SIZE; z++ )
					if( ( Vec3( x, y, z ) - origin ).LengthSq() < lCraterRadius * lCraterRadius ) {}
		//mVoxelData[x][y][z].mExist = false;
	}

}

void AsteroidData::generateIndexVertexBuffers()
{
	// Eliminate non-visible voxels
	// Check each of the 6 sides.
	vector<AsteroidVoxelVertex*> mVisibleVoxels;
	AsteroidVoxelVertex* mVisVoxelStructure[ASTEROID_SIZE][ASTEROID_SIZE][ASTEROID_SIZE];

	u32 vertexCount = 0;

	for( s32 x = 0; x < ASTEROID_SIZE; x++ )
	{
		for( s32 y = 0; y < ASTEROID_SIZE; y++ )
		{
			for( s32 z = 0; z < ASTEROID_SIZE; z++ )
			{

				bool canBeSeen = 0;

				if( x == 0 || x == ASTEROID_SIZE - 1 || y == 0 || y == ASTEROID_SIZE - 1 || z == 0 || z == ASTEROID_SIZE - 1 )
					if( mVoxelData[x][y][z].mExist == true )
						canBeSeen = true;

				if( x > 0 )
					if( mVoxelData[x - 1][y][z].mExist == false )
						canBeSeen = true;

				if( y > 0 )
					if( mVoxelData[x][y - 1][z].mExist == false )
						canBeSeen = true;

				if( z > 0 )
					if( mVoxelData[x][y][z - 1].mExist == false )
						canBeSeen = true;

				if( x < ASTEROID_SIZE - 1 )
					if( mVoxelData[x + 1][y][z].mExist == false )
						canBeSeen = true;

				if( y < ASTEROID_SIZE - 1 )
					if( mVoxelData[x][y + 1][z].mExist == false )
						canBeSeen = true;

				if( z < ASTEROID_SIZE - 1 )
					if( mVoxelData[x][y][z + 1].mExist == false )
						canBeSeen = true;

				if( canBeSeen )
				{
					if( mVoxelData[x][y][z].mExist == true )
					{
						// Set vertex
						AsteroidVoxelVertex* vertex = new AsteroidVoxelVertex;
						vertex->setVertex( vertexCount );

						//Add to data structures
						mVisibleVoxels.push_back( vertex );
						mVisVoxelStructure[x][y][z] = vertex;

						// Add to vertex list
						mVertex.push_back( f32( x ) * 100.0 );
						mVertex.push_back( f32( y ) * 100.0 );
						mVertex.push_back( f32( z ) * 100.0 );

						vertexCount++;
					}
					else
					{
						AsteroidVoxelVertex* vertex = new AsteroidVoxelVertex;
						vertex->mExist = false;

						mVisibleVoxels.push_back( vertex );
						mVisVoxelStructure[x][y][z] = vertex;
					}
				}
				else
				{
					AsteroidVoxelVertex* vertex = new AsteroidVoxelVertex;
					vertex->mExist = false;

					mVisibleVoxels.push_back( vertex );
					mVisVoxelStructure[x][y][z] = vertex;
				}
			}
		}
	}

	// Use brute force against the VoxelCloud to generate index.

	for( u32 x = 0; x < ASTEROID_SIZE - 1; x ++ )
	{
		for( u32 y = 0; y < ASTEROID_SIZE - 1; y++ )
		{
			for( u32 z = 0; z < ASTEROID_SIZE - 1; z++ )
			{
				for( u32 basex = x; basex <= x + 1; basex++ )
					for( u32 basey = y; basey <= y + 1; basey++ )
						for( u32 basez = z; basez <= z + 1; basez++ )
							// Find all triangles
							// Find second vertex, then find the next vertex using the second vertex as a starting point
							for( u32 ox = 0; ox <= 1; ox++ )
							{
								for( u32 oy = 0; oy <= 1; oy++ )
								{
									for( u32 oz = 0; oz <= 1; oz++ )
									{
										for( s32 ox1 = -1; ox1 <= 1; ox1++ )
										{
											for( s32 oy1 = - 1; oy1 <= 1; oy1++ )
											{
												for( s32 oz1 = - 1; oz1 <= 1; oz1++ )
												{
													if( basex + ox1 + ox >= x )
														if( basex + ox1 + ox <= x + 1 )
															if( basey + oy1 + oy >= y )
																if( basey + oy1 + oy <= y + 1 )
																	if( basez + oz1 + oz >= z )
																		if( basez + oz1 + oz <= z + 1 )
																			if( basex + ox1 + ox <= x + 1 )
																				if( basey + oy1 + oy <= y + 1 )
																					if( basez + oz + oz1 <= z + 1 )
																						if( basex + ox <= x + 1 )
																							if( basey + oy <= y + 1 )
																								if( basez + oz <= z + 1 )
																									if( mVisVoxelStructure[basex][basey][basez]->mExist == true )
																										if( mVisVoxelStructure[basex + ox][basey + oy][basez + oz]->mExist == true )
																											if( mVisVoxelStructure[basex + ox + ox1][basey + oy + oy1][basez + oz + oz1]->mExist == true )
																												if( mVisVoxelStructure[basex][basey][basez]->mVertex != mVisVoxelStructure[basex + ox][basey + oy][basez + oz]->mVertex )
																													if( mVisVoxelStructure[basex][basey][basez]->mVertex != mVisVoxelStructure[basex + ox][basey + oy][basez + oz]->mVertex )
																														if( mVisVoxelStructure[basex + ox][basey + oy][basez + oz]->mVertex != mVisVoxelStructure[basex + ox + ox1][basey + oy + oy1][basez + oz + oz1]->mVertex )
																														{
																															mIndex.push_back( mVisVoxelStructure[basex + ox + ox1][basey + oy + oy1][basez + oz + oz1]->mVertex );
																															mIndex.push_back( mVisVoxelStructure[basex + ox][basey + oy][basez + oz]->mVertex );
																															mIndex.push_back( mVisVoxelStructure[basex][basey][basez]->mVertex );

																															mIndex.push_back( mVisVoxelStructure[basex + ox + ox1][basey + oy + oy1][basez + oz + oz1]->mVertex );
																															mIndex.push_back( mVisVoxelStructure[basex][basey][basez]->mVertex );
																															mIndex.push_back( mVisVoxelStructure[basex + ox][basey + oy][basez + oz]->mVertex );

																														}

												}
											}
										}
									}
								}
							}

			}
		}
	}

	//Clear up after myself.
	for( auto i = mVisibleVoxels.begin(); i != mVisibleVoxels.end(); ++i )
	{
		delete(*i);
	}

	mVisibleVoxels.empty();

}


////////////////////////////////////////////////////
// Divide between AsteroidData and LargeAsteroid //
////////////////////////////////////////////////////


LargeAsteroid::LargeAsteroid() :
	mMeshData( nullptr ),
	mSceneNode( nullptr )
{

	mMeshData = new AsteroidData;

	mMeshData->generateBaseShape();
	mMeshData->generateIndexVertexBuffers();

	// set up mesh, vertex decl, entity and scene node.
	mMesh = Ogre::MeshManager::getSingleton().createManual( generateName(), "General" );
	mSubMesh = mMesh->createSubMesh();

	mMesh->sharedVertexData = new Ogre::VertexData;
	mMesh->sharedVertexData->vertexCount = mMeshData->mVertex.size();

	mDecl = mMesh->sharedVertexData->vertexDeclaration;

	size_t offset = 0;
	mDecl->addElement( 0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION );
	offset += Ogre::VertexElement::getTypeSize( Ogre::VET_FLOAT3 );

	mVBuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( offset, mMeshData->mVertex.size(), Ogre::HardwareBuffer::HBU_DYNAMIC, false );
	mIBuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( Ogre::HardwareIndexBuffer::IT_32BIT, mMeshData->mIndex.size(), Ogre::HardwareBuffer::HBU_DYNAMIC );

	mMesh->sharedVertexData->vertexBufferBinding->setBinding( 0, mVBuf );
	mSubMesh->indexData->indexBuffer = mIBuf;
	mSubMesh->indexData->indexCount = mMeshData->mIndex.size();
	mSubMesh->indexData->indexStart = 0;

	//lock buffers
	f32* vertices = static_cast<f32*>( mVBuf->lock( Ogre::HardwareBuffer::HBL_DISCARD ) );

	u32 vx = 0;

	for( auto i = mMeshData->mVertex.begin(); i != mMeshData->mVertex.end(); ++i )
	{
		vertices[vx] = (*i);
		vx++;
	}

	u32* indices = static_cast<u32*>( mIBuf->lock( Ogre::HardwareBuffer::HBL_DISCARD ) );

	vx = 0;
	for( auto i = mMeshData->mIndex.begin(); i != mMeshData->mIndex.end(); ++i )
	{
		indices[vx] = (*i);
		vx++;
	}

	//unlock buffers
	mVBuf->unlock();
	mIBuf->unlock();


	mMesh->_setBounds( Ogre::AxisAlignedBox( 0, 0, 0, ASTEROID_SIZE * 100.0f, ASTEROID_SIZE * 100.0f, ASTEROID_SIZE * 100.0f ) );
	mMesh->load();

	mEntity = gRenderSystem->getSceneMgr()->createEntity( generateName(), mMesh );
	mSceneNode = gRenderSystem->getRootSceneNode()->createChildSceneNode();
	mSceneNode->attachObject( mEntity );

	gRenderSystem->getSceneMgr()->setAmbientLight( Ogre::ColourValue( 0.5, 0.5, 0.5f ) );

}

LargeAsteroid::~LargeAsteroid()
{
	gRenderSystem->getSceneMgr()->destroyEntity( mEntity );
	gRenderSystem->getSceneMgr()->destroySceneNode( mSceneNode );

	mMesh.setNull();
	mVBuf.setNull();
	mIBuf.setNull();

	//Free up memory.
	delete mMeshData;


}



#5185556 Funniest line of code ever ?

Posted by TheComet on 07 October 2014 - 09:55 AM

Somewhere in a text editor application I saw this line:

const char* CARROT = "^";



#5184002 Threading question

Posted by TheComet on 30 September 2014 - 01:59 AM

I'm trying to learn more about multithreading and am a little confused.

 

Currently, I'm using Ogre3D and I'm processing my game entities asynchronously. This means each entity is writing to Ogre::SceneNode asynchronously whenever its position changes:

void processMyGameEntity(Entity& e)
{
    Vector3 newPosition = doFancyMovementCode(e);
    e.sceneNode->setPosition(newPosition);
}

// ... elsewhere
void Game::updateGame()
{
    for(auto& entity : m_EntityList)
        this->threadPool.push(processMyGameEntity(entity));
}

I know Ogre3D is using boost.thread in the background for rendering, so it is asynchronously reading from scene nodes, but I'm not synchronising when writing to the scenenodes. Why is this working fine? Is it safe for me to continue doing this?

 

Another question I have: The thread pool I'm using uses std::thread, but Ogre3D is using boost::thread. How do I synchronise objects being shared between the two?




#5179641 And this is why you don't change names to lowercase

Posted by TheComet on 11 September 2014 - 12:10 PM

http://www.penisland.net/




#5172273 Funniest line of code ever ?

Posted by TheComet on 08 August 2014 - 08:15 AM

At work I came across lots of peculiar if-statements that always followed this pattern:

if(statement)
{
    foo();
}else if(!statement)
{
    bar();
}else
{
    fatal_error();
}

They all seemed to originate from a single developer, and apparently he has trust issues with the compiler/hardware.




#5166419 Amusing glitch gallery

Posted by TheComet on 12 July 2014 - 09:22 AM

 

tumblr_n8l3gicoIs1qdlh1io1_400.gif


This isn't normal?

 

This is actual footage of Brazil playing against Germany




#5166364 Amusing glitch gallery

Posted by TheComet on 12 July 2014 - 03:23 AM

tumblr_n8l3gicoIs1qdlh1io1_400.gif




#5165819 c++ function pointers

Posted by TheComet on 09 July 2014 - 09:07 AM

You think this is weird, get into pointer to class methods smile.png

Member function pointers aren't any more weird, they follow the same structure as function pointers after all:

typedef int (*function_type)(int); // function pointer
typedef int (SomeClass::*member_function_type)(int); // member function pointer

The only difference being you need an object or object pointer to call them on:

SomeClass object;
member_function_type member_func = &SomeClass::someMethod;
object.*member_func(25);



#5163826 Boost.Python - Ignoring return types of member functions?

Posted by TheComet on 30 June 2014 - 07:47 AM

I have two unrelated questions.

 

1) Consider the following C++ class and its wrapping code using Boost.Python:

struct Foo
{
    InternalThing* bar(std::string name);
};

BOOST_PYTHON_MODULE(test)
{
    using namespace boost::python;
    class_<Foo>("Foo")
        .def("bar", &Foo::bar)
    ;
}

InternalThing is a class that is not wrapped and has no reason to be exposed, consequently generating a compile error because Boost.Python can't find it.

 

How can I tell Boost.Python to ignore the return type and just assume it to be void?

 

 

2) When I tested the compiled shared object in Python (using PyCharm), I noticed that PyCharm's autocomplete doesn't know about any of the available classes/methods. Is there a way to expose that kind of information to PyCharm, perhaps through a .py stub file?




#5160513 Unworkable project

Posted by TheComet on 14 June 2014 - 10:39 AM

I'd personally hit the "delete" button and blame a system glitch ...

That might actually work if they don't use version control and everyone is gullible enough. Not hard to imagine considering the circumstances, but it's a stupid move.




#5158753 Scott Meyers - The Last Thing D Needs

Posted by TheComet on 06 June 2014 - 12:29 PM

Still watching, but holy cow...He-Man hair biggrin.png

Sorry but I'm not sorry

 

ohgod.jpg

 

(however, I am sorry for reviving a thread that was at the bottom of the board. I hope that's ok)




#5156359 Scott Meyers - The Last Thing D Needs

Posted by TheComet on 27 May 2014 - 04:28 PM

http://www.ustream.tv/recorded/47947981

 

Great talk, I recommend watching it if you have the time.

 

It's a summary of some of the peculiarities found in C++, centered around the topic of how hard standardization is and what is to become of the C++ standard in the future.




#5156251 Physics and Animation (3D)?

Posted by TheComet on 27 May 2014 - 04:23 AM

I've little experience with physics simulation, and was wondering what the best approach is to mixing skeletal animation with physics along with some procedural animation.

 

It occurred to me that animations aren't bound to the physical limitations a ragdoll (for instance) would enforce. That is, an animation can very easily create infinite amounts of energy, which basically ends up destroying any purely physically simulated object on contact. An example of this behaviour can be observed in Skate 3.

 

I'm trying to simulate something like what Nintendogs did, where you can pet an animal with the mouse cursor. I want to support things such as moving an arm into a certain position, then have the pet stay like that, all while having the pet react to other physical objects. On top of that, the pet plays various animations blended together with procedural animation.

 

My approach would have been to use some form of PID controller to generate force inputs for the physics engine, depending on what the skeleton should be doing, and what it actually is doing. This would mean the pet would be a full ragdoll, and the animation would only influence the way it moved.

 

Would this be the best approach? Is there a library that already handles this? Can someone perhaps point me to some useful articles on the subject?




#5155251 Ogre3D Animation Help

Posted by TheComet on 22 May 2014 - 12:57 PM

The solution is below, and turned out to be pretty simple. It will copy a section of one animation (specified by startTime and endTime) into a destination animation, scaling it to take up the length of the destination animation.

 

// ----------------------------------------------------------------------------
void Entity::extractAnimation(Ogre::Animation* source,
                              Ogre::Animation* dest,
                              Ogre::Real startTime,
                              Ogre::Real endTime)
{
    Ogre::Real timeScale = dest->getLength() / (endTime - startTime);
    dest->destroyAllTracks();


    // loop through all animation node tracks in source and copy them to destination
    for(Ogre::Animation::NodeTrackIterator srcNodeTrackIt = source->getNodeTrackIterator();
        srcNodeTrackIt.hasMoreElements()
        ;)
    {
        Ogre::NodeAnimationTrack* srcNodeTrack = srcNodeTrackIt.getNext();
        unsigned short trackHandle = srcNodeTrack->getHandle();
        Ogre::NodeAnimationTrack* destNodeTrack = dest->createNodeTrack(trackHandle);


        // loop through all transforms of current source track and copy them to destination
        // if they are within the time frame specified
        for(unsigned short keyFrameHandle = 0;
            keyFrameHandle != srcNodeTrack->getNumKeyFrames();
            ++keyFrameHandle)
        {
            Ogre::TransformKeyFrame* srcKeyFrame = srcNodeTrack->getNodeKeyFrame(keyFrameHandle);
            if(srcKeyFrame->getTime() < startTime || srcKeyFrame->getTime() > endTime)
                continue;


            Ogre::Real scaledTime = (srcKeyFrame->getTime()-startTime) * timeScale;
            Ogre::TransformKeyFrame* destKeyFrame = destNodeTrack->createNodeKeyFrame(scaledTime);


            destKeyFrame->setTranslate(srcKeyFrame->getTranslate());
            destKeyFrame->setRotation(srcKeyFrame->getRotation());
            destKeyFrame->setScale(srcKeyFrame->getScale());
        }
    }
}

Example usage:

    this->extractAnimation(
            m_OgreEntity->getSkeleton()->getAnimation("Anim_1"),
            m_OgreEntity->getSkeleton()->createAnimation("walk", 0.6f),
            41.0f,  // walk begin frame
            71.0f   // walk end frame
    );


    m_OgreEntity->refreshAvailableAnimationState();
    m_WalkAnimState = m_OgreEntity->getAnimationState("walk");



#5152060 Variadic templates - Deducing member function signature?

Posted by TheComet on 07 May 2014 - 09:38 AM

Hi Juliean,

 

Thanks for the help! You're definitely on the right track. Unfortunately, PARAMS does have to be declared before the function signature, and since PARAMS is of variable length, it must be declared at the very end.

 

I played around with it a little more now and I've found a solution (doesn't quite comply to the original requirements I had, but it's fine too).

 

The template parameters for the class now only contain the listener:

template <class LISTENER_CLASS>
class GenericDispatcher

And I modified the dispatcher function to be:

template <class RET_TYPE, class... PARAMS>
void dispatch(RET_TYPE (LISTENER_CLASS::*func)(PARAMS...), PARAMS... params)
{
    for(auto it = m_Listeners.begin(); it != m_Listeners.end(); ++it)
        (it->second->*func)(params...);
}

If you pass the member function pointer as an argument, it allows the compiler to deduce its signature.

 

The entire code:

#include <iostream>
#include <string>
#include <map>

struct Listener
{
    virtual void doThing(int, int) = 0;
    virtual void doAnotherThing(float) = 0;
};

struct Foo : public Listener
{
    virtual void doThing(int a, int b)
    {
        std::cout << a*b << std::endl;
    }
    virtual void doAnotherThing(float a)
    {
        std::cout << a << std::endl;
    }
};

template <class LISTENER_CLASS>
class GenericDispatcher
{
public:
    void addListener(LISTENER_CLASS* listener, std::string name)
    {
        m_Listeners[name] = listener;
    }

    template <class RET_TYPE, class... PARAMS>
    void dispatch(RET_TYPE (LISTENER_CLASS::*func)(PARAMS...), PARAMS... params)
    {
        for(auto it = m_Listeners.begin(); it != m_Listeners.end(); ++it)
            (it->second->*func)(params...);
    }

private:
    std::map<std::string, LISTENER_CLASS*> m_Listeners;
};

int main()
{
    Foo a, b;
    GenericDispatcher<Listener> dispatcher;
    dispatcher.addListener(&a, "a");
    dispatcher.addListener(&b, "b");
    dispatcher.dispatch(&Listener::doThing, 6, 7);
    dispatcher.dispatch(&Listener::doAnotherThing, 4.32f);
    return 0;
}





PARTNERS