Error running grass node

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Saiyantwin
Posts: 7
Joined: Tue Oct 30, 2007 8:55 pm

Error running grass node

Post by Saiyantwin »

My first post ^^ Hi all.

I want to try some of those cool programs made here on the forums.
I just dont know how to compile them.
I put all the source files from download dir to my project and then replaced my main with his. Errors errors and more bs.

Before you go yelling and telling me to do some tuts, I did do ém all. Its just that I have not worked with external sources before where you have to include several files.

Here is the error:
[/img]http://img103.imageshack.us/my.php?imag ... ionib1.jpg[/img]

And here is the grass node project by bitplane incase u missed it:
http://irrlicht.sourceforge.net/phpBB2/ ... sc&start=0

Any suggestions?


Maybe if I provide som additional info on the problem, someone will get an idea to what the cause of the problem is.

Bitplane uses #include "CGrassPatchSceneNode.h" - where as in the examples i've seen the individual has used <CGrassPatchSceneNode.h>

The difference is clear. <CGrassPatchSceneNode.h> gets the following:
Cannot open include file: 'CGrassPatchSceneNode.h': No such file or directory

"CGrassPatchSceneNode.h" gets me:
10 of these:
main.obj : error LNK2001: unresolved external symbol "public: unsigned int __thiscall irr::scene::CGrassPatchSceneNode::getWindRes(void)" (?getWindRes@CGrassPatchSceneNode@scene@irr@@QAEIXZ)

This might be my limited amount of knowledge talking but maybe <> defines an external .h file and "" is internal... who knows?.

At this point I add the other .cpp either by using #include "CGrassPatchSceneNode.cpp" or adding it as a sourcefile in the project.

And now we are back to crashing the application :(
First-chance exception at 0x100b4ded in Irrlicht.exe: 0xC0000005: Access violation reading location 0x01712570.
Unhandled exception at 0x100b4ded in Irrlicht.exe: 0xC0000005: Access violation reading location 0x01712570.
The program '[1236] Irrlicht.exe: Native' has exited with code 0 (0x0).

A new development is that now I get this:
Debugging information for 'Irrlicht.exe cannot be found or does not match. No symbols loaded.

I mean seriously HOW ****ing hard can it be. Im just trying to compile a program.

Give me a reason not to give up. I was so looking forward to making games but this is seems hopeless.

I spend yesterday trying to get a premade maze script working, no luck. But that doesnt worry me, it was regular c++ and not specificly made for Irrlicht so I moved on and saved that one for later. Later that day I spend several hours getting Alpha to work on a mesh exported from Max.
The problem was that I was getting equal overall transparency on my mesh. Alpha channel wasn't working.
Thought first it was because I used multiple textures on one mesh. Or that maybe I should adjust the alpha level. Maybe the problem was the PNG/TGA.
At last I figured out that it was because I was using the "hello" tut code as foundation - it runs software render. DOH! My point is, I have no problem figuring these Irrlicht related problems out on my own, even though I have to work on it for several hours.
But I can't pinpoint the problem when its something like this. What words do I search for. Do I find a regular C++ manual and start from basics? Not worth it atm. I think. If I just learn how to compile others premade scripts, then I dont see any other problems related to general programming pop up in a long future.

This little thing might help others btw. Noticed some others with same problem during my travel of the forum. Some said that Multiple textures on one mesh was not possible. IT IS. Works wonders for me.

If I'm going down and out of the wonderful world of game making because of some compiler issues I might aswell share my experiences.

Help me please. Don't let this be my last post ;)
Saiyantwin
Posts: 7
Joined: Tue Oct 30, 2007 8:55 pm

Post by Saiyantwin »

Maybe someone could just link me a tutorial on compiling sourcecode.

Or tell me how you would normally do it in steps.

I am using Visual C++ Express 2005 as shown in the picture.

Btw. this is my first post EVER on ANY forum. so please just give me a friendly hello atleast :P

and no its not because im 8 years old, I am 23 - not that it really matters.

I will keep on searching for a solution but dont hesitate to reply so I can get on with the fun stuff.
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

First, you must solemly promise that you intend to use the grass scene node for Good, rather than for Evil, and by Evil, I of course mean trying to write a MMORPG.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Saiyantwin
Posts: 7
Joined: Tue Oct 30, 2007 8:55 pm

Post by Saiyantwin »

Oh I will conquer the world with it, no doubt about it!

First I will make WoW 2 then run for president.

Actually I'm making a FPS.
The scene is a maze with deadly obsticles. Objective is to hunt down the 'pacman' monster to get key and escape.
So I need that grass node BAAD.
Got a crew of 3d artist to make some stuff for me.
I will post more details about the project when I get further in progress.
I will kick MMOPRG ass! :P
Saiyantwin
Posts: 7
Joined: Tue Oct 30, 2007 8:55 pm

Update

Post by Saiyantwin »

Even though non of you aided me in times of need, I found my way around the previous problem. Hurray! Spend ALL day on this one.
But now I have a new problem and this one is more Irrlicht related so maybe you will help me with this one. Thank you very much! :)

http://img116.imageshack.us/my.php?imag ... llywa9.jpg

This code from his sourcecode makes the game crash during startup.
//height = Terrain->getHeight(p.X, p.Z);

I'm not exactly sure why, but I tried someone elses suggestion from the 'grass node' post and switched with this:

f32 ay = TerrainHeightMap->getPixel(x1,z1).getBlue()* Terrain->getScale().Y;
f32 by = TerrainHeightMap->getPixel(x1+1,z1).getBlue()* Terrain->getScale().Y;
f32 cy = TerrainHeightMap->getPixel(x1,z1+1).getBlue()* Terrain->getScale().Y;
f32 dy = TerrainHeightMap->getPixel(x1+1,z1+1).getBlue()* Terrain->getScale().Y;
f32 u = xz.X - (f32)x1;
f32 v2 = xz.Z - (f32)z1;
height = ay*(1.0f-u)*(1.0f-v2) + by*u*(1.0f-v2) + cy*(1.0f-u)*v2 + dy*u*v2;
------------------------------------------------------
Seems to locate the 'Y' coordinate like it should, and I dont see why that has anything to do with the odd effect of grass gone wild. Why does the original code not work.

Another thing, I cannot switch render mode (this also makes the game crash) and even though I use his terrain the grass area is offset by a few hundred X, Y.

Come on guys, I need you on this one. I dont use paypal sorry ;)

Oh yeah and the code (didnt want to include it because it just takes up alot of space but if it helps then why not):

main.cpp

Code: Select all


#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#include "CGrassPatchSceneNode.h"
//#include "CWindGenerator.h"
#include "RealisticWater.h"


#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif

core::array<video::E_MATERIAL_TYPE> modes;
video::ITexture *tex1;
video::ITexture *tex2;

scene::IWindGenerator *wind;

#define width  10
#define height 10
#define total  width*height



class MyEventReceiver : public IEventReceiver
{
public:

    MyEventReceiver(scene::ISceneNode* terrain, scene::CGrassPatchSceneNode** grass)
    {
        // store pointer to terrain so we can change its drawing mode
        Terrain = terrain;
        Grass   = &grass[0];
        mode    = 0;
        tex     = false;
    }

    bool OnEvent(SEvent event)
    {
        // check if user presses the key 'W' or 'D'
        if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
        {
            switch (event.KeyInput.Key)
            {
            case irr::KEY_KEY_W: // switch wire frame mode
                Terrain->setMaterialFlag(video::EMF_WIREFRAME, !Terrain->getMaterial(0).Wireframe);
                return true;
            case irr::KEY_KEY_D: // toggle detail map
                Terrain->setMaterialType(
                    Terrain->getMaterial(0).MaterialType == video::EMT_SOLID ? 
                    video::EMT_DETAIL_MAP : video::EMT_SOLID);
                return true;
            case irr::KEY_KEY_Z: // change draw distance
                for (int n=0; n<total; ++n)
                {
                    if (Grass[n]->getDrawDistance() > GRASS_PATCH_SIZE + 50)
                        Grass[n]->setDrawDistance(Grass[n]->getDrawDistance()- 50.0f);
                }
                return true;
            case irr::KEY_KEY_X: // change draw distance
                for (int n=0; n<total; ++n)
                {
                    Grass[n]->setDrawDistance(Grass[n]->getDrawDistance()+ 50.0f);
                }
                return true;
            case irr::KEY_KEY_C: // change max density
                for (int n=0; n<total; ++n)
                {
                    if (Grass[n]->getMaxDensity() > 55 )
                        Grass[n]->setMaxDensity(Grass[n]->getMaxDensity()- 50);
                }
                return true;
            case irr::KEY_KEY_V: // change max density
                for (int n=0; n<total; ++n)
                {
                    Grass[n]->setMaxDensity(Grass[n]->getMaxDensity()+ 50);
                }
                return true;
            case irr::KEY_KEY_B: // change mode
                if (mode > 0)
                   --mode;
                for (int n=0; n<total; ++n)
                {
                    Grass[n]->setMaterialType(modes[mode]);
                }
                return true;
            case irr::KEY_KEY_N: // change mode
                if (mode < modes.size())
                   ++mode;
                for (int n=0; n<total; ++n)
                {
                    Grass[n]->setMaterialType(modes[mode]);
                }
                return true;
            case irr::KEY_KEY_M: // change mode
                tex = !tex;
                for (int n=0; n<total; ++n)
                {
                    Grass[n]->setMaterialTexture(0,tex ? tex1:tex2);
                }
                return true;
                
            case irr::KEY_KEY_S: // switch terrain invisible
                Terrain->setVisible( !Terrain->isVisible());
                return true;

            case irr::KEY_KEY_K: // less wind
                 if ( wind->getStrength() > 5 )
                    wind->setStrength( wind->getStrength() - 5 );
                 return true;
                 
            case irr::KEY_KEY_L: // more wind
                 if ( wind->getStrength() < 100 )
                    wind->setStrength( wind->getStrength() + 5 );
                 return true;
                 
            case irr::KEY_KEY_O: // blustery wind
                 if ( wind->getRegularity() > 1 )
                    wind->setRegularity( wind->getRegularity() - 1 );
                 return true;
                 
            case irr::KEY_KEY_P: // regular wind
                 if ( wind->getRegularity() < 20 )
                    wind->setRegularity( wind->getRegularity() + 1 );                 
                 return true;

            case irr::KEY_KEY_U: // decrease wind resolution
                if (Grass[0]->getWindRes() > 1)
                {
                    for (int n=0; n<total; ++n)
                    {
                        Grass[n]->setWindRes(Grass[n]->getWindRes() - 1);
                    }
                }
                return true;

            case irr::KEY_KEY_I: // decrease wind resolution
                if (Grass[0]->getWindRes() < 20)
                {
                    for (int n=0; n<total; ++n)
                    {
                        Grass[n]->setWindRes(Grass[n]->getWindRes() + 1);
                    }
                }
                return true;

            case irr::KEY_KEY_T: // decrease refresh delay
                if (Grass[0]->getRefreshDelay() > 4)
                {
                    for (int n=0; n<total; ++n)
                    {
                        Grass[n]->setRefreshDelay(Grass[n]->getRefreshDelay() - 10);
                    }
                }
                return true;

            case irr::KEY_KEY_Y: // increase refresh delay
                if (Grass[0]->getRefreshDelay() < 500)
                {
                    for (int n=0; n<total; ++n)
                    {
                        Grass[n]->setRefreshDelay(Grass[n]->getRefreshDelay() + 10);
                    }
                }
                return true;

            }
        }

        return false;
    }
 
private:
    scene::ISceneNode* Terrain;
    u32 mode;
    bool tex;
    scene::CGrassPatchSceneNode** Grass;
};




int main()
{

	// ask if user would like shadows
		char i;
	printf("Please press 'y' if you want to use realtime shadows.\n");

	std::cin >> i;
	bool shadows = (i == 'y');
		// ask user for driver

	video::E_DRIVER_TYPE driverType;

	printf("Please select the driver you want for this example:\n"\
		" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
		" (d) Software Renderer\n (e) Burning's Software Renderer\n"\
		" (f) NullDevice\n (otherKey) exit\n\n");

	std::cin >> i;

	switch(i)
	{
		case 'a': driverType = video::EDT_DIRECT3D9;break;
		case 'b': driverType = video::EDT_DIRECT3D8;break;
		case 'c': driverType = video::EDT_OPENGL;   break;
		case 'd': driverType = video::EDT_SOFTWARE; break;
		case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
		case 'f': driverType = video::EDT_NULL;     break;
		default: return 1;
	}

	// create device and exit if creation failed

	IrrlichtDevice *device =
		createDevice(driverType, core::dimension2d<s32>(1000, 760),
		32, false, shadows);

	if (device == 0)
		return 1; // could not create selected driver.

	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();
	gui::IGUIEnvironment* env = device->getGUIEnvironment();

	driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);

    // add some help text
    gui::IGUIStaticText* text = env->addStaticText(
        L"Press 'S' to toggle terrain\nPress 'W' to toggle wireframe mode\nPress 'D' to toggle detail map\nZ and X for distance\nC and V for max density\nB and N to change render mode\nM to swap texture\nK and L to change wind strength\nO and P to change wind regularity\nU and I for wind resolution\nT and Y for buffer refresh rate",
        core::rect<s32>(10,320,200,450), true, true, 0, -1, true);


	//Object
	scene::IAnimatedMesh* mesh = smgr->getMesh(
	"3d/objects/milka.b3d");
	
    //node->setAnimationSpeed(30);

	IAnimatedMeshSceneNode* hero = smgr->addAnimatedMeshSceneNode( mesh ); 
	//hero->setMaterialTexture( 0, driver->getTexture("256.gif") );
	hero->setFrameLoop(1*50, 20*50);
	hero->setAnimationSpeed  (15 * 100);
	hero->setScale(vector3df(10,10,10));
		// add shadow
	hero->addShadowVolumeSceneNode();
	smgr->setShadowColor(video::SColor(150,0,0,0));
	hero->setPosition(vector3df(1000,500,1000));
	hero->setMaterialFlag(EMF_LIGHTING, true);
	//node->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL);
	//node->setMaterialFlag(EMF_BACK_FACE_CULLING, false);
	//hero->setRotation(vector3df(270,0,0));
	
	// create light
	scene::ISceneNode* node = 0;
	node = smgr->addLightSceneNode(0, core::vector3df(0,0,0),
		video::SColorf(1.0f, 0.6f, 0.7f, 1.0f), 800.0f);
	scene::ISceneNodeAnimator* anim = 0;
	anim = smgr->createFlyCircleAnimator (core::vector3df(1000,650,1000),250.0f);
	node->addAnimator(anim);
	anim->drop();

	// attach billboard to light

	node = smgr->addBillboardSceneNode(node, core::dimension2d<f32>(50, 50));
	node->setMaterialFlag(video::EMF_LIGHTING, false);
	node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
	node->setMaterialTexture(0, driver->getTexture("particlewhite.bmp"));

	//Camera
	scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS();
	camera->setPosition(core::vector3df(550,550,1000));

    // add terrain scene node
    scene::ITerrainSceneNode* terrain2 = smgr->addTerrainSceneNode("media/terrain-heightmap.bmp");
    video::IImage* heightMap  = driver->createImageFromFile ("media/terrain-heightmap.bmp");  
    video::IImage* textureMap = driver->createImageFromFile ("media/terrain-grasscol.bmp");  
    video::IImage* grassMap   = driver->createImageFromFile ("media/terrain-grassmap.png"); 

    core::vector3df ts(40, 4.0f, 40);
    terrain2->setScale(ts);
    terrain2->setPosition( core::vector3df(0,0,0) );
    
    terrain2->setMaterialFlag(video::EMF_LIGHTING, false);

    terrain2->setMaterialTexture(0, driver->getTexture("media/terrain-texture.jpg"));
    terrain2->setMaterialTexture(1, driver->getTexture("media/detailmap3.jpg")); 
     
    terrain2->setMaterialType(video::EMT_DETAIL_MAP);
   
    terrain2->scaleTexture(1.0f, 20.0f);
/*
RealisticWaterSceneNode* pWater;

pWater = new RealisticWaterSceneNode(smgr, 2100.0f, 2100.0f, driver->getTexture("data/terrain-grassmap.png"),device->getTimer(),core::dimension2di(256,256));
pWater->setPosition(vector3df(1000,500,1000));
pWater->setMaterialFlag(video::EMF_LIGHTING, false);
*/

	   	// create skybox
	driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);


	smgr->addSkyBoxSceneNode(
		driver->getTexture("irrlicht2_up.jpg"),
		driver->getTexture("irrlicht2_dn.jpg"),
		driver->getTexture("irrlicht2_lf.jpg"),
		driver->getTexture("irrlicht2_rt.jpg"),
		driver->getTexture("irrlicht2_ft.jpg"),
		driver->getTexture("irrlicht2_bk.jpg"));

	driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);

    // create triangle selector for the terrain    
    scene::ITriangleSelector* selector
        = smgr->createTerrainTriangleSelector(terrain2, 0);
    terrain2->setTriangleSelector(selector);
    selector->drop(); 

    // create collision response animator and attach it to the camera
    scene::ISceneNodeAnimator* anim2 = smgr->createCollisionResponseAnimator( 
        selector, camera, core::vector3df(60,100,60),
        core::vector3df(0,-3,0), 
        core::vector3df(0,50,0));
    camera->addAnimator(anim2);
    anim2->drop();

    // create event receiver
    scene::CGrassPatchSceneNode *grass[width*height];
    MyEventReceiver receiver(terrain2,&grass[0]);
    device->setEventReceiver(&receiver);

    // create wind...
    wind = scene::createWindGenerator( 30.0f, 3.0f );

	int lastFPS = -1;

    tex1 = driver->getTexture("media/grass.png");
    tex2 = driver->getTexture("media/grass2.bmp");
    driver->makeColorKeyTexture(tex2, core::position2d<s32>(0,0));
  
    //now we add some grass nodes
    for (int x=0; x<width; ++x)
      for (int z=0; z<height; ++z)
      {   
        // add a grass node        
        grass[x*width + z] = new scene::CGrassPatchSceneNode(terrain2, smgr, -1, core::vector3d<s32>(x,0,z), "grass", heightMap, textureMap, grassMap, wind);
        grass[x*width + z]->setMaterialFlag(video::EMF_LIGHTING,false);
        grass[x*width + z]->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL);        
        grass[x*width + z]->setMaterialTexture(0,tex1);
        grass[x*width + z]->drop();
	  }

	while(device->run())
	if (device->isWindowActive())
	{
		driver->beginScene(true, true, SColor(255,100,101,140));

		smgr->drawAll();
		env->drawAll();

		driver->endScene();

		int fps = driver->getFPS();

		if (lastFPS != fps)
		{
		  core::stringw str = L"Irrlicht Engine - SpecialFX example [";
		  str += driver->getName();
		  str += "] FPS:";
		  str += fps;

		  device->setWindowCaption(str.c_str());
		  lastFPS = fps;
		}
	}

		device->drop();

	return 0;
}

And CGrassPatchSceneNode.cpp

Code: Select all

// Grass node by Gaz Davidson 2006
// created from Irrlicht's particle system node by Nikolaus Gebhardt

#include "CGrassPatchSceneNode.h"
#include "CWindGenerator.h"

namespace irr
{
namespace scene
{  
#pragma comment(lib, "Irrlicht.lib")

//! constructor
CGrassPatchSceneNode::CGrassPatchSceneNode(
		ITerrainSceneNode* terrain, ISceneManager* mgr, s32 id, core::vector3d<s32> gridpos,
		char *filepath, video::IImage* heightMap, video::IImage* colourMap,
		video::IImage* grassMap, scene::IWindGenerator *windgen) : 

		 ISceneNode((ITerrainSceneNode*)terrain, mgr, -1),
	   	 DrawDistanceSQ(GRASS_PATCH_SIZE*1.5*GRASS_PATCH_SIZE*1.5),
	   	 MaxDensity(800),
	   	 TerrainHeightMap(heightMap),
	   	 TerrainColourMap(colourMap),
	   	 TerrainGrassMap(grassMap),
	   	 Terrain(terrain),
	   	 WindGen(windgen),
	   	 lastwindtime(0),
	   	 lastdrawcount(0),
	   	 redrawnextloop(true),
	   	 fpsLock(30)
{
	#ifdef _DEBUG
	setDebugName("CGrassPatchSceneNode");
	#endif
 	
	// set position
	setPosition(core::vector3df((f32)(gridpos.X*GRASS_PATCH_SIZE),0 , (f32)(gridpos.Z*GRASS_PATCH_SIZE)));
	
	setWindRes(5);
	
	// set default image count
	setImageCount(core::dimension2d<s32>(4,2));
	
	// create grass
	Create();
}

//! destructor
CGrassPatchSceneNode::~CGrassPatchSceneNode()
{
}

void CGrassPatchSceneNode::setWindRes(u32 newres)
{
	// set size of wind grid
	windGridRes = newres < 2 ? 2 : newres;
	WindGrid.set_used((windGridRes+1)*(windGridRes+1));
	/*for (u32 i=0; i < WindGrid.size(); ++i)
	{
		WindGrid[i] = core::vector2df(0,0);
	}*/
}
u32 CGrassPatchSceneNode::getWindRes() { return windGridRes; }

video::SMaterial&	  CGrassPatchSceneNode::getMaterial(u32 i) { return Material; }
u32					CGrassPatchSceneNode::getMaterialCount() { return 1; }
core::dimension2d<s32> CGrassPatchSceneNode::getImageCount()	{ return imagecount; }
void CGrassPatchSceneNode::setImageCount(core::dimension2d<s32> ic)
{
	imagecount = ic;
	imagesize.Width= 1.0f / f32(imagecount.Width);
	imagesize.Height=1.0f / f32(imagecount.Height);
	
	v1.set_used(imagecount.Width * imagecount.Height);
	v2.set_used(imagecount.Width * imagecount.Height);
	v3.set_used(imagecount.Width * imagecount.Height);
	v4.set_used(imagecount.Width * imagecount.Height);
	
	for (int x=0;x<imagecount.Width; ++x)
	  for (int y=0;y<imagecount.Height; ++y)
	  {
		v1[ (imagecount.Width*y)+x ] = imagesize.Width  *  x;
		v2[ (imagecount.Width*y)+x ] = imagesize.Height * (y+1);
		v3[ (imagecount.Width*y)+x ] = imagesize.Height *  y;
		v4[ (imagecount.Width*y)+x ] = imagesize.Width  * (x+1);
	   }
}
void CGrassPatchSceneNode::setRefreshDelay(u32 ms)   { fpsLock = ms;  }
u32  CGrassPatchSceneNode::getRefreshDelay()		 { return fpsLock; }
void CGrassPatchSceneNode::setDrawDistance(f32 draw) { DrawDistanceSQ = draw*draw; }
f32  CGrassPatchSceneNode::getDrawDistance()		 { return (f32)sqrt(DrawDistanceSQ); }
void CGrassPatchSceneNode::setMaxDensity(u32 max)	{ MaxDensity = max;	}
u32  CGrassPatchSceneNode::getMaxDensity()		   { return MaxDensity;   }

// creates random grass, 
bool CGrassPatchSceneNode::Create() 
{
 srand((100 * gridpos.X) + gridpos.Z); 
 // particle count 
 s32 count = 3000; // lots. we dont need them all
 
 // create them
 Particles.set_used(count);
  
 Box.reset(0,0,0);
 core::matrix4 m;
 m.setRotationDegrees(Terrain->getRotation());
 m.setTranslation(Terrain->getAbsolutePosition());
 m.makeInverse();
 
 for(s32 i=0; i<count; ++i)
 {

	// get random x and z axis
	f32 x = (rand() % (GRASS_PATCH_SIZE*10) ) / 1.0f;
	f32 z = (rand() % (GRASS_PATCH_SIZE*10) ) / 1.0f;
	
	x -= GRASS_PATCH_SIZE/2.0f;
	z -= GRASS_PATCH_SIZE/2.0f;
	
	Particles[i].pos.X = x;
	Particles[i].pos.Z = z;
	
	Particles[i].sprite.Width  = rand() % imagecount.Width;
	
	if (i<30)
	  Particles[i].sprite.Height = 1 *(rand() % imagecount.Height); // usually grass, sometimes a flower
	else
	  Particles[i].sprite.Height = 0;

	m.transformVect(Particles[i].pos);
	
	//				  patch position + particle position - terrain position = position in terrain
	core::vector3df p = getPosition()  + Particles[i].pos; //  - Terrain->getPosition();

	core::dimension2d<f32> size;
/*	core::vector3df xz((p.X - Terrain->getPosition().X)/Terrain->getScale().X, 0.0f,
(p.Z -  Terrain->getPosition().Z)/Terrain->getScale().Z);*/
	core::vector3df xz(p.X/Terrain->getScale().X,0.0f,p.Z/Terrain->getScale().Z);   
	s32 x1 = (s32) floorf( xz.X );
	s32 z1 = (s32) floorf( xz.Z ); 
	
	f32 height;

	// drop blades that are outside the terrain
	if ( x1 < 1 || 
		 z1 < 1 || 
		 x1 > TerrainHeightMap->getDimension().Width - 1 || 
		 z1 > TerrainHeightMap->getDimension().Height - 1 ) 
	{
		 --count; --i;
		 Particles.set_used(count);
		 continue;
	}
		
	// drop blades that aren't so dense
	video::SColor cDensity  = TerrainGrassMap->getPixel(x1,z1);
	if ((u32)(rand() % 255) > cDensity.getAlpha() || cDensity.getAlpha() < 1 )
	{
	   --count; --i;
	   Particles.set_used(count);
	   continue;  
	}
   

f32 ay = TerrainHeightMap->getPixel(x1,z1).getBlue()* Terrain->getScale().Y;
f32 by = TerrainHeightMap->getPixel(x1+1,z1).getBlue()* Terrain->getScale().Y;
f32 cy = TerrainHeightMap->getPixel(x1,z1+1).getBlue()* Terrain->getScale().Y;
f32 dy = TerrainHeightMap->getPixel(x1+1,z1+1).getBlue()* Terrain->getScale().Y;
f32 u = xz.X - (f32)x1;
f32 v2 = xz.Z - (f32)z1;
height = ay*(1.0f-u)*(1.0f-v2) + by*u*(1.0f-v2) + cy*(1.0f-u)*v2 + dy*u*v2;

	//height = 1000;//Terrain->getHeight(p.X, p.Z);

	size = core::dimension2d<f32> ((f32)(rand() % 50 + 20), 100.0f);
   
	size.Height *= (f32)cDensity.getBlue()/200.0f;
	
	Particles[i].flex  = size.Height / 120.0f;
	Particles[i].pos.Y = height + (size.Height*0.5f);

	Particles[i].color	  =  TerrainColourMap->getPixel(x1,z1);
	Particles[i].startColor =  TerrainColourMap->getPixel(x1,z1);  
	
	Box.addInternalPoint(Particles[i].pos);
	   
	f32 rotation   =  (rand() % 3600) / 10.0f;

	core::matrix4 m2;
	m2.setRotationDegrees(core::vector3df(0,rotation,0)) ; //rand() % 20,rotation,rand() % 20));
	core::vector3df dimensions(0.5f * size.Width,
							  -0.5f * size.Height,0);
	m2.rotateVect(dimensions);
	
	core::vector3df h = core::vector3df(dimensions.X,0.0f,dimensions.Z);
	core::vector3df v = core::vector3df(0.0f,dimensions.Y,0.0f);

	Particles[i].points[0] = Particles[i].pos + core::vector3df(dimensions.X,dimensions.Y,dimensions.Z);
	Particles[i].points[1] = Particles[i].pos + core::vector3df(dimensions.X,-dimensions.Y,dimensions.Z);
	Particles[i].points[2] = Particles[i].pos - core::vector3df(dimensions.X,dimensions.Y,dimensions.Z);
	Particles[i].points[3] = Particles[i].pos - core::vector3df(dimensions.X,-dimensions.Y,dimensions.Z);
	/*
	core::vector3d<f32> xz1(Particles[i].points[0].X/Terrain->getScale().X,0.0f,Particles[i].points[0].Z/Terrain->getScale().Z);	
	x1 = (s32) xz1.X;
	z1 = (s32) xz1.Z;
	video::SColor c1 = TerrainHeightMap->getPixel(x1, z1);
	f32 height1 = c1.getBlue()* Terrain->getScale().Y;

	core::vector3d<f32> xz2(Particles[i].points[3].X/Terrain->getScale().X,0.0f,Particles[i].points[3].Z/Terrain->getScale().Z);	
	x1 = (s32) xz2.X - 10;
	z1 = (s32) xz2.Z - 10;
	video::SColor c2 = TerrainHeightMap->getPixel(x1, z1);
	f32 height2 = c2.getBlue()* Terrain->getScale().Y;
		
	Particles[i].points[0].Y = Particles[i].pos.Y + height1;
	Particles[i].points[3].Y = Particles[i].pos.Y + height2; 
	*/

  //  Particles[i].points[0].Y -= 30;
  //  Particles[i].points[3].Y -= 30;
  //  Particles[i].points[1].Y += 30;
  //  Particles[i].points[2].Y += 30;

 }

 return true;
 
}

//! pre render
void CGrassPatchSceneNode::OnRegisterSceneNode()
{ 
	if (IsVisible)
	{
		if (Particles.size() != 0)
		{   
			core::vector3df campos = SceneManager->getActiveCamera()->getPosition();
			if ( (Box.getCenter() + getPosition()).getDistanceFromSQ(campos) < DrawDistanceSQ*1.5  )
			{
			   SceneManager->registerNodeForRendering(this);
			   ISceneNode::OnRegisterSceneNode();
			}
		}
	}
}

void CGrassPatchSceneNode::OnAnimate(u32 timeMs)
{

	//only change the grass if so many ms have passed since the last time we did it
	// at 0 = 140fps, at 30 = 320fps, at 3000 = 370fps. woot!
	if (lastwindtime < timeMs - fpsLock)
	{
		lastwindtime   = timeMs;
		redrawnextloop = true;
		
		// populate wind grid
		f32 dist =(Box.getCenter() + getPosition()).getDistanceFromSQ(SceneManager->getActiveCamera()->getPosition()) + 1;
	  
		if ( WindGen && dist < DrawDistanceSQ*1.5)
		  for (u32 x=0; x<windGridRes+1; ++x)
			for (u32 z=0; z<windGridRes+1; ++z)
			  WindGrid[x*windGridRes + z] = //core::vector2df(0,0);
				 WindGen->getWind(core::vector3df(
									   ( (f32)(gridpos.X*GRASS_PATCH_SIZE) + (f32)x*((f32)GRASS_PATCH_SIZE/(f32)windGridRes) - (GRASS_PATCH_SIZE/2.0f) ), 
									   0.0f,
									   ( (f32)(gridpos.X*GRASS_PATCH_SIZE) + (f32)x*((f32)GRASS_PATCH_SIZE/(f32)windGridRes) - (GRASS_PATCH_SIZE/2.0f) )),
								  timeMs);
	}
	else
	{
		redrawnextloop = false;
	}
	
	ISceneNode::OnAnimate(timeMs);
}

//! render
void CGrassPatchSceneNode::render()
{
	video::IVideoDriver* driver = SceneManager->getVideoDriver();
	ICameraSceneNode* camera = SceneManager->getActiveCamera();

	if (!camera || !driver)
		return;
   
	if (!redrawnextloop)
	{	
		// just draw the old buffer
		driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);	
		driver->setMaterial(Material);
		driver->drawIndexedTriangleList(Vertices.pointer(), lastdrawcount*4,
			Indices.pointer(), lastdrawcount*4);
	}
	else
	{
		// reallocate arrays, if they are too small
		reallocateBuffers();

		core::vector3df campos = camera->getAbsolutePosition();
		core::aabbox3d<f32> cbox = camera->getViewFrustum()->getBoundingBox();

		core::vector3df pos = getPosition();
		u32 drawcount=0;
		u32 max = (Particles.size() < MaxDensity) ? Particles.size() : MaxDensity;
		
		// in far boxes we dont loop so deep
		// 175 to 255 fps 
		f32 d = getPosition().getDistanceFromSQ(campos) / (f32)(GRASS_PATCH_SIZE*GRASS_PATCH_SIZE);
		if (d > 1.0)
		{
		  //printf("max = %d, %d\n", max, (int)(max/d));
		  max = u32(f32(max)/d) ; 
		}
		
		// i likes teh oldenpointer
		f32 *v1p = &v1[0];
		f32 *v2p = &v2[0];
		f32 *v3p = &v3[0];
		f32 *v4p = &v4[0];

		// make the matrix outside the main loop
		core::matrix4 m; 
		
		// create particle vertex data
		for (u32 i=0; i< max; ++i)
		{
			
			s32 idx = drawcount*4;
			SGrassParticle& particle = Particles[i];
			core::vector3df gpos = particle.pos + pos;
			
			// bounding box check: 150fps to 175fps
			if ( !cbox.isPointInside(gpos) )
			   continue;
			
			// distance checks: 145fps to 175fps
			f32 dist = campos.getDistanceFromSQ(gpos);
			
			if (dist > DrawDistanceSQ)  // too far
			{
			   continue;
			} 
			else if (dist > DrawDistanceSQ * 0.5) // if we're fading in
			{
			   f32 i1 = f32(i)/f32(max);
			   f32 i2 = (dist/DrawDistanceSQ)/2;
			   
			   if (particle.sprite.Height) // first row is boring grass, the rest doesnt fade
			   {
				  //particle.color = video::SColor(255,255,255,255);			   
			   }
			   else
			   {
				  if ( i1 < i2)
				  {
					 continue;
				  }
				  else
				  {
					 // fade this particle
					 s32 c = s32(255.0f-f32(i2/i1)*255.0f);
				  }
			   }
			}	
			else  
			{
			   // particle.color = video::SColor(255,255,255,255);
			}
					  
			//
			// wind
			// 

			s32 igridsize = GRASS_PATCH_SIZE/(windGridRes-1);
			s32 ihalfres  = (windGridRes-1)/2;
			
			// get wind modifier from wind grid
			u32 xgrid = u32((particle.pos.X/(f32)igridsize) +(f32)ihalfres);
			u32 zgrid = u32((particle.pos.Z/(f32)igridsize) +(f32)ihalfres);

			// get fraction to next grid pos
			f32 xnext = particle.pos.X/((f32)GRASS_PATCH_SIZE/(f32)windGridRes)+ (windGridRes/2.0f) - xgrid;
			f32 znext = particle.pos.Z/((f32)GRASS_PATCH_SIZE/(f32)windGridRes)+ (windGridRes/2.0f) - zgrid;			   

			// get wind positions
			core::vector2df wind1  = WindGrid[ xgrid   * windGridRes   +zgrid];
			core::vector2df wind2  = WindGrid[(xgrid+1)* windGridRes   +zgrid];
			core::vector2df wind3  = WindGrid[ xgrid   *(windGridRes+1)+zgrid];
			core::vector2df wind4  = WindGrid[(xgrid+1)*(windGridRes+1)+zgrid];
			core::vector2df wind2d = wind1*(1.0f-xnext)*(1.0f-znext) + 
									 wind2*xnext*(1.0f-znext) + 
									 wind3*(1.0f-xnext)*znext + 
									 wind4*xnext*znext;		 
			// flexibility of this grass strand
			wind2d *= particle.flex;
			// convert to 3d vector
			core::vector3df wind(wind2d.X,0.0f,wind2d.Y);


			// blade colour change along Y axis	   
			video::SColor gcol(	   particle.color.getAlpha(),
							   (s32) (particle.color.getRed()  *0.8f),
							   (s32) (particle.color.getGreen()*0.8f),
							   (s32) (particle.color.getBlue() *0.8f) );
		
	 
			Vertices[0+idx].Pos = particle.points[0]; //particle.pos + core::vector3df(dimensions.X,dimensions.Y,dimensions.Z);
			Vertices[0+idx].Color = gcol; // particle.color;
			//Vertices[0+idx].Normal = ??
	
			Vertices[1+idx].Pos = particle.points[1] + wind; //particle.pos + core::vector3df(dimensions.X,-dimensions.Y,dimensions.Z) + wind;
			Vertices[1+idx].Color = particle.color;
			//Vertices[1+idx].Normal = ??
	
			Vertices[2+idx].Pos = particle.points[2] + wind; //particle.pos - core::vector3df(dimensions.X,dimensions.Y,dimensions.Z) + wind;
			Vertices[2+idx].Color = particle.color;
			//Vertices[2+idx].Normal = ??
	 
			Vertices[3+idx].Pos = particle.points[3]; //particle.pos - core::vector3df(dimensions.X,-dimensions.Y,dimensions.Z);
			Vertices[3+idx].Color = gcol ; //particle.color;
			//Vertices[3+idx].Normal = ??			
			
			//printf("%f, %f, %f, %f\n",v1p[particle.sprite.Width],v2p[particle.sprite.Height],v3p[particle.sprite.Height],v4p[particle.sprite.Width]);
			
			
			s32 arrpos = (imagecount.Width*particle.sprite.Height)+particle.sprite.Width;
			
			// set tcoords
			Vertices[0+idx].TCoords.set(v1p[arrpos], v2p[arrpos] );
			Vertices[1+idx].TCoords.set(v1p[arrpos], v3p[arrpos] );
			Vertices[2+idx].TCoords.set(v4p[arrpos], v3p[arrpos] );
			Vertices[3+idx].TCoords.set(v4p[arrpos], v2p[arrpos] );
			
			drawcount++;
		}
		driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);	
	
		driver->setMaterial(Material);
	
		driver->drawIndexedTriangleList(Vertices.pointer(), drawcount*4,
			Indices.pointer(), drawcount*4);
   		lastdrawcount = drawcount;
	}

	// for debug purposes only:
	if (DebugDataVisible)
	{
		driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
		video::SMaterial m;
		m.Lighting = false;
		driver->setMaterial(m);
		driver->draw3DBox(Box, video::SColor(0,255,255,255));
		core::aabbox3d<f32> b2;
		b2.reset(core::vector3df(0,0,0));

		b2.addInternalPoint(Box.MaxEdge*0.01f);
		driver->draw3DBox(b2, video::SColor(0,255,255,255));
	}
}


//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CGrassPatchSceneNode::getBoundingBox() const
{
	return Box;
}

void CGrassPatchSceneNode::reallocateBuffers()
{
	if (Particles.size() * 4 > Vertices.size() ||
		Particles.size() * 6 > Indices.size())
	{
		s32 oldSize = Vertices.size();
		Vertices.set_used(Particles.size() * 4);

		u32 i;

		// fill remaining vertices
		for (i=oldSize; i<Vertices.size(); i+=4)
		{
			Vertices[0+i].Normal = core::vector3df(0,1,0);
			Vertices[1+i].Normal = core::vector3df(0,1,0);
			Vertices[2+i].Normal = core::vector3df(0,1,0);
			Vertices[3+i].Normal = core::vector3df(0,1,0);
		}

		// fill remaining indices
		s32 oldIdxSize = Indices.size();
		s32 oldvertices = oldSize;
		Indices.set_used(Particles.size() * 12);
		
		for (i=oldIdxSize; i<Indices.size(); i+=12)
		{
			Indices[0+i] = 0+oldvertices;
			Indices[1+i] = 2+oldvertices;
			Indices[2+i] = 1+oldvertices;
			Indices[3+i] = 0+oldvertices;
			Indices[4+i] = 3+oldvertices;
			Indices[5+i] = 2+oldvertices;

			Indices[6+i] = 1+oldvertices;
			Indices[7+i] = 2+oldvertices;
			Indices[8+i] = 0+oldvertices;
			Indices[9+i] = 2+oldvertices;
			Indices[10+i] = 3+oldvertices;
			Indices[11+i] = 0+oldvertices;
			
			oldvertices += 4;
		}
	}
}


} // end namespace scene
} // end namespace irr


Saiyantwin
Posts: 7
Joined: Tue Oct 30, 2007 8:55 pm

Sorry

Post by Saiyantwin »

I dont mean to bump this post its just the best way to update you on my current status.

--> I tried to use bitplane's original sourcefiles again and this time with no crash. Wierd to say the least. But the crazy grass is still there.
So now im back to using height = Terrain->getHeight(p.X, p.Z);
I hope you get what im saying :)

LOL! My mistake, it was still running off my edited files. This **** makes me want to pull my hair and make it look like the grass...
Post Reply