Horde3D

Next-Generation Graphics Engine
It is currently 19.04.2024, 01:24

All times are UTC + 1 hour




Post new topic Reply to topic  [ 26 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: 17.05.2008, 14:19 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
Horde3D::castRay and Horde3DUtil::pick use internally checkIntersection to determine the point of intersection with a node - if any. I need this intersection point in my app, so it would be great if we could extend the API to provide this information. At the moment I'm directly accessing checkIntersection by using an extended wrapper.

Another problem is, if several objects intersect with the ray: Then only the nearest object is returned without a way to determine the other objects.
Edit: I read the code a bit more carefully: It's not possible to use minDist to select the nearest object which is further away then a certain value. So the intersected nodes must be stored internally somehow.


Top
 Profile  
Reply with quote  
PostPosted: 18.05.2008, 10:22 
Offline

Joined: 08.11.2006, 03:10
Posts: 384
Location: Australia
Good idea.
Codepoet wrote:
A better approach would be to store a list of all intersected nodes [if the user has requested more than one result] and add functions to retrieve and clear the list.

^^A lot of the time the user will still only require the closest object, so there should be extra parameters that you can pass to configure how the picking will happen.

Gamebryo 2.x acheives this by having the user declare and fill in a configuration structure (e.g. closest object or all objects? return intersection position? return normal, texcoords, etc at point of intersection?), and then the results of the picking operation are stored in this same structure.

e.g. something like:
Code:
struct pickResult { vec3 pos, normal; vec2 tex; float distance; };
struct pickInfo {
  pickInfo( int f ) : flags(f) {}
  std::vector<pickResult> results;
  int flags;
  const static int F_GET_POS = 0x01;
  const static int F_GET_NORM = 0x02;
  const static int F_GET_DISTANCE = 0x04;
  const static int F_GET_ALL_OBJECTS = 0x08;
};

pickInfo bullet( F_GET_DISTANCE );
doPick( node, bullet, rayStart, rayDirection );
if( !bullet.results.empty() )
   damage = std::max(0, 100 - bullet.results.front().distance);


[edit] I forgot that we can't use std::vectors in Horde's interface :oops: but you get the idea


Top
 Profile  
Reply with quote  
PostPosted: 18.05.2008, 12:51 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
Edit: Updated design to avoid memory allocations inside user app.

The current API does not use structures. So I'll not introduce them ;)
My suggestion will achieve the same thing:

Code:
int castRay(NodeHandle node,
    float ox, float oy, float oz,
    float dx, float dy, float dz,
    int flags,
    int numNearest);

flags:
UNSORTED - do not sort result list (may be faster, default is sorted)
(more? depending on getCastRayResults implementation here can be determined which information should be calculated)
numNearest: if == 0 return all intersecting nodes; if != 0 and UNSORTED was specified, it is undefined which n nodes are included in the result
return value: number of intersections found

Code:
bool getCastRayResults(int index,
    NodeHandle *node,
    float *distance,
    float *intersection);

index: result index in range [0, result of castRay)
node: NodeHandle or NULL
distance: float or NULL
intersection: float[3] or NULL
return value: true on success, otherwise false (really needed? as long as the index is valid, this call should succeed always)

Code:
void clearCastRayResults();

releases internal memory. Automatically called by castRay.



Sample use case for all intersections:
Code:
int num = castRay(startNode, ox, oy, oz, dx, dy, dz, 0, 0)
for(int i; i < num; ++i)
{
    NodeHandle node;
    float distance;
    float intersection[3];
    getCastRayResults(i, &node, &distance, intersection);

    // do something with the result
    // ..
}
clearCastRayResult();


Sample use case for only nearest intersection:
Code:
if(castRay(startNode, ox, oy, oz, dx, dy, dz, 0, 1))
{
    NodeHandle node;
    float distance;
    float intersection[3];
    getCastRayResult(0, &node, &distance, intersection);

    // do something with result
    // ...
}
clearCastRayResult();


In order to avoid duplicating code with picking replace Horde3DUtils::pick with a function that returns the ray origin and direction. Then the user can do the ray cast as usual.


Last edited by Codepoet on 20.05.2008, 20:18, edited 2 times in total.

Top
 Profile  
Reply with quote  
PostPosted: 18.05.2008, 19:36 
Offline

Joined: 15.05.2008, 05:32
Posts: 46
Location: California
How about:

Code:
enum
{
  RAYCAST_FLAG_SORT = (1<<0),
  RAYCAST_FLAG_NEAREST_RESULT_ONLY = (1<<1),
};

class RaycastResult
{
public:
  RaycastResult(NodeHandle* node, float k) : m_node(node), m_k(k) {}
  NodeHandle* Node() const { return m_node; }
  float Distance() const { return m_k }

private:
  NodeHandle* m_node;
  float m_k; // normalized distance along the ray [0-1] (could be real distance as well)
};

void myFunc()
{
  std::vector<RaycastResult> results;
 
  // cast the ray and fill in the vector with results
  rayCast(from_x, from_y, from_z, to_x, to_y, to_z, RAYCAST_FLAG_SORT, results);

  for( size_t i_intersection=0; i_intersection<results.size(); ++i_intersection )
  {
    const RaycastResult& result = results[i_intersection];
    // do whatever
  }
}


I just saw someone saying no std::vector. Why?


Top
 Profile  
Reply with quote  
PostPosted: 18.05.2008, 20:25 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
roarflolo wrote:
I just saw someone saying no std::vector. Why?

The public API is a C-style procedural interface. That means no structs, classes or anything like that. This makes it really easy to write language bindings for Horde3D.


Top
 Profile  
Reply with quote  
PostPosted: 20.05.2008, 19:48 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
I've attached the code to replace pickNode with a function which only returns the ray parameters for use with castRay.


Attachments:
File comment: Replaces Horde3DUtils::pickNode with Horde3DUtils::pickRay
pick.patch.zip [1.06 KiB]
Downloaded 611 times
Top
 Profile  
Reply with quote  
PostPosted: 20.05.2008, 20:01 
Offline
Engine Developer

Joined: 10.09.2006, 15:52
Posts: 1217
Codepoet, I like your idea much! I appreciate especially that you try to keep the interface consistent.

Just one suggestion: currently one would require memory allocations for the result list which can kill performance and introduce memory fragmentation. What about having an internal list of results that you can query? I'm thinking of something similar to the way findNodes/getNodeFindResult is working.

Another note: the ray casting is not meant for complex applications like physics. It is not very optimized (for heavy meshes), so if you require a plenty of queries you better use a physics engine.


Top
 Profile  
Reply with quote  
PostPosted: 20.05.2008, 20:08 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
marciano wrote:
Just one suggestion: currently one would require memory allocations for the result list which can kill performance and introduce memory fragmentation. What about having an internal list of results that you can query? I'm thinking of something similar to the way findNodes/getNodeFindResult is working.

good idea. I've updated my post above.

marciano wrote:
Another note: the ray casting is not meant for complex applications like physics. It is not very optimized (for heavy meshes), so if you require a plenty of queries you better use a physics engine.

It's ideal for debugging at the moment since I don't have any physics, yet.


Top
 Profile  
Reply with quote  
PostPosted: 30.05.2008, 21:59 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
I'd like to raise again the issue about changing the castRay code - I just tested the terrain intersection algorithm and had to change the engine code to spit out debug messages inside castRay since I can't access the intersection point otherwise...

@Volker, marciano: If you want to include my proposal I'll implement it and post the patches here.


Top
 Profile  
Reply with quote  
PostPosted: 30.05.2008, 22:29 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
Sure


Top
 Profile  
Reply with quote  
PostPosted: 31.05.2008, 00:40 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
Here's the patch. When you've committed it to svn I'll update my D and Python bindings.

I've made two small changes to my proposal above: The current implementation does not use flags, so I omitted this parameter and getCastRayResults is now getCastRayResult.

Apply with "patch -p1" as usual.


Attachments:
File comment: implements my proposal above.
extendedcastray.patch.zip [3.37 KiB]
Downloaded 592 times
Top
 Profile  
Reply with quote  
PostPosted: 01.06.2008, 15:34 
Offline
Engine Developer

Joined: 10.09.2006, 15:52
Posts: 1217
Thanks for the patch.

Is the function for clearing the results really needed? Actually this could happen implicitely during the next query.

I would suggest to integrate the new functionality after Horde 1.0 final was released since it would break the current API.


Top
 Profile  
Reply with quote  
PostPosted: 01.06.2008, 17:46 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
At the moment it's cleared automatically when one calls castRay.
The idea was to allow the user to free "unused" resources ASAP. But you are right, it seems like overkill here. I'll remove it.

I don't know your release policy, but if you want that 1.x stays backwards compatible to 1.0 it would mean that this usefull feature would have to wait until 2.0 / stay in the development branch. Obviously I'd like to have it in the 1.0 release instead of having to write an extension and duplicating the code in the engine core. Especially for beginners it would make it easier if there's only one obvious way to do picking instead of having the option of either using the engine or an extension.
I understand the problem of breaking the API this late in the release process, so I'll respect your decision either way ;)


Top
 Profile  
Reply with quote  
PostPosted: 01.06.2008, 17:55 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
New patch without clearCastRayResults.


Attachments:
File comment: removed clearCastRayResults
extendedcastray2.patch.zip [3.26 KiB]
Downloaded 603 times
Top
 Profile  
Reply with quote  
PostPosted: 02.06.2008, 12:22 
Offline

Joined: 22.11.2007, 17:05
Posts: 707
Location: Boston, MA
Codepoet wrote:
I don't know your release policy, but if you want that 1.x stays backwards compatible to 1.0 it would mean that this usefull feature would have to wait until 2.0 / stay in the development branch. Obviously I'd like to have it in the 1.0 release instead of having to write an extension and duplicating the code in the engine core.
You do have a point though - at the 1.0 beta stage we have a license to break a little (before the 1.0.x freeze). This is a good change, which simplifies and clarifies the API, and we do want 1.0 to be a very useful freeze...

_________________
Tristam MacDonald - [swiftcoding]


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 26 posts ]  Go to page 1, 2  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 35 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group