Page 2 of 3

Re: Ray casting and tiles

Posted: Wed Feb 21, 2024 10:22 pm
by CuteAlien
Before doing any collisions. createTriangleSelector creates the collision geometery (triangles for your mesh polygons) which is needed for checking collisions later.

Re: Ray casting and tiles

Posted: Wed Feb 21, 2024 10:29 pm
by tBane
done

Code: Select all

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// UPDATE

// CAMERA POSITIONING
cam->setPosition(vector3df(cam_x, cam_y, cam_z));
cam->setTarget(vector3df(cam_x, 30, cam_z+50));

// GET THE MOUSE POSITION
position2d < s32 > mousePos = device->getCursorControl()->getPosition();
cout << "mouse position: " << mousePos.X << ", " << mousePos.Y<<endl;

// TRIANGLE SELECTOR
ITriangleSelector* selector;
for (auto& tile : hexMap->tiles)
{
	selector = smgr->createTriangleSelector(tile->getMesh(), tile);
	tile->setTriangleSelector(selector);
}

// CALCULATE THE RAY TO COLLISION
core::line3d<f32> ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(mousePos, cam);
cout << "ray start: " << ray.start.X << ", " << ray.start.Y << ", " << ray.start.Z << endl;
ray.end.X = 0;
ray.end.Y = -10;
ray.end.Z = 0;
cout << "ray end: " << ray.end.X << ", " << ray.end.Y << ", " << ray.end.Z << endl;

core::vector3df intersection;
core::triangle3df hitTriangle;
scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager();

if (collMan != nullptr)
	cout << "collMan ok "<<endl;
else	
	cout << "collMaan is nullptr "<<endl;


scene::ISceneNode* selectedSceneNode = collMan->getSceneNodeAndCollisionPointFromRay( ray, intersection, hitTriangle);

if (selectedSceneNode != nullptr)
	cout << "collision node position: " << selectedSceneNode->getPosition().X << ", " << selectedSceneNode->getPosition().Y << endl;
else
	cout << "collision node is null\n";

cout << endl;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Re: Ray casting and tiles

Posted: Wed Feb 21, 2024 10:34 pm
by CuteAlien
OK, cool :)

Re: Ray casting and tiles

Posted: Wed Feb 21, 2024 10:36 pm
by tBane
no no. not done yet.
Now I need to add a collision and I have no idea how to do it.

Re: Ray casting and tiles

Posted: Wed Feb 21, 2024 10:46 pm
by CuteAlien
What is colliding and what's the collision supposed to do?

Re: Ray casting and tiles

Posted: Wed Feb 21, 2024 11:01 pm
by tBane
Collision mouse cursor with hexTile and then texture of hexTile changed

Re: Ray casting and tiles

Posted: Wed Feb 21, 2024 11:15 pm
by CuteAlien
Didn't the code you have already return the tile? As in selectedSceneNode should be one of your tiles?
Changing texture is done via the material. You seem to know quite a bit programming, so I guess you'll figure it out. I have to sleep.

Re: Ray casting and tiles

Posted: Wed Feb 21, 2024 11:21 pm
by tBane
no, I'm not good. the collision I wrote doesn't work.

Re: Ray casting and tiles

Posted: Thu Feb 22, 2024 12:14 pm
by CuteAlien
You seem to set ray-end to some other values. Don't do that.

Re: Ray casting and tiles

Posted: Thu Feb 22, 2024 3:00 pm
by tBane
ok, done. I think I'm calculating the ray incorrectly

Code: Select all

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// UPDATE

// CAMERA POSITIONING
cam->setPosition(vector3df(cam_x, cam_y, cam_z));
cam->setTarget(vector3df(cam_x, 30, cam_z+50));

// GET THE MOUSE POSITION
position2d < s32 > mousePos = device->getCursorControl()->getPosition();
cout << "mouse position: " << mousePos.X << ", " << mousePos.Y<<endl;

// TRIANGLE SELECTOR
ITriangleSelector* selector;
for (auto& tile : hexMap->tiles)
{
	selector = smgr->createTriangleSelector(tile->getMesh(), tile);
	tile->setTriangleSelector(selector);
}

// CALCULATE THE RAY TO COLLISION
core::line3d<f32> ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(mousePos, cam);
cout << "ray start: " << ray.start.X << ", " << ray.start.Y << ", " << ray.start.Z << endl;
cout << "ray end: " << ray.end.X << ", " << ray.end.Y << ", " << ray.end.Z << endl;

core::vector3df intersection;
core::triangle3df hitTriangle;
scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager();

if (collMan != nullptr)
	cout << "collMan ok "<<endl;
else	
	cout << "collMaan is nullptr "<<endl;


scene::ISceneNode* selectedSceneNode = collMan->getSceneNodeAndCollisionPointFromRay( ray, intersection, hitTriangle);

if (selectedSceneNode != nullptr)
	cout << "collision node position: " << selectedSceneNode->getPosition().X << ", " << selectedSceneNode->getPosition().Y << endl;
else
	cout << "collision node is null\n";

cout << endl;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Code: Select all

mouse position: 264, 211
ray start: 0, 30, -40
ray end: -1671.13, 902.167, 3000.14
collMan ok
collision node is null

mouse position: 265, 211
ray start: 0, 100, -40
ray end: -1665.15, -1817.04, 2438.17
collMan ok
collision node is null

mouse position: 265, 211
ray start: 0, 100, -40
ray end: -1665.15, -1817.04, 2438.17
collMan ok
collision node is null

Re: Ray casting and tiles

Posted: Thu Feb 22, 2024 3:58 pm
by CuteAlien
Hm, ray looks good to me (if your cursor is in the middle then ray.start should be pretty close to your camera position).

Do you call createTriangleSelector each frame? It should only be set once - after creating the nodes. Thought it should still work (just massive memory leak and slow). Also drop the selector after setTriangleSelector (always needed if you created it with a function starting with name "create" if you don't use the pointer yourself anymore). Again not causing the bug, but memory leak.

tile->getMesh does return your mesh?

Re: Ray casting and tiles

Posted: Thu Feb 22, 2024 4:09 pm
by tBane
ray.start has a value like camera.
ok added selector drop.
yes, tile->getMesh() return the mesh of the hexTile.

now main.cpp :

Code: Select all

int main()
{
	MyEventReceiver receiver;
	// CREATE DEVICE ( OpenGL )
	device = createDevice(EDT_SOFTWARE, dimension2d<u32>(screenWidth, screenHeight), bitsPerPixel, fullscreen, stencilbuffer, vsync, &receiver);

	if (!device)	// if no Device then error
		return 1;

	// GET THE BASIC THINGS
	driver = device->getVideoDriver();	// get the Video Driver
	smgr = device->getSceneManager();	// get the Scene
	GUI = device->getGUIEnvironment();	// get the GUI Manager

	// LOAD THE FONTS
	basicFont = device->getGUIEnvironment()->getBuiltInFont();							// get the Default Font
	boldFont = device->getGUIEnvironment()->getFont("media/fonthaettenschweiler.bmp");	// get the Bold Font

	loadTextures();
	setTheStylesForGUI();
	createGUI();

	// ADD CAMERA
	cam_x = 0;	cam_y = 100;	cam_z = -40;

	ICameraSceneNode* cam = smgr->addCameraSceneNode(0, vector3df(cam_x, 30, cam_z), vector3df(0, 5, 0));
	cam->setTarget(vector3df(cam_x, cam_y, cam_z));
	
	// CURSOR IS HIDDEN
	device->getCursorControl()->setVisible(true);

	// LOAD THE MODEL 
	modelMesh = smgr->getMesh(modelPathfile.c_str());
	if (!modelMesh)
		device->drop();
	
	createHexMap();

	// ADDING TRIANGLE SELECTOR TO MAP
	ITriangleSelector* selector;
	for (auto& tile : hexMap->tiles)
	{
		selector = smgr->createTriangleSelector(tile->getMesh(), tile);
		tile->setTriangleSelector(selector);
		selector->drop();
	}
	
	// MAIN "TW Editor" LOOP 
	while (device->run())
	{
		if (device->isWindowActive())
		{
			
			// EVENTS
			if (receiver.IsKeyDown(irr::KEY_ESCAPE))	// if press ESCAPE then exit
			{
				device->drop();
				return 0;
			}

			if (receiver.IsKeyDown(irr::KEY_KEY_A) || receiver.IsKeyDown(irr::KEY_LEFT))	cam_x -= 1.0f;
			if (receiver.IsKeyDown(irr::KEY_KEY_D) || receiver.IsKeyDown(irr::KEY_RIGHT))	cam_x += 1.0f;
			if (receiver.IsKeyDown(irr::KEY_KEY_W) || receiver.IsKeyDown(irr::KEY_UP))		cam_z += 1.0f;
			if (receiver.IsKeyDown(irr::KEY_KEY_S) || receiver.IsKeyDown(irr::KEY_DOWN))	cam_z -= 1.0f;

			////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			// UPDATE

			// CAMERA POSITIONING
			cam->setPosition(vector3df(cam_x, cam_y, cam_z));
			cam->setTarget(vector3df(cam_x, 30, cam_z+50));

			// GET THE MOUSE POSITION
			position2d < s32 > mousePos = device->getCursorControl()->getPosition();
			cout << "mouse position: " << mousePos.X << ", " << mousePos.Y<<endl;

			// CALCULATE THE RAY TO COLLISION
			core::line3d<f32> ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(mousePos, cam);
			cout << "ray start: " << ray.start.X << ", " << ray.start.Y << ", " << ray.start.Z << endl;
			cout << "ray end: " << ray.end.X << ", " << ray.end.Y << ", " << ray.end.Z << endl;

			// COLLISION
			core::vector3df intersection;
			core::triangle3df hitTriangle;
			scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager();
			
			if (collMan != nullptr)
				cout << "collMan ok "<<endl;
			else	
				cout << "collMaan is nullptr "<<endl;


			scene::ISceneNode* selectedSceneNode = collMan->getSceneNodeAndCollisionPointFromRay( ray, intersection, hitTriangle);

			if (selectedSceneNode != nullptr)
				cout << "collision node position: " << selectedSceneNode->getPosition().X << ", " << selectedSceneNode->getPosition().Z << endl;
			else
				cout << "collision node is null\n";

			cout << endl;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			// RENDER
			driver->beginScene(true, true, SColor(clear_a, clear_r, clear_g, clear_b));														// clear screen
				smgr->drawAll();																												// render scene
				driver->draw2DImage(TWTexture, position2d<s32>(0, screenHeight - 128 - 20), rect<s32>(0, 0, 128, 128));							// render TW Logo
				boldFont->draw(L"TW World Editor v0.1", recti(20, screenHeight - 20, 100, screenHeight), SColor(256, 128, 48, 48), true, true);	// render text on bottom
				GUI->drawAll();																													// render GUI
				position2d<s32> m = device->getCursorControl()->getPosition();																	// render cursor
			driver->endScene();																												// render submit

			// FPS
			int currentFPS = driver->getFPS();
			core::stringw str = L"FPS: ";
			str += currentFPS;
			device->setWindowCaption(str.c_str());
		}
		else
			device->yield();	// if window is inactive not use CPU

	}

	// In the end, delete the Irrlicht device.
	device->drop();
	return 0;
}

Re: Ray casting and tiles

Posted: Thu Feb 22, 2024 4:47 pm
by CuteAlien
I don't see anything wrong. Did you check if it actually goes in the loop with hexMap->tiles? So you don't accidentally have an empty copy of that variable or something like that?

edit: Minor side-note unrelated to your problem: You are not working with opengl, but the simplest software renderer - don't use that one for rendering anything real (it's fine for 2d UI and some simple stuff). Pass EDT_OPENGL in createDevice for using opengl

Re: Ray casting and tiles

Posted: Thu Feb 22, 2024 6:59 pm
by tBane
Everything works. Thank you very much for help :-)

Re: Ray casting and tiles

Posted: Sat Feb 24, 2024 4:25 pm
by tBane
Hi. I have a next problem. I work with this mesh and I would like highlighting hexTiles. I use this but but not work:

Code: Select all

if (selectedSceneNode != nullptr)
{
	vector2di tilePos = globalToHex(selectedSceneNode->getPosition().X, selectedSceneNode->getPosition().Z);
	
	for (auto& t : highlightedHexTiles)
		t->meshBuffer->Material.Lighting = false;

	highlightedHexTiles.clear();
	getNeighbours(highlightedHexTiles, hexMap->getHexTile(tilePos.X, tilePos.Y), brushSize);
	
	for (auto& t : highlightedHexTiles)
		t->meshBuffer->Material.Lighting = true;
}