collision in normal projection and orthographic projection

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
joy
Posts: 124
Joined: Tue Apr 27, 2004 9:15 am
Location: Germany

collision in normal projection and orthographic projection

Post by joy »

Hi,
same old annoying issue. But I am getting closer and for that I need your help again.
I still need a drag and drop function for meshes in an orthographic projection. That means I still need a correct collision detection. As I posted in the bug forum the function getSceneNodeFromScreenCoordinatesBB does not work for me. Now I tried to get closer to the basics. Therefore I use the functions getRayFromScreenCoordinates and getCollisionPoint. And guess what? It works like charm in the normal projection view. Then I tried the same in the orthographic view. And it works not correctly. I am pretty sure that there goes something wrong in one of the functions ignoring the orthographic matrix. But I have no clues where the bug is and how to fix the problem.

Any help or ideas? Should I post some code?

Thanks alot
joy
Posts: 124
Joined: Tue Apr 27, 2004 9:15 am
Location: Germany

Post by joy »

:?
May be some code will help? try this yourself. I used saigumis tutorial orthogonal again.

Code: Select all

#include <irrlicht.h>
#include <windows.h>
#include <winbase.h>
#include <stdio.h>

int main(){
	
	irr::IrrlichtDevice *device = irr::createDevice(irr::video::EDT_DIRECTX9, irr::core::dimension2d<irr::s32>(512, 384), 16, false, false, 0);
	device->getFileSystem()->addZipFileArchive("Debug/lb.zip",true,true);
	device->getFileSystem()->addZipFileArchive("Release/lb.zip",true,true);

                device->setWindowCaption(L"Orthogonal Demo");

	irr::video::IVideoDriver* driver = device->getVideoDriver();
	irr::scene::ISceneManager* smgr = device->getSceneManager();

	irr::scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0,irr::core::vector3df(1.0f, 1.0f, 1.0f),irr::core::vector3df(0,0,0));
	irr::core::matrix4 MyMatrix;
	MyMatrix.buildProjectionMatrixOrthoLH(16.0f,12.0f,3.5f,-3.5f);




Try this line to set the orthographic view! to see the difference and correct detection comment out this line!
	camera->setProjectionMatrix(MyMatrix);



irr::scene::IAnimatedMesh* MyMesh = smgr->getMesh("tile_3.ms3d");
	irr::scene::ISceneNode* marker = smgr->addAnimatedMeshSceneNode(MyMesh,0,-1,irr::core::vector3df(1.0f,0.0f,-1.0f),irr::core::vector3df(0.0f,0.0f,0.0f));
	marker->setMaterialTexture(0, driver->getTexture("dummy.bmp"));

    irr::core::position2d<irr::s32> mouse;
    int MouseX = 0;
    int MouseY = 0;
	while(device->run()) {

        irr::scene::IMesh* mesh = MyMesh->getMesh(0);
        irr::scene::ITriangleSelector* pSelector = smgr->createOctTreeTriangleSelector(mesh, marker, 1);
        marker->setTriangleSelector(pSelector);
        irr::core::triangle3df colTri; 
        irr::core::vector3df colPoint; 
        irr::scene::ISceneCollisionManager* pSCollMan = smgr->getSceneCollisionManager();
        irr::core::position2d<irr::s32> mouse = device->getCursorControl()->getPosition();	    
        MouseX=mouse.X;
        MouseY=mouse.Y;
        irr::core::line3d<irr::f32> line =smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(irr::core::position2d<irr::s32>(MouseX,MouseY),camera);; 
        


        bool col =pSCollMan -> getCollisionPoint(line, pSelector, colPoint, colTri);
        char setLast[10] = "       ";
        if (col == true)
        {
            marker->setVisible(false);
            sprintf( setLast, "SetLast" );
        }
        char setSel[10] = "";
        if (col == false)
        {
            marker->setVisible(true); 
             sprintf( setSel, "SetSel" );
        }
        char outStr[128];
        int count = 0;
        sprintf( outStr, "%d:  %s    %s\n", count++, setLast, setSel );
        OutputDebugString( outStr );
        pSelector->drop();

		driver->beginScene(true, true, irr::video::SColor(0,100,100,100));
		smgr->drawAll();
		driver->endScene();
	}

	device->drop();
	return 0;
}
You would really help me!
Guest

Post by Guest »

joy,

you say nodepicking works charming in perspective projection view,
I can confirm this, as I use similar code.

Code: Select all

line3d<irr::f32> line =smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(irr::core::position2d<irr::s32>(MouseX,MouseY),camera);
Maybe:
vector3d<irr::f32> line.end
has to be transformed be the changed projection matrix using:
matrix4::transformVect( line.end, line.end );

before calling:
pSCollMan -> getCollisionPoint(line, pSelector, colPoint, colTri);

If this doesn't work try to transform camera position also:
matrix4::transformVect( line.start, line.start);
matrix4::transformVect( line.end, line.end );
pSCollMan -> ...

anyone?
joy
Posts: 124
Joined: Tue Apr 27, 2004 9:15 am
Location: Germany

Post by joy »

That was actually a great idea.... but it didn't work. I transform the line with the orthographic matrix but the result was worse. The camera is already transformed as I set this line:

camera->setProjectionMatrix(MyMatrix);

But I guess I have to transform something like that, but I can't think of anything else but the line to transform.

Anyone?
Thulsa Doom
Posts: 63
Joined: Thu Aug 05, 2004 9:40 am
Location: Germany

Post by Thulsa Doom »

Hi joy,
sorry 4 not loggin in, the last post was mine 8) .

Wrote this just from the scratch using your base.
Made some minor mods. Have no compiler ATM.

This sould give us a hint where the line points to.
(syntax errors possible)

Code: Select all


include <irrlicht.h> 
#include <windows.h> 
#include <winbase.h> 
#include <stdio.h> 

int main(){ 
    
   irr::IrrlichtDevice *device = irr::createDevice(irr::video::EDT_DIRECTX9, irr::core::dimension2d<irr::s32>(512, 384), 16, false, false, 0); 
   device->getFileSystem()->addZipFileArchive("Debug/lb.zip",true,true); 
   device->getFileSystem()->addZipFileArchive("Release/lb.zip",true,true); 

                device->setWindowCaption(L"Orthogonal Demo"); 

   irr::video::IVideoDriver* driver = device->getVideoDriver(); 
   irr::scene::ISceneManager* smgr = device->getSceneManager(); 

   irr::scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0,irr::core::vector3df(1.0f, 1.0f, 1.0f),irr::core::vector3df(0,0,0)); 
   irr::core::matrix4 MyMatrix; 
   MyMatrix.buildProjectionMatrixOrthoLH(16.0f,12.0f,3.5f,-3.5f); 

   irr::scene::IAnimatedMesh* 
   	MyMesh = smgr->getMesh("tile_3.ms3d"); 
   irr::scene::ISceneNode* 
   	marker = smgr->addAnimatedMeshSceneNode(MyMesh,0,-1,irr::core::vector3df(1.0f,0.0f,-1.0f),irr::core::vector3df(0.0f,0.0f,0.0f)); 
   marker->setMaterialTexture(0, driver->getTexture("dummy.bmp")); 
   
//---------
   irr::scene::IBillboardSceneNode*  
   	pointer = smgr->addBillboardSceneNode(0, core::dimension2d<f32>(50, 50));
   pointer->setMaterialFlag(video::EMF_LIGHTING, false);
   pointer->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
   pointer->setMaterialTexture(0, driver->getTexture("../../media/particlewhite.bmp"));
   irr::core::vector3d<f32>& 
   	pos = new irr::core::vector3df(0,0,0);
//--------- 

   irr::scene::IMesh* 
   	mesh = MyMesh->getMesh(0); 
   irr::scene::ITriangleSelector* 
   	pSelector = smgr->createOctTreeTriangleSelector(mesh, marker, 1); 
   marker->setTriangleSelector(pSelector); 
   pSelector->drop();
   irr::scene::ISceneCollisionManager* 
   	pSCollMan = smgr->getSceneCollisionManager(); 
   irr::core::triangle3df colTri; 
   irr::core::vector3df colPoint; 
   	
//Try this line to set the orthographic view! to see the difference and correct detection comment out this line! 
   camera->setProjectionMatrix(MyMatrix); 

   while(device->run()) { 
   	
        irr::core::position2d<irr::s32> 
        	mouse = device->getCursorControl()->getPosition();       
        irr::core::line3d<irr::f32> 
        	line = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(irr::core::position2d<irr::s32>(mouse.X,mouse.Y),camera);
 
        bool col = pSCollMan->getCollisionPoint(line, pSelector, colPoint, colTri); 
//---------
	pos = (irr::core::vector3d<f32>) line->getMiddle();
	pointer->setPosition(pos);
//---------
        char setLast[10] = "       "; 
        if (col == true) 
	{ 
		marker->setVisible(false); 
		sprintf( setLast, "SetLast" ); 
        } 
        char setSel[10] = ""; 
        if (col == false) 
        { 
		marker->setVisible(true); 
		sprintf( setSel, "SetSel" ); 
        } 
        char outStr[128]; 
        int count = 0; 
        sprintf( outStr, "%d:  %s    %s\n", count++, setLast, setSel ); 
        OutputDebugString( outStr ); 

        driver->beginScene(true, true, irr::video::SColor(0,100,100,100)); 
        smgr->drawAll(); 
        driver->endScene(); 
   } 

   device->drop(); 
   return 0; 
} 

joy
Posts: 124
Joined: Tue Apr 27, 2004 9:15 am
Location: Germany

Post by joy »

Hi Thulsa Doom, thank your for helping me!!

I inserted your code from above and I have a billbordscene node as the background now, but how should I see now, where the line points to? Sorry for beeing so blind and unknowing!
Thulsa Doom
Posts: 63
Joined: Thu Aug 05, 2004 9:40 am
Location: Germany

Post by Thulsa Doom »

joy,
no problem.
(I would like to have an orthogonal-view option in my game if its possible :wink: .)
What I expected is the billboard as background at the actual cursor position in normal projection.

Code: Select all

   pos = (irr::core::vector3d<f32>) line->getMiddle(); 
   pointer->setPosition(pos); 
If this is the case, we can tell now if the line.start/line.end position wether or not depend on the projection matrix. If billboard does stay underlying cursor while changing projection, and thats uncomfortable: the line (billboard indicator) even crosses the mesh without notifiing a collision (bool col=true) in orthogonal projection, we have a problem. BTW have u tryied different mesh formats?
I will check source maybe Ill find another hint.
joy
Posts: 124
Joined: Tue Apr 27, 2004 9:15 am
Location: Germany

Post by joy »

Ok now I got it. Well it is definitly the orthographic view. But there are a lot of huge differences between using the normal projection matrix and the orthographic matrix.

1. difference:
in the projection view, when I just don't set the orthographic view with that: camera->setProjectionMatrix(MyMatrix);
and I don't try to transform the line with the orthographic matrix then the Billboard node is a tiny tiny point directly clipped on the tip of the mouse pointer.
When I set the orthographic view (with or without transforming the line) the Billboard node is huge. it fills the whole background so that I still see the "light middle" but it is not clipped to the mouse pointer.

2. difference:
in the projection view, the billboard node moves with the mousepointer as expected.
in the orthographic view the node follows the mouspointer too, but not as far. when I additionally transform the line it still follows but less then before.

I am surprised that the bbnode in the projection view is a lot smaller as in the orthographic view while the mesh is bigger as in the orthographic view. That doesn't make a lot of sense to me. That the bbnode is not following right I would think that the mousepointer should be transform or recalculate some way....
Guest

Post by Guest »

I see,

the reason for the apparent contrarily behaviour of the sizes of bbnode and mesh is with the utmost probability that the mesh camera distance is constant in both projections and the - pointer->setPosition(line->getMiddle()); - distance to the camera variies with projections. We cannot change setNearValue, setFarValue, setAspectRatio, setFOV, to adjust this, as the projection matrix would change also (API).
But we can 'force' a collision and look what happes.
Mod the code within my comments.
Outside the render loop add right after:

Code: Select all

//--------- 
...
pos = new ...
irr::core::vector3d<f32>& 
	delta = new irr::core::vector3df( camera->getAbsolutePosition() - marker->getAbsolutePosition() );
irr::core::plane3d<f32> 
	plane = irr::core::plane3d( marker->getAbsolutePosition(), delta.normalize() );
//--------- 
Change the code inside the render loop to:

Code: Select all

//--------- 
plane->getIntersectionWithLine( line->getMiddle(), line->getVector(), pos );
pointer->setPosition(pos);
//--------- 
If everything works fine the bbnode will - in any projection - slide on a plane thru the mesh given by marker.
Thulsa Doom
Posts: 63
Joined: Thu Aug 05, 2004 9:40 am
Location: Germany

Post by Thulsa Doom »

Damnit, it was me again 8) .

Joy,
the line is fine, I tryied different meshes yesterday,
always with same result:
At orthogonal projection the collision is always detected
on a scaled version of the mesh itself. The collision behaviour
strongly suggests that the invisible irr::scene::ITriangleSelector
is not transformed by the changed projection view.
Any tries to directly use the method:

pSelector->getTriangles (core::triangle3df *triangles, s32 arraySize, s32 &outTriangleCount, const core::line3d< f32 > &line, const core::matrix4 *transform=0)

had no succes so far.

PS.: use getPosition instead of getAbsolutePosition!
joy
Posts: 124
Joined: Tue Apr 27, 2004 9:15 am
Location: Germany

Post by joy »

Thanks Thulsa, although you are doing that also for your own project you are helping me a lot.
Are trying the same source code than I am?

Anyway I tried your example above and that is my result:

in the projection view the bbnode is drifting from near to far and vice versa. That means, that when the mouse pointer is on the right side of the window the bbnode ist very tiny, on the left side of the window it is very big and cuts the mesh somehow.

In the orthographic view the bbnode stays the same size as it would just drifting on a plane from the right side to the left side. But it is cutting the mesh too. And on the very right side the bbnode dissapears.
Thulsa Doom
Posts: 63
Joined: Thu Aug 05, 2004 9:40 am
Location: Germany

Post by Thulsa Doom »

I spotted this too,
it's the difference between getPosition instead of getAbsolutePosition. Use the first (whyever). Anyway in both projections the bbnode stays well underlying the current cursor position, which means transforming the line is not necessary. I used e.g. a md2 mesh for test purpose.
In normal projection it's larger then in orthogonal projection.
In orthogonal projection there is a kind of invisible outline as large as the mesh is in normal projection.
In my opinion thats the ITriangleSelector which has not beeing transformed.
Afterward I used ITriangleSelector::getTriangles(...) which has an input argument for an core::matrix4 and on output argument for a Triangle list to fix it, but no success.
I will do some further tests...
joy
Posts: 124
Joined: Tue Apr 27, 2004 9:15 am
Location: Germany

Post by joy »

I tried it with just getPosition but for me there is no difference... Well I have some more tests too...
Post Reply