Why would GLU crash at this spot? - c++

I have found that my application crashes with a null reference exception right here in sweep.c in GLU source code:
static void ConnectLeftVertex( GLUtesselator *tess, GLUvertex *vEvent )
/*
* Purpose: connect a "left" vertex (one where both edges go right)
* to the processed portion of the mesh. Let R be the active region
* containing vEvent, and let U and L be the upper and lower edge
* chains of R. There are two possibilities:
*
* - the normal case: split R into two regions, by connecting vEvent to
* the rightmost vertex of U or L lying to the left of the sweep line
*
* - the degenerate case: if vEvent is close enough to U or L, we
* merge vEvent into that edge chain. The subcases are:
* - merging with the rightmost vertex of U or L
* - merging with the active edge of U or L
* - merging with an already-processed portion of U or L
*/
{
ActiveRegion *regUp, *regLo, *reg;
GLUhalfEdge *eUp, *eLo, *eNew;
ActiveRegion tmp;
/* assert( vEvent->anEdge->Onext->Onext == vEvent->anEdge ); */
/* Get a pointer to the active region containing vEvent */
tmp.eUp = vEvent->anEdge->Sym;
/* __GL_DICTLISTKEY */ /* __gl_dictListSearch */
regUp = (ActiveRegion *)dictKey( dictSearch( tess->dict, &tmp ));
regLo = RegionBelow( regUp );
eUp = regUp->eUp;
eLo = regLo->eUp; //CRASHES RIGHT HERE SINCE RegLo is = 0x000000 FOR SOME REASON
/* Try merging with U or L first */
if( EdgeSign( eUp->Dst, vEvent, eUp->Org ) == 0 ) {
ConnectLeftDegenerate( tess, regUp, vEvent );
return;
}
/* Connect vEvent to rightmost processed vertex of either chain.
* e->Dst is the vertex that we will connect to vEvent.
*/
reg = VertLeq( eLo->Dst, eUp->Dst ) ? regUp : regLo;
if( regUp->inside || reg->fixUpperEdge) {
if( reg == regUp ) {
eNew = __gl_meshConnect( vEvent->anEdge->Sym, eUp->Lnext );
if (eNew == NULL) longjmp(tess->env,1);
} else {
GLUhalfEdge *tempHalfEdge= __gl_meshConnect( eLo->Dnext, vEvent->anEdge);
if (tempHalfEdge == NULL) longjmp(tess->env,1);
eNew = tempHalfEdge->Sym;
}
if( reg->fixUpperEdge ) {
if ( !FixUpperEdge( reg, eNew ) ) longjmp(tess->env,1);
} else {
ComputeWinding( tess, AddRegionBelow( tess, regUp, eNew ));
}
SweepEvent( tess, vEvent );
} else {
/* The new vertex is in a region which does not belong to the polygon.
* We don''t need to connect this vertex to the rest of the mesh.
*/
AddRightEdges( tess, regUp, vEvent->anEdge, vEvent->anEdge, NULL, TRUE );
}
}
It seems as though eRegLo is a NULL pointer sometimes which causes my application to crash. How could I modify the source to prevent it from crashing my application?
Thanks

You will have to look into the source for RegionBelow and see if and when it can return a NULL pointer. Between your call to RegionBelow and your de-reference of regLo, perform a regLo == NULL check. You can do this with an assert or by throwing an exception (in C++). Most likely, if RegionBelow can return NULL on error, there will be some other method that you can use to determine what the error was and how to handle it. You will have to consult the source code or documentation for RegionBelow to find that information.

Related

Why is this Haxe try-catch block still crashing, when using Release mode for C++ target

I have a HaxeFlixel project, that is working OK in Debug mode for misc targets, including flash, neko and windows. But Targeting Windows in Release mode, I'm having an unexpected crash, and surprisingly it's happening inside a try-catch block. Here's the crashing function:
/**
* Will safely scan a parent node's children, search for a child by name, and return it's text.
* #param parent an Fast object that is parent of the `nodeNamed` node
* #param nodeName the node's name or a comma-separated path to the child (will scan recursively)
* #return node's text as String, or null if child is not there
*/
public static function getNodeText(parent:Fast, nodeName:String):String {
try {
var _node : Fast = getNodeNamed(parent, nodeName);
//if (_node == null)
// return null;
// next line will crash if _node is null
var it :Iterator<Xml> = _node.x.iterator();
if ( it == null || !it.hasNext() )
return null;
var v = it.next();
var n = it.next();
if( n != null ) {
if( v.nodeType == Xml.PCData && n.nodeType == Xml.CData && StringTools.trim(v.nodeValue) == "" ) {
var n2 = it.next();
if( n2 == null || (n2.nodeType == Xml.PCData && StringTools.trim(n2.nodeValue) == "" && it.next() == null) )
return n.nodeValue;
}
//does not only have data (has children)
return null;
}
if( v.nodeType != Xml.PCData && v.nodeType != Xml.CData )
//does not have data";
return null;
return v.nodeValue;
}catch (err:Dynamic) {
trace("Failed parsing node Text [" + nodeName+"] " + err );
return null;
}
}
By enabling if (_node == null) return null; line, It's working safely again. By catching errors as Dynamic I thought I was supposed to catch every possible error type! Why is this happening? And why is it appearing in release mode?
My IDE is FlashDevelop, and I'm using HaxeFlixel 3.3.6, lime 0.9.7 and openFL 1.4.0, if that makes any difference
EDIT: I suspect this has to do with how the translated C++ code missed the Dynamic Exception. The equivalent generated C++ code is:
STATIC_HX_DEFINE_DYNAMIC_FUNC2(BaxXML_obj,_getNodeNamed,return )
::String BaxXML_obj::getNodeText( ::haxe::xml::Fast parent,::String nodeName){
HX_STACK_FRAME("bax.utils.BaxXML","getNodeText",0x4a152f07,"bax.utils.BaxXML.getNodeText","bax/utils/BaxXML.hx",56,0xf6e2d3cc)
HX_STACK_ARG(parent,"parent")
HX_STACK_ARG(nodeName,"nodeName")
HX_STACK_LINE(56)
try
{
HX_STACK_CATCHABLE(Dynamic, 0);
{
HX_STACK_LINE(57)
::haxe::xml::Fast _node = ::bax::utils::BaxXML_obj::getNodeNamed(parent,nodeName); HX_STACK_VAR(_node,"_node");
HX_STACK_LINE(63)
Dynamic it = _node->x->iterator(); HX_STACK_VAR(it,"it");
// ... Let's skip the irrelevant code
}
catch(Dynamic __e){
{
HX_STACK_BEGIN_CATCH
Dynamic err = __e;{
HX_STACK_LINE(82)
::String _g5 = ::Std_obj::string(err); HX_STACK_VAR(_g5,"_g5");
HX_STACK_LINE(82)
::String _g6 = (((HX_CSTRING("Failed parsing node Text [") + nodeName) + HX_CSTRING("] ")) + _g5); HX_STACK_VAR(_g6,"_g6");
HX_STACK_LINE(82)
::haxe::Log_obj::trace(_g6,hx::SourceInfo(HX_CSTRING("BaxXML.hx"),82,HX_CSTRING("bax.utils.BaxXML"),HX_CSTRING("getNodeText")));
HX_STACK_LINE(83)
return null();
}
}
}
HX_STACK_LINE(56)
return null();
}
What haxedefs do you have defined?
Adding these to your project.xml might help:
<haxedef name="HXCPP_CHECK_POINTER"/> <!--makes null references cause errors-->
<haxedef name="HXCPP_STACK_LINE" /> <!--if you want line numbers-->
<haxedef name="HXCPP_STACK_TRACE"/> <!--if you want stack traces-->
You might also try the crashdumper library:
https://github.com/larsiusprime/crashdumper
(Crashdumper will turn on HXCPP_CHECK_POINTER by default as part of it's include.xml, and will set up hooks for both hxcpp's errors and openfl/lime's uncaught error events)
I guess this boils down to how C++ handles null-pointer Exceptions. It doesn't!
More info here or here
That seems odd, some questions that may help solving it.
It looks like you are doing quite some assumptions on how the xml looks (doing some manual it.next()), why is that?
Why are you using this big-ass try-catch block?
How does getNodeNamed look, it seems it can return null.
Do you have an example xml to test with?

Maya API - Move CV with Kinect

I’m trying to create a 64-bit plug-in for Autodesk Maya 2013. The aim of this plug-in is to be able to model objects through the Kinect.
In context, with the plug-in you can select the CV of a created object. To specify you want to move the selected points, the position of selected CV is updated constantly.
Here is my problem, when I try to update the position of a selected CV of an object, the result is not displayed on the screen.
I have tried many ways without getting any result, as an example:
1) when I do the setPosition the point doesn’t update.
for ( ; !iter.isDone(); iter.next() ) {
iter.getDagPath( mdagPath, mComponent );
MItSurfaceCV sCvFn( mdagPath, mComponent, true, &stat );
if ( MS::kSuccess == stat ) {
for ( ; !sCvFn.isDone(); sCvFn.nextRow() ) {
for ( ; !sCvFn.isRowDone(); sCvFn.next() ) {
MPoint pto(pHand.posX, pHand.posY, pHand.posZ);
sCvFn.setPosition(pto, MSpace::kWorld);
}
}
}
sCvFn.updateSurface();
}
2) in this case, if you iterate over the array newCVS before doing the setCVs you can see the updated points.
But then, when doing setCVs and looking for the position in the CV array of the object (doing a getCVs) the position of the modified CV doesn’t change.
for ( ; !iter.isDone(); iter.next() ) {
stat = iter.getDagPath( mdagPath, mComponent );
if(stat == MS::kSuccess) {
MFnNurbsSurface surf(mdagPath);
MItSurfaceCV sCvFn( mdagPath, mComponent, true, &stat );
MPointArray currentCV;
surf.getCVs(currentCV, MSpace::kWorld);
MPointArray newCVS(currentCV.length(), MPoint::origin);
newCVS.setLength(currentCV.length());
for(unsigned i = 0; i < currentCV.length(); i++){
newCVS[i] = newCVS[i] + currentCV[i];
}
int index;
if ( MS::kSuccess == stat ) {
for ( ; !sCvFn.isDone(); sCvFn.nextRow() ) {
for ( ; !sCvFn.isRowDone(); sCvFn.next() ) {
sCvFn.getIndex(indexU, indexV);
int posArray = indexU * surf.numCVsInV() + indexV;
index = posArray;
MVector diff = MPoint(pHand.posX, pHand.posY, pHand.posZ) - currentCV[posArray];
newCVS[posArray] = newCVS[posArray] + diff;
}
}
surf.setCVs(newCVS, MSpace::kWorld);
surf.updateSurface();
}
}
3) When having CV selected in Maya, I tried to move this points with MEL commands. For this, I use the “MGlobal::executeCommand” function, but still nothing happens.
Finally, I changed executeCommand to executeCommandOnIdle. In this case, the object change correctly but the procedure crashes, perhaps, because this procedure is executed many times per second.
I would appreciate if anyone can help me with this problem or knows something about this.

Deleting a file from git repository using libgit2

Say you have a file in a git repository:
a.txt
What APIs should be used to create a commit that removes that file?
For example in this question the file is committed without creating it on disk. Is it now possible to remove that file without using the index (stage area)?
I was expecting a similar flow, maybe creating a git_tree_entry for the tree builder, but that does not seem to be the case. git_reference_list() does not list files, so there's a dead end. Also searching the sources for delete and remove got me no success.
Removing a file is similar to adding a file - you remove the index entry to stage the delete, then you can create a commit from the index.
You probably want to use git_index_remove_bypath, which will remove the file from the index and resolve any conflicts that file had.
Here is a copy-paste example; for getLastCommit() see this question.
bool commitStage (
git_repository * repo, git_signature * sign,
const char * message )
{
bool b = false;
int rc;
git_index * repo_idx; /* the stage area for our repository */
git_oid oid_idx_tree; /* the SHA1 for the tree generated from index */
git_oid oid_commit; /* the SHA1 for our commit */
git_tree * tree_cmt; /* tree generated from index */
git_commit * parent_commit;/* most recent commit in the head */
parent_commit = getLastCommit( repo );
if ( parent_commit != NULL )
{ /* we have the parent commit */
rc = git_repository_index( &repo_idx, repo );
if ( rc == 0 )
{ /* we now have the index (stage area) structure in repo_idx */
git_index_read(repo_idx);
/* the stage area may be altered here with functions like
git_index_add_bypath();
git_index_remove_bypath();
*/
/* by writing the index we get the SHA1 of the tree */
rc = git_index_write_tree( &oid_idx_tree, repo_idx );
if ( rc == 0 )
{
rc = git_tree_lookup(
&tree_cmt, repo, &oid_idx_tree );
if ( rc == 0 )
{ /* the actual tree structure; create a commit from it */
rc = git_commit_create(
&oid_commit, repo, "HEAD",
sign, sign, NULL,
message,
tree_cmt, 1, (const git_commit**)&parent_commit );
if ( rc == 0 )
{
b = true;
}
}
}
git_index_free( repo_idx );
}
git_commit_free( parent_commit );
}
return b;
}

How to use OpenSSL to extend {D,E,N} RSA key to {D,E,N,p,q,etc.}?

I have an RSA key consisting of the public & private factors and the modulus D. (I'm currently generating and using the key with a JavaScript library.) I would like to use the same key to perform encryptions & decryptions with OpenSSL. I can plug my factors into an OpenSSL RSA key and everything works, but I'd like to have OpenSSL calculate the auxiliary factors it uses (if available) to speed up operations.
I'm not sure whether it's even mathematically possible to work back from {D,E,N} to those factors, but if it is, I'd like to know how to ask libopenssl to do it.
Thanks!
The algorithm for deriving p and q from the secret d is very easy and fast, though probabilistic. It is explained very briefly in Chapter 8 of "Handbook of applied cryptography", section 8.2.2, or in Boneh's article "Twenty Years of Attacks on the RSA Cryptosystem", page 205.
You could find first an implementation of the algorithm in a high level language (for instance in Python, check the function rsa_construct in PyCrypto). From there, you can implement it via OpenSSL using its multiprecision API.
/* crypto/rsa/rsa_aug_key.c -*- Mode: C; c-file-style: "eay" -*- */
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core#OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
/*
* If key has d, e and n, but not p, q, dmp1, dmq1 and iqmp, try
* to calculate these extra factors. Return 1 on success or 0
* on failure. (The key may still be useable even if this fails.)
*/
int RSA_augment_key(RSA *key)
{
int spotted;
BN_CTX *ctx;
BIGNUM *ktot;
BIGNUM *t;
BIGNUM *tmp;
BIGNUM *a;
BIGNUM *two;
BIGNUM *l00;
BIGNUM *cand;
BIGNUM *k;
BIGNUM *n_1;
if (!key || !key->d || !key->e || !key->n) return 0;
spotted = 0;
ctx = BN_CTX_new( );
ktot = BN_new( );
t = BN_new( );
tmp = BN_new( );
a = 0; BN_dec2bn( &a, "2" );
two = 0; BN_dec2bn( &two, "2" );
l00 = 0; BN_dec2bn( &l00, "100" );
cand = BN_new( );
k = BN_new( );
n_1 = BN_new( ); if (!BN_sub( n_1, key->n, BN_value_one( ) )) goto fail;
/* Python-code comments from PyCrypto
// ------------------------------------------------------------------
// # Compute factors p and q from the private exponent d.
// # We assume that n has no more than two factors.
// # See 8.2.2(i) in Handbook of Applied Cryptography.
// ktot = d*e-1*/
if (!BN_mul( tmp, key->d, key->e, ctx )) goto fail;
if (!BN_sub( ktot, tmp, BN_value_one( ) )) goto fail;
/* # The quantity d*e-1 is a multiple of phi(n), even,
// # and can be represented as t*2^s.
// t = ktot */
if (!BN_copy( t, ktot )) goto fail;
/* while t%2==0:
// t=divmod(t,2)[0] */
while (!BN_is_odd( t ))
if (!BN_rshift1( t, t )) goto fail;
/* # Cycle through all multiplicative inverses in Zn.
// # The algorithm is non-deterministic, but there is a 50% chance
// # any candidate a leads to successful factoring.
// # See "Digitalized Signatures and Public Key Functions as Intractable
// # as Factorization", M. Rabin, 1979
// spotted = 0
// a = 2
// while not spotted and a<100: */
while (!spotted && BN_cmp( a, l00 ) < 0) {
/* k = t */
if (!BN_copy( k, t )) goto fail;
/* # Cycle through all values a^{t*2^i}=a^k
// while k<ktot: */
while (BN_cmp( k, ktot ) < 0) {
/* cand = pow(a,k,n) */
if (!BN_mod_exp( cand, a, k, key->n, ctx )) goto fail;
/* # Check if a^k is a non-trivial root of unity (mod n)
// if cand!=1 and cand!=(n-1) and pow(cand,2,n)==1: */
if (BN_cmp( cand, BN_value_one( ) ) && BN_cmp( cand, n_1 )) {
if (!BN_mod_exp( tmp, cand, two, key->n, ctx )) goto fail;
if (BN_cmp( tmp, BN_value_one( )) == 0) {
/* # We have found a number such that (cand-1)(cand+1)=0 (mod n).
// # Either of the terms divides n.
// obj.p = GCD(cand+1,n)
// spotted = 1
// break */
key->p = BN_new( );
if (!BN_add( tmp, cand, BN_value_one( ) )) goto fail;
if (!BN_gcd( key->p, tmp, key->n, ctx )) goto fail;
spotted = 1;
break;
}
}
// k = k*2
if (!BN_lshift1( k, k )) goto fail;
}
/* # This value was not any good... let's try another!
// a = a+2 */
if (!BN_add( a, a, two )) goto fail;
}
if (!spotted) {
/* Unable to compute factors P and Q from exponent D */
goto fail;
}
key->q = BN_new( );
if (!BN_div( key->q, tmp, key->n, key->p, ctx )) goto fail;
if (!BN_is_zero( tmp )) {
/* Curses! Tricked with a bogus P! */
goto fail;
}
key->dmp1 = BN_new( );
key->dmq1 = BN_new( );
key->iqmp = BN_new( );
if (!BN_sub( tmp, key->p, BN_value_one( ) )) goto fail;
if (!BN_mod( key->dmp1, key->d, tmp, ctx )) goto fail;
if (!BN_sub( tmp, key->q, BN_value_one( ) )) goto fail;
if (!BN_mod( key->dmq1, key->d, tmp, ctx )) goto fail;
if (!BN_mod_inverse( key->iqmp, key->q, key->p, ctx )) goto fail;
if (RSA_check_key( key ) == 1) goto cleanup;
fail:
BN_free( key->p ); key->p = 0;
BN_free( key->q ); key->q = 0;
BN_free( key->dmp1 ); key->dmp1 = 0;
BN_free( key->dmq1 ); key->dmq1 = 0;
BN_free( key->iqmp ); key->iqmp = 0;
spotted = 0;
cleanup:
BN_free( k );
BN_free( cand );
BN_free( n_1 );
BN_free( l00 );
BN_free( two );
BN_free( a );
BN_free( tmp );
BN_free( t );
BN_free( ktot );
BN_CTX_free( ctx );
return spotted;
}
Hard problem. To find p and q from n, you need to factor n, which is hard. Given that you know both d and e, you could instead look for a large factor of de-1, which would be phi(n). Once you have that you can take advantage of the fact that, n - phi(n) = p + q - 1 for RSA keys, and thus find p and q
So the process is roughly:
Try to guess x in de-1 = x phi(n). Sine e = 65537 for RSA, this shouldn't be too bad -- x has to be somewhere in the range 50000..200000 or so, so it should only require 100K or so trial divisions.
Now find y = (p + q)/2 = (n + phi(n) + 1)/2 and z = sqrt(yy - n), which gives you p = y+z and q = y-z
Relatively straight-forward, but there's no built-in way of doing this with openssl or any other library I'm aware of.

SoRayPickAction in Open Inventor?

Sorry if this is a repeat, but I'm trying to figure out the implementation of SoRayPickAction in Open Inventor. I'm trying to implement it so that it will, when the mouse is clicked, select a particular node so then I can translate, rotate, etc. I have three nodes: desk, lamp, and frame (picture frame). However, I don't think that my code is at all right. I also have various methods such a MouseButtonCallback (which will check if the mouse is clicked and then use a navigator) and MouseMoveCallback (same idea). So here's the code that I have, but do you have any suggestions? Right now, well, it doesn't do anything.
SbViewportRegion viewport(400,300);
SoRayPickAction m(viewport);
m.setRay(SbVec3f(0.0,0.0,0.0), SbVec3f(0.0,0.0,-1.0));
m.apply(callback_node);
const SoPickedPoint *mpp = m.getPickedPoint();
if(mpp != NULL) {
std::cout << "test" << std::endl;
}
Might you also know of an action in OpenInventor that can "place" a node in the scene, i.e. place the lamp on top of the desk, frame on the wall, etc. Is it with paths? I don't even know what I'm looking for, unfortunately. Thanks so much for your help!!
Edit: How does this look?
SoSeparator *desk2;
SoSeparator *lamp2;
SoSeparator *pic_frame2;
SoSeparator *picked;
void MouseButtonCallback(void* data, SoEventCallback* node)
{
SoHandleEventAction* action = node->getAction();
const SoMouseButtonEvent* event = static_cast<const SoMouseButtonEvent*>(action- >getEvent());
Navigator* nav = static_cast<Navigator*>(data);
if (SoMouseButtonEvent::isButtonPressEvent(event, event->getButton()))
nav->OnMouseDown(event, action);
else
nav->OnMouseUp(event, action);
const SbViewportRegion & viewportRegion = action->getViewportRegion();
SoRayPickAction pickAction(viewportRegion);
SbVec2s mousePos = event->getPosition(viewportRegion);
pickAction.setPoint(mousePos);
pickAction.setPickAll(TRUE);
pickAction.setRadius(2.0F);
pickAction.setRay(SbVec3f(0.0,0.0,0.0), SbVec3f(0.0,0.0,-1.0));
pickAction.apply(node);
const SoPickedPoint *mpp = pickAction.getPickedPoint();
if(mpp != NULL) {
SoPath *path = mpp->getPath();
if(desk2 != NULL && path->containsNode(desk2))
{ //but this doesn't respond with cout when I try to test it :(
if (SoMouseButtonEvent::isButtonPressEvent(event, event->getButton()))
*picked = *desk2;
}
else if(lamp2 != NULL && path->containsNode(lamp2))
{
if (SoMouseButtonEvent::isButtonPressEvent(event, event->getButton()))
*picked = *lamp2;
}
else if(pic_frame2 != NULL && path->containsNode(pic_frame2))
{
if (SoMouseButtonEvent::isButtonPressEvent(event, event->getButton()))
*picked = *pic_frame2;
}
action->setHandled();
}
void MouseMoveCallback(void* data, SoEventCallback* node)
{
SoHandleEventAction* action = node->getAction();
const SoLocation2Event* event = static_cast<const SoLocation2Event*>(action->getEvent());
Navigator* nav = static_cast<Navigator*>(data);
nav->OnMouseMove(event, action);
const SbViewportRegion & viewportRegion = action->getViewportRegion();
SoRayPickAction pickAction(viewportRegion);
SbVec2s mousePos = event->getPosition(viewportRegion);
pickAction.setPoint(mousePos);
pickAction.setPickAll(TRUE);
pickAction.setRadius(2.0F);
pickAction.setRay(SbVec3f(0.0,0.0,0.0), SbVec3f(0.0,0.0,-1.0));
pickAction.apply(node);
const SoPickedPoint *mpp = pickAction.getPickedPoint();
if(mpp != NULL) {
SoPath *path = mpp->getPath();
if(desk2 != NULL && path->containsNode(desk2))
{
*picked = *desk2; //can't remember how to set pointers, will figure that out
}
else if(lamp2 != NULL && path->containsNode(lamp2))
{
*picked = *lamp2;
}
else if(pic_frame2 != NULL && path->containsNode(pic_frame2))
{
*picked = *pic_frame2;
}
}
action->setHandled();
}
(part of main method)
//desk
SoTransform *desk_transform = new SoTransform;
desk_transform->translation.setValue(SbVec3f(380,340,330));
SoSeparator* desk2 = new SoSeparator();
desk2->addChild(desk_transform);
desk2->addChild(desk);
root->addChild(desk2);
SoTransformerManip* picked_transform = new SoTransformerManip();
picked_transform->translation.setValue(SbVec3f(200,340,330));
SoSeparator* pick2 = new SoSeparator();
pick2->addChild(picked_transform);
pick2->addChild(picked);
root->addChild(pick2);
std::auto_ptr<btCollisionShape> picked_shape(new btBoxShape(btVector3(10.0f, 10.0f, 10.0f)));
CollisionEngine* picked_collision = new CollisionEngine(collision_world.get(), picked_shape.get());
picked_collision->translation_in.connectFrom(&picked_transform->translation);
picked_collision->rotation_in.connectFrom(&picked_transform->rotation);
picked_transform->translation.connectFrom(&picked_collision->translation_out);
You have the picked point. You then get an SoPath as you guessed. Then see if the path contains a node you want to do something with.
SbViewportRegion viewport(400,300);
SoRayPickAction m(viewport);
m.setRay(SbVec3f(0.0,0.0,0.0), SbVec3f(0.0,0.0,-1.0));
m.apply(callback_node);
const SoPickedPoint *mpp = m.getPickedPoint();
if(mpp != NULL) {
std::cout << "test" << std::endl;
SoPath * path = pickedPoint->getPath();
if (deskSeparator != NULL && path->containsNode(deskSeparator)
{
}
else if (lampSeparator != NULL && path->containsNode(lampSeparator)
{
}
else if (radomeSeparator != NULL && path->containsNode(radomeSeparator)
{
if ( SoMouseButtonEvent::isButtonPressEvent( event, SoMouseButtonEvent::BUTTON2 )
|| ( SoMouseButtonEvent::isButtonPressEvent( event, SoMouseButtonEvent::BUTTON1 ) && event->wasShiftDown() ) )
{
modelPointMoving = true;
const SoDetail * detail = modelPickedPoint->getDetail( 0 );
int face = -1;
if ( detail && detail->isOfType( SoFaceDetail::getClassTypeId() ) )
{
const SoFaceDetail * faceDetail = static_cast<const SoFaceDetail *>( detail );
face = faceDetail->getFaceIndex();
}
updateStatusBar( face, point.getValue(), normal.getValue() );
graphicModel.postNote( pickedPoint );
break;
}
else if ( SoMouseButtonEvent::isButtonPressEvent( event, SoMouseButtonEvent::BUTTON1 ) )
{
}
else if ( SoMouseButtonEvent::isButtonReleaseEvent( event, SoMouseButtonEvent::BUTTON1 ) )
{
}
}
}
You'll eventually want to connect the pick ray to the mouse position sort of like this:
// Set an 2-pixel wide region around the pixel.
SbVec2s mousePosition = event->getPosition( viewportRegion );
pickAction.setPoint( mousePosition );
pickAction.setPickAll( TRUE );
pickAction.setRadius( 2.0F );
This is done before you .apply() the pick action of course.
I guess my code is a mixture of yours and mine but I think it should give you a start. Also, this is sitting inside a function to process mouse events:
void
RenderWindow::mouseEvent( void *, SoEventCallback * eventCallback )
{
const SoEvent *event = eventCallback->getEvent();
if ( ! event )
{
qDebug() << " ** Error in mousePressCallback: Event not found.";
return;
}
//SoType eventType = event->getTypeId();
//SbName eventTypeName = eventType.getName();
//const char * eventTypeString = eventTypeName.getString();
SoHandleEventAction * action = eventCallback->getAction();
const SbViewportRegion & viewportRegion = action->getViewportRegion();
SoRayPickAction pickAction( viewportRegion );
Up in main or a setup routine I register the mouse event (for both click action and location (moving the mouse over the viewport):
// Add a mouse event callback to catch mouse button presses.
SoEventCallback * mouseEventCallback = new SoEventCallback();
mouseEventCallback->setName( "MOUSE_EVENT_CALLBACK" );
mouseEventCallback->addEventCallback( SoMouseButtonEvent::getClassTypeId(), &::mouseEvent, static_cast<void *>( this ) );
// Add a mouse event callback to catch mouse motion.
mouseEventCallback->addEventCallback( SoLocation2Event::getClassTypeId(), &::mouseEvent, static_cast<void *>( this ) );
rootSeparator->addChild( mouseEventCallback );
Now that I look at it I wrote the chunks in reverse order ;-). Sorry.
Good Luck