FVec2 ZViewpoint::zviewpointProjOnPlane( int scnX, int scnY, FVec3 p0, FVec3 planeNrm ) { DMat4 modl = zviewpointReferenceModel; DMat4 _s = scale3D( DVec3(zviewpointScale, zviewpointScale, zviewpointScale)); modl.cat( _s ); DMat4 _t = trans3D( DVec3(zviewpointPermitTransX ? zviewpointTrans[0] : 0.f, zviewpointPermitTransY ? zviewpointTrans[1] : 0.f, zviewpointPermitTransZ ? zviewpointTrans[2] : 0.f)); modl.cat( _t ); FMat4 _v = zviewpointRotQuat.mat(); DMat4 rot = DMat4( _v ); rot.transpose(); modl.cat( rot ); if( zviewpointReferenceViewport[2]==0 || zviewpointReferenceViewport[3]==0 ) { // PROTECT against exception return FVec2( (float)0.f, (float)0.f ); } int viewport[4]; glGetIntegerv( GL_VIEWPORT, viewport ); DMat4 projMat; double world[2][3] = {0,}; gluUnProject( scnX, scnY, 0.f, modl, projMat, viewport, &world[0][0], &world[0][1], &world[0][2] ); gluUnProject( scnX, scnY, 1.f, modl, projMat, viewport, &world[1][0], &world[1][1], &world[1][2] ); FVec3 wp0 = zviewpointLinePlaneIntersect( FVec3::Origin, FVec3::ZAxis, FVec3((float)world[0][0],(float)world[0][1],(float)world[0][2]), FVec3((float)world[1][0],(float)world[1][1],(float)world[1][2]) ); return FVec2( (float)wp0.x, (float)wp0.y ); }
Color Cylinder::getDifColor(const Vec3D& pnt, const CIsect& isect/* = CIsect()*/) const { if (mMtrl->DifTexture) { Vec3D texCoords = getTexCoords(pnt, isect); return scale3D(mMtrl->DifTexture->sample(texCoords.x(), texCoords.y()), mMtrl->DifColor); } return mMtrl->DifColor; }
void ZViewpoint::zviewpointHandleMsgTrackball( ZMsg *msg ) { static float viewpointMouseLast[2]; static int dragging = 0; float newzviewpointScale = 0.f; int scaleChange = 0; if( (zmsgIs(type,ZUIMouseClickOn) || zmsgIs(type,MouseClick)) && zmsgIs(dir,D) && (zmsgIs(which,R) || zmsgIs(which,M)) && zmsgI(shift) && zmsgI(ctrl) && zmsgI(alt) ) { // RESET memset( &zviewpointTrans, 0, sizeof(zviewpointTrans) ); zviewpointRotQuat.fromAxisAngle( FVec3::XAxis, 0.f ); zviewpointScale = 1.f; } char button = msg->getS( "which", "X" ) [0]; // if( (zmsgIs(type,ZUIMouseClickOn) || zmsgIs(type,MouseClick)) && zmsgIs(dir,D) && ( ( zmsgIs(which,M) && (zviewpointPermitRotX||zviewpointPermitRotY||zviewpointPermitRotZ) ) || zmsgIs(which,R) ) ) { if( (zmsgIs(type,ZUIMouseClickOn) || zmsgIs(type,MouseClick)) && zmsgIs(dir,D) && ( ( button==zviewpointRotateButton && (zviewpointPermitRotX||zviewpointPermitRotY||zviewpointPermitRotZ) ) || button==zviewpointTranslateButton ) ) { // I added the checks on permitrot but I think that this is probably temporay. I probably need to put in // some kind of better mapping system so that calling code can assign the mappings that they want // I had commented out the M button for some reason probably because // it conflicted with something. But I need it in Jarle. So this probably // needs to turn into a option but I will leave it on until // I see what it is that needs it turned off. Of course the // higher level thing could trap it and "zmsgUsed" to make ti disappear viewpointMouseLast[0] = zmsgF(x); viewpointMouseLast[1] = zmsgF(y); dragging = zMouseMsgRequestExclusiveDrag( "type=Viewpoint_MouseDrag" ); if( dragging ) { zviewpointRotating = button == zviewpointRotateButton; zviewpointTranslating = button == zviewpointTranslateButton; } zMsgUsed(); } else if( zmsgIs( type, KeyDown ) ) { if( zmsgIs( which, down ) ) { zviewpointRotateTrackball( 0.f, -zviewpointRotateStep ); zMsgUsed(); } if( zmsgIs( which, up ) ) { zviewpointRotateTrackball( 0.f, +zviewpointRotateStep ); zMsgUsed(); } if( zmsgIs( which, left ) ) { zviewpointRotateTrackball( +zviewpointRotateStep, 0.f ); zMsgUsed(); } if( zmsgIs( which, right ) ) { zviewpointRotateTrackball( -zviewpointRotateStep, 0.f ); zMsgUsed(); } } else if( (zmsgIs(type,Key) && zmsgIs(which,wheelforward)) || (zmsgIs(type,Key) && !strcmp(msg->getS("which"),",") ) ) { newzviewpointScale = zviewpointScale * 0.8f; scaleChange = 1; zMsgUsed(); } else if( (zmsgIs(type,Key) && zmsgIs(which,wheelbackward)) || (zmsgIs(type,Key) && !strcmp(msg->getS("which"),".") ) ) { newzviewpointScale = zviewpointScale * 1.2f; scaleChange = 1; zMsgUsed(); } if( scaleChange && zviewpointPermitScale ) { float x = (float)zMouseMsgX; float y = (float)zMouseMsgY; // I want the world coord at which the mouse is pointing before the zoom // to be the same as the world coord at which the mouse is pointing after the zoom // @TODO: convert his mess into a single function DMat4 preScale = zviewpointReferenceModel; DMat4 preScaleMat( scale3D( DVec3(zviewpointScale, zviewpointScale, zviewpointScale) ) ); preScale.cat( preScaleMat ); DVec3 pre0, pre1; gluUnProject( x, y, 0.f, preScale, zviewpointReferenceProj, zviewpointReferenceViewport, &pre0.x, &pre0.y, &pre0.z ); gluUnProject( x, y, 1.f, preScale, zviewpointReferenceProj, zviewpointReferenceViewport, &pre1.x, &pre1.y, &pre1.z ); FVec3 wp0 = zviewpointLinePlaneIntersect( FVec3::Origin, FVec3::ZAxis, FVec3((float)pre0.x,(float)pre0.y,(float)pre0.z), FVec3((float)pre1.x,(float)pre1.y,(float)pre1.z) ); DMat4 postScale = zviewpointReferenceModel; DMat4 postScaleMat = ( scale3D( DVec3(newzviewpointScale, newzviewpointScale, newzviewpointScale) ) ); postScale.cat( postScaleMat ); DVec3 post0, post1; gluUnProject( x, y, 0.f, postScale, zviewpointReferenceProj, zviewpointReferenceViewport, &post0.x, &post0.y, &post0.z ); gluUnProject( x, y, 1.f, postScale, zviewpointReferenceProj, zviewpointReferenceViewport, &post1.x, &post1.y, &post1.z ); FVec3 wp1 = zviewpointLinePlaneIntersect( FVec3::Origin, FVec3::ZAxis, FVec3((float)post0.x,(float)post0.y,(float)post0.z), FVec3((float)post1.x,(float)post1.y,(float)post1.z) ); wp1.sub( wp0 ); zviewpointTrans.add( wp1 ); zviewpointScale = newzviewpointScale; } if( zmsgIs(type,Viewpoint_MouseDrag) ) { if( zmsgI(releaseDrag) ) { zMouseMsgCancelExclusiveDrag(); zviewpointRotating = zviewpointTranslating = 0; } else { if( zviewpointRotating ) { float dx = +0.01f * ( viewpointMouseLast[0] - zmsgF(x) ); float dy = -0.01f * ( viewpointMouseLast[1] - zmsgF(y) ); float side = zmsgI( shift ) ? ( (zmsgF(localX) < zmsgF(w)/2) ? -1.f : 1.f ) : 0.f; // note: the side doesn't really work if the object is being rendered in a ZUI because the // w here refers to the screen, and not the ZUI. zviewpointRotateTrackball( dx, dy, side ); viewpointMouseLast[0] = zmsgF(x); viewpointMouseLast[1] = zmsgF(y); zMsgUsed(); } // else if( zmsgI(r) ) { else if( zviewpointTranslating ) { // COMPUTE how big is one pixel at the world z-plane of interest // For now, this plane normal to the camera and passes-though the origin // Do this by unprojecting rays at the mouse current and last and then // solving for the world position at the intersection of that plane // CAT in tranforms which take place before the translate DMat4 m = zviewpointReferenceModel; DMat4 _m( scale3D( DVec3(zviewpointScale, zviewpointScale, zviewpointScale) ) ); m.cat( _m ); DMat4 _m1( trans3D( DVec3(zviewpointTrans )) ); m.cat( _m1 ); DVec3 p0, p1, p2, p3; gluUnProject( zmsgF(x), zmsgF(y), 0.f, m, zviewpointReferenceProj, zviewpointReferenceViewport, &p0.x, &p0.y, &p0.z ); gluUnProject( zmsgF(x), zmsgF(y), 1.f, m, zviewpointReferenceProj, zviewpointReferenceViewport, &p1.x, &p1.y, &p1.z ); gluUnProject( viewpointMouseLast[0], viewpointMouseLast[1], 0.f, m, zviewpointReferenceProj, zviewpointReferenceViewport, &p2.x, &p2.y, &p2.z ); gluUnProject( viewpointMouseLast[0], viewpointMouseLast[1], 1.f, m, zviewpointReferenceProj, zviewpointReferenceViewport, &p3.x, &p3.y, &p3.z ); FVec3 wp0 = zviewpointLinePlaneIntersect( FVec3::Origin, FVec3::ZAxis, FVec3((float)p0.x,(float)p0.y,(float)p0.z), FVec3((float)p1.x,(float)p1.y,(float)p1.z) ); FVec3 wp1 = zviewpointLinePlaneIntersect( FVec3::Origin, FVec3::ZAxis, FVec3((float)p2.x,(float)p2.y,(float)p2.z), FVec3((float)p3.x,(float)p3.y,(float)p3.z) ); wp0.sub( wp1 ); FVec3 delta( wp0.x, wp0.y, 0.f ); if( zmsgI(shift) ) { delta.x = 0.f; delta.y = 0.f; delta.z = wp0.y * 4.f; } zviewpointTrans.add( delta ); viewpointMouseLast[0] = zmsgF(x); viewpointMouseLast[1] = zmsgF(y); zMsgUsed(); } } } }