Anyway, I am facing a problem with Newton Game Dynamics: I am trying to implement ray picking in my program but it does not work. Either it selects the last object of the NewtonWorld, either it selects nothing at all. So here is my source if you need it (it is nearly the exact function as the demo):
pick.h:
- Code: Select all
#include <newton/Newton.h>
#include <glm/glm.hpp>
struct Pick{
static NewtonBody* MousePickByForce (NewtonWorld* const nWorld, const glm::vec3& origin, const glm::vec3& end, dFloat& paramter, glm::vec3& positionOut, glm::vec3& normalOut);
};
pick.cpp:
- Code: Select all
/* Copyright (c) <2009> <Newton Game Dynamics>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely
*/
#include "pick.h"
#include <glm/ext.hpp>
class dMousePickClass
{
public:
dMousePickClass ()
:m_param (1.f)
,m_body(NULL)
{
}
// implement a ray cast pre-filter
static unsigned RayCastPrefilter (const NewtonBody* body, const NewtonCollision* const collision, void* const userData)
{
// ray cannot pick trigger volumes
//return NewtonCollisionIsTriggerVolume(collision) ? 0 : 1;
return (NewtonBodyGetType(body) == NEWTON_DYNAMIC_BODY) ? 1 : 0;
}
static dFloat RayCastFilter (const NewtonBody* const body, const NewtonCollision* const collisionHit, const dFloat* const contact, const dFloat* const normal, dLong collisionID, void* const userData, dFloat intersetParam)
{
dFloat mass;
dFloat Ixx;
dFloat Iyy;
dFloat Izz;
dMousePickClass* const data = (dMousePickClass*) userData;
NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz);
if ((mass > 0.f) || (NewtonBodyGetType(body) == NEWTON_KINEMATIC_BODY)) {
float p0[3], p1[3];
NewtonBodyGetAABB(body,p0, p1);
if(contact[0] < p0[0] || contact[0] > p1[0] ||
contact[1] < p0[1] || contact[1] > p1[1] ||
contact[2] < p0[2] || contact[2] > p1[2]){}
else
data->m_body = body;
}
if (intersetParam < data->m_param) {
data->m_param = intersetParam;
data->m_normal = glm::vec3(normal[0], normal[1], normal[2]);
}
return intersetParam;
}
glm::vec3 m_normal;
dFloat m_param;
const NewtonBody* m_body;
};
NewtonBody* Pick::MousePickByForce (NewtonWorld* const nWorld, const glm::vec3& origin, const glm::vec3& end, dFloat& paramterOut, glm::vec3& positionOut, glm::vec3& normalOut)
{
// float x = dFloat (mouseX);
// float y = dFloat (mouseY);
// glm::vec3 p0 (ScreenToWorld(glm::vec3 (x, y, 0.0f, 0.0f)));
// glm::vec3 p1 (ScreenToWorld(glm::vec3 (x, y, 1.0f, 0.0f)));
dMousePickClass rayCast;
NewtonWorldRayCast(nWorld, glm::value_ptr(origin), glm::value_ptr(end), dMousePickClass::RayCastFilter, &rayCast, dMousePickClass::RayCastPrefilter, 0);
if (rayCast.m_body) {
positionOut = origin + (end - origin)*(rayCast.m_param);
normalOut = rayCast.m_normal;
paramterOut = rayCast.m_param;
}
return (NewtonBody*) rayCast.m_body;
}
and scene.cpp (central class):
- Code: Select all
glm::vec3 ScreenToWorld (const glm::vec3& screen)
{
//Where the values will be stored
GLint viewport[4];
//Retrieves the viewport and stores it in the variable
// get a point on the display array of the windows
glGetIntegerv(GL_VIEWPORT, viewport);
//Where the 16 doubles of the matrix are to be stored
//Retrieve the matrix
GLdouble modelview[16];
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
GLdouble projection[16];
glGetDoublev(GL_PROJECTION_MATRIX, projection);
GLdouble winX = 0.0;
GLdouble winY = 0.0;
GLdouble winZ = 0.0; //The coordinates to pass in
winX = screen.x; //Store the x cord
winY = screen.y; //Store the y cord
winZ = screen.z; //Store the Z cord
//Now windows coordinates start with (0,0) being at the top left
//whereas OpenGL cords start lower left so we have to do this to convert it:
//Remember we got viewport value before
winY = (dFloat)viewport[3] - winY;
GLdouble objx;
GLdouble objy;
GLdouble objz;
// use the real GL view port
glGetIntegerv(GL_VIEWPORT, viewport);
gluUnProject (winX, winY, winZ, modelview, projection, viewport, &objx, &objy, &objz);
return glm::vec3(dFloat(objx), dFloat(objy), dFloat(objz));
}
void Scene::pick(float x, float y){
glm::vec3 p0 (ScreenToWorld(glm::vec3 (x, y, 0.0f)));
glm::vec3 p1 (ScreenToWorld(glm::vec3 (x, y, 1.0f)));
float param;
glm::vec3 pos_out;
glm::vec3 norm_out;
NewtonBody *picked = Pick::MousePickByForce(world, p0, p1, param, pos_out, norm_out);
if(!picked)
printf("Nothing\n");
else
exit(0);//to see if when i click it works
picked = 0;
}
If you need more information, ask me and I will give them.
Thank you for your help.