Beispiel #1
0
bool IntersectPolygon (TPolygon p, TVector3 *v) {
    TRay ray; 
    TVector3 nml, edge_nml, edge_vec;
    TVector3 pt;
    double d, s, nuDotProd, wec;
    double edge_len, t, distsq;
    int i;

    nml = MakeNormal (p, v);
    ray.pt = MakeVector (0., 0., 0.);
    ray.vec = nml;

    nuDotProd = DotProduct (nml, ray.vec);
    if  (fabs(nuDotProd) < EPS)
        return false;

    d = - (nml.x * v[p.vertices[0]].x + 
           nml.y * v[p.vertices[0]].y + 
           nml.z * v[p.vertices[0]].z);

    if  (fabs (d) > 1) return false;

    for  (i=0; i < p.num_vertices; i++) {
		TVector3 *v0, *v1;

		v0 = &v[p.vertices[i]];
		v1 = &v[p.vertices[ (i+1) % p.num_vertices ]]; 

		edge_vec = SubtractVectors (*v1, *v0);
		edge_len = NormVector (&edge_vec);

		t = - DotProduct (*((TVector3 *) v0), edge_vec);

		if  (t < 0) {
			distsq = MAG_SQD2 (*v0);
		} else if  (t > edge_len) {
			distsq = MAG_SQD2 (*v1);
		} else {
			*v0 = AddVectors (*v0, ScaleVector (t, edge_vec));
			distsq = MAG_SQD2 (*v0);
		}

		if  (distsq <= 1) return true;
    }

    s = - (d + DotProduct (nml, MakeVector (ray.pt.x, ray.pt.y, ray.pt.z))) / nuDotProd;
    pt = AddVectors (ray.pt, ScaleVector (s, ray.vec));

    for  (i=0; i < p.num_vertices; i++) {
        edge_nml = CrossProduct (nml, 
            SubtractVectors (v[p.vertices[ (i+1) % p.num_vertices ]], v[p.vertices[i]]));

        wec = DotProduct (SubtractVectors (pt, v[p.vertices[i]]), edge_nml);
        if (wec < 0) return false;
    } 
    return true;
} 
complex stb_InnerProduct(stabiliser *phi1, stabiliser *phi2)
{
    affine_sp a = afp_Copy(phi1->a); //This won't work. I need to define a copy method
    stabiliser stab;
    stab.a = &a;
    stab.q = phi1->q;
    affine_sp *a1 = phi1->a, *a2 = phi2->a;
    quadratic_fm *q1 = phi1->q, *q2 = phi2->q;
    for (int i = a2->k +1; i < a2->n; i++){
        alpha = InnerProduct(a2->h, a2->GBar[i])
        res = shrink(&stab, a2->HBar[i], alpha);
        if (res == EMPTY){
            return (complex) 0;
        }
    }
    short *y = (short *)calloc(a2->k, sizeof(short));
    short *scratch_space = (short *)calloc(a2->n, sizeof(short));
    short res = 0;
    AddVectors(a2->n, scratch_space, a1->h);
    AddVectors(a2->n, scratch_space, a2->h);
    short **R = (short **)calloc(a2->n, sizeof(short*));
    for (int i=0; i<a2->n; i++){R[i] = (short *)calloc(a2->n, sizeof(short));}
    for (int i = 0; i < a2->k; i++){
        y[i] = InnerProduct(scratch_space, a2->Gbar[i]);
        for (int j = 0; j < a.k; j++){
            R[j][i] = InnerProduct(a.G[j], a2.GBar[i]);
        }

    }
    qfm_BasisChange(q2, R);
    qfm_ShiftChange(q2, y);
    for (int i = 0; i<a2->n; i++){a2->h[i] = a1->h[i];}
    //Cleanup
    for(int i = 0; i<q2->k; i++){free(R[i]);}
    free(scratch_space);
    free (R);
    free(y);
    //Find the final quadratic form q
    q.Q = Modulo(q1->Q - q2->Q, 8);
    for (int i = 0; i < q.K; i++){ 
        q.D[i] = Modulo(q1->D[i]-q2->D[i], 8);
        for (int j = 0; j<q.k; j++){
            q.J[i][j] = Modulo(q1->J[i][j] - q2->J[i][j], 8);
        }
    }
    return pow(2, -1*(a1->k - a2->k)/2)*ExponentialSum(q);
}
Beispiel #3
0
double DexAnalogMixin::FilterLoadForce( Vector3 load_force ) {
	// Combine the new force sample with previous filtered value (recursive filtering).
	ScaleVector( filteredLoadForce, filteredLoadForce, filterConstant );
	AddVectors( filteredLoadForce, filteredLoadForce, load_force );
	ScaleVector( filteredLoadForce, filteredLoadForce, 1.0 / (1.0 + filterConstant ));
	// Return the filtered value in place.
	CopyVector( load_force, filteredLoadForce );
	return( VectorNorm( filteredLoadForce ) );
}
Beispiel #4
0
double DexAnalogMixin::FilterManipulandumRotations( Vector3 rotations ) {
	// Combine the new rotations sample with previous filtered value (recursive filtering).
	ScaleVector( filteredManipulandumRotations, filteredManipulandumRotations, filterConstant );
	AddVectors( filteredManipulandumRotations, filteredManipulandumRotations, rotations );
	ScaleVector( filteredManipulandumRotations, filteredManipulandumRotations, 1.0 / (1.0 + filterConstant ));
	// Return the filtered value in place.
	CopyVector( rotations, filteredManipulandumRotations );
	return( VectorNorm( rotations ) );
}
Beispiel #5
0
double DexAnalogMixin::FilterCoP( int which_ati, Vector3 center_of_pressure ) {
	// Combine the new force sample with previous filtered value (recursive filtering).
	ScaleVector( filteredCoP[which_ati], filteredCoP[which_ati], filterConstant );
	AddVectors( filteredCoP[which_ati], filteredCoP[which_ati], center_of_pressure );
	ScaleVector( filteredCoP[which_ati], filteredCoP[which_ati], 1.0 / (1.0 + filterConstant ));
	// Return the filtered value in place.
	CopyVector( center_of_pressure, filteredCoP[which_ati] );
	return( VectorNorm( filteredCoP[which_ati] ) );
}
Beispiel #6
0
double DexAnalogMixin::FilterAcceleration( Vector3 acceleration ) {
	// Combine the new position sample with previous filtered value (recursive filtering).
	ScaleVector( filteredAcceleration, filteredAcceleration, filterConstant );
	AddVectors( filteredAcceleration, filteredAcceleration, acceleration );
	ScaleVector( filteredAcceleration, filteredAcceleration, 1.0 / (1.0 + filterConstant ));
	// Return the filtered value in place.
	CopyVector( acceleration, filteredAcceleration );
	return( VectorNorm( acceleration ) );
}
int DexMouseTracker::RetrieveMarkerFrames( CodaFrame frames[], int max_frames ) {

	int n_frames;
	int previous_frame;
	int next_frame;

	Vector3	jump, delta;
	double	time, interval, offset, relative;


	// Copy data into an array.
	previous_frame = 0;
	next_frame = 0;

	// Fill an array of frames at a constant frequency by interpolating the
	// frames that were taken at a variable frequency in real time.
	for ( n_frames = 0; n_frames < max_frames; n_frames++ ) {

		// Compute the time of each slice at a constant sampling frequency.
		time = (double) n_frames * samplePeriod;
		frames[n_frames].time = (float) time;

		// See if we have caught up with the real-time data.
		if ( time > recordedMarkerFrames[next_frame].time ) previous_frame = next_frame;
		// Find the next real-time frame that has a time stamp later than this one.
		// It could be that this true already.
		while ( recordedMarkerFrames[next_frame].time <= time && next_frame < nAcqFrames ) next_frame++;
		// If we reached the end of the real-time samples, then we are done.
		if ( next_frame >= nAcqFrames ) break;

		// Compute the time difference between the two adjacent real-time frames.
		interval = recordedMarkerFrames[next_frame].time - recordedMarkerFrames[previous_frame].time;
		// Compute the time between the current frame and the previous real_time frame.
		offset = time - recordedMarkerFrames[previous_frame].time;
		// Use the relative time to interpolate.
		relative = offset / interval;

		for ( int j = 0; j < nMarkers; j++ ) {
			frames[n_frames].marker[j].visibility = 
				recordedMarkerFrames[previous_frame].marker[j].visibility &&
				recordedMarkerFrames[next_frame].marker[j].visibility;
			if ( frames[n_frames].marker[j].visibility ) {
				SubtractVectors( jump, 
									recordedMarkerFrames[next_frame].marker[j].position,
									recordedMarkerFrames[previous_frame].marker[j].position );
				ScaleVector( delta, jump, (float) relative );
				AddVectors( frames[n_frames].marker[j].position, recordedMarkerFrames[previous_frame].marker[j].position, delta );
			}
		}
	}

	return( n_frames );

}
TVector3 CCourse::FindCourseNormal (double x, double z) const {

    double *elevation = Course.elevation;
    int x0, x1, y0, y1;
    GetIndicesForPoint (x, z, &x0, &y0, &x1, &y1);

    TIndex2 idx0, idx1, idx2;
    double u, v;
    FindBarycentricCoords (x, z, &idx0, &idx1, &idx2, &u, &v);

	const TVector3& n0 = Course.nmls[ idx0.i + nx * idx0.j ];
	const TVector3& n1 = Course.nmls[ idx1.i + nx * idx1.j ];
	const TVector3& n2 = Course.nmls[ idx2.i + nx * idx2.j ];

	TVector3 p0 = COURSE_VERTX (idx0.i, idx0.j);
	TVector3 p1 = COURSE_VERTX (idx1.i, idx1.j);
	TVector3 p2 = COURSE_VERTX (idx2.i, idx2.j);

	TVector3 smooth_nml = AddVectors (
		ScaleVector (u, n0),
		AddVectors (ScaleVector (v, n1), ScaleVector (1.-u-v, n2)));

	TVector3 tri_nml = CrossProduct (
		SubtractVectors (p1, p0), SubtractVectors (p2, p0));
    NormVector (tri_nml);

	double min_bary = min (u, min (v, 1. - u - v));
	double interp_factor = min (min_bary / NORM_INTERPOL, 1.0);

	TVector3 interp_nml = AddVectors (
		ScaleVector (interp_factor, tri_nml),
		ScaleVector (1.-interp_factor, smooth_nml));
    NormVector (interp_nml);

    return interp_nml;
}
Beispiel #9
0
/* Take current data in s, make it the intial inputs for the transformed vector ns
 * return the updated values in NS to calling function */
void transform_NS(ns_stance *s, vector *ns){
	vector working_vector; 
	vector working_vector_2;
		
	//initialize current ns_vector
	ns->v[0] = (s->x);
	ns->v[1] = (s->y);
	ns->v[2] = (s->theta);
	//PrintVector(ns);//diagnostic
	
	//shift
	AddVectors(ns, ns_shift_vector, &working_vector);
	//diagnostic
	//printf("Shift result = ");
	//PrintVector(&working_vector);
	
	//rotate
	MultMatVec(ns_rot_matrix, &working_vector, &working_vector_2);
	//diagnostic
	//printf("Rotate Result = ");
	//PrintVector(&working_vector_2);
	
	//scale
	// Update Scaling Matrix based on current signal strength [NOT WORKING RIGHT]

	if(s->sig > 15000) {
		scale_matrix->v[0][0] = 1.0 / (NS_TICKS_PER_CM - 15);
		scale_matrix->v[1][1] = scale_matrix->v[0][0];
	}
	else if(s->sig > 4000) {  
		  scale_matrix->v[0][0] = 1.0 / ( ((-3.0 * s->sig) / 1100.0) + 86.0 );
		  scale_matrix->v[1][1] = scale_matrix->v[0][0];
	}
	else {
		scale_matrix->v[0][0] = 1.0 / (NS_TICKS_PER_CM + 15);
		scale_matrix->v[1][1] = scale_matrix->v[0][0];
	}
	
	MultMatVec(scale_matrix, &working_vector_2, ns);
	//diagnostic
	//printf("Scaling Result = ");
	//PrintVector(ns);	
}
Beispiel #10
0
void SpringSys::UpdateParticleState(TimeValue t, Tab<Matrix3> tmArray, int index, TimeValue Delta)
{
	Point3 t_pos, t_vel, orig_pos, orig_vel;
	Matrix3 tm;
	for (int b=0;b<parts[index].GetSprings()->length();b++)
	{
		if (parts[index].GetSpring(b)->GetPointConstraint()->GetIndex() < tmArray.Count())
		{
			tm = tmArray[parts[index].GetSpring(b)->GetPointConstraint()->index];
			ComputeControlledParticleForce(tm, index, b);  /* compute bone deriv used by ApplySpring */
		}
	}

	Clear_Forces(index);							/* zero the force accumulators */
	Compute_Forces(t, index);						/* magic force function */
	ComputeDerivative(index, t_pos, t_vel);		/* get deriv */
	//ComputeDerivative(pIndex, t_pos, t_vel, Delta);		/* get deriv */
	ScaleVectors(t_pos, t_vel, Delta);				/* scale it */
	GetParticleState(index, orig_pos, orig_vel);	/* get state */
	AddVectors(orig_pos, orig_vel, t_pos, t_vel);	/* add -> temp2 */
	SetParticleState(index, t_pos, t_vel);			/* update state */
}
int DexApparatus::CheckMovementAmplitude(  double min, double max, 
										   double dirX, double dirY, double dirZ,
										   const char *msg, const char *picture ) {
	
	const char *fmt;
	bool  error = false;
	
	int i, k, m;

	int first, last;
	
	double N = 0.0, sd;
	Matrix3x3 Sxy;
	Vector3  delta, mean;
	Vector3   direction, vect;

	// TODO: Should normalize the direction vector here.
	direction[X] = dirX;
	direction[Y] = dirY;
	direction[Z] = dirZ;

	// First we should look for the start and end of the actual movement based on 
	// events such as when the subject reaches the first target. 
	FindAnalysisFrameRange( first, last );

	// Compute the mean position. 
	N = 0.0;
	CopyVector( mean, zeroVector );
	for ( i = first; i < last; i++ ) {
		if ( acquiredManipulandumState[i].visibility ) {
			if ( abs( acquiredManipulandumState[i].position[X] ) > 1000 ) {
				i = i;
			}
			N++;
			AddVectors( mean, mean, acquiredManipulandumState[i].position );
		}
	}
	// If there is no valid position data, signal an error.
	if ( N <= 0.0 ) {
		monitor->SendEvent( "Movement extent - No valid data." );
		sd = 0.0;
		error = true;
	}
	else {
	
		// This is the mean.
		ScaleVector( mean, mean, 1.0 / N );;

		// Compute the sums required for the variance calculation.
		CopyMatrix( Sxy, zeroMatrix );
		N = 0.0;

		for ( i = first; i < last; i ++ ) {
			if ( acquiredManipulandumState[i].visibility ) {
				N++;
				SubtractVectors( delta, acquiredManipulandumState[i].position, mean );
				for ( k = 0; k < 3; k++ ) {
					for ( m = 0; m < 3; m++ ) {
						Sxy[k][m] += delta[k] * delta[m];
					}
				}
			}
		}
		
		// If we have some data, compute the directional variance and then
		// the standard deviation along that direction;
		// This is just a scalar times a matrix.

		// Sxy has to be a double or we risk underflow when computing the sums.
		for ( k = 0; k < 3; k++ ) {
			vect[k] = 0;
			for ( m = 0; m < 3; m++ ) {
				Sxy[k][m] /= N;
			}
		}
		// This is a matrix multiply.
		for ( k = 0; k < 3; k++ ) {
			for ( m = 0; m < 3; m++ ) {
				vect[k] += Sxy[m][k] * direction[m];
			}
		}
		// Compute the length of the vector, which is the variance along 
		// the specified direction. Then take the square root of that 
		// magnitude to get the standard deviation along that direction.
		sd = sqrt( VectorNorm( vect ) );

		// Check if the computed value is in the desired range.
		error = ( sd < min || sd > max );

	}

	// If not, signal the error to the subject.
	// Here I take the approach of calling a method to signal the error.
	// We agree instead that the routine should either return a null pointer
	// if there is no error, or return the error message as a static string.
	if ( error ) {
		
		// If the user provided a message to signal a visibilty error, use it.
		// If not, generate a generic message.
		if ( !msg ) msg = "Movement extent outside range.";
		// The message could be different depending on whether the maniplulandum
		// was not moved enough, or if it just could not be seen.
		if ( N <= 0.0 ) fmt = "%s\n Manipulandum not visible.";
		else fmt = "%s\n Measured: %f\n Desired range: %f - %f\n Direction: < %.2f %.2f %.2f>";
		int response = fSignalError( MB_ABORTRETRYIGNORE, picture, fmt, msg, sd, min, max, dirX, dirY, dirZ );
		
		if ( response == IDABORT ) return( ABORT_EXIT );
		if ( response == IDRETRY ) return( RETRY_EXIT );
		if ( response == IDIGNORE ) return( IGNORE_EXIT );
		
	}
	
	// This is my means of signalling the event.
	monitor->SendEvent( "Movement extent OK.\n Measured: %f\n Desired range: %f - %f\n Direction: < %.2f %.2f %.2f>", sd, min, max, dirX, dirY, dirZ );
	return( NORMAL_EXIT );
	
}
Beispiel #12
0
void CEnvironment::DrawFog () {
	if (!fog.is_on)
		return;

    TPlane bottom_plane, top_plane;
    TVector3 left, right, vpoint;
    TVector3 topleft, topright;
    TVector3 bottomleft, bottomright;

	// the clipping planes are calculated by view frustum (view.cpp)
	const TPlane& leftclip = get_left_clip_plane ();
	const TPlane& rightclip = get_right_clip_plane ();
	const TPlane& farclip = get_far_clip_plane ();
	const TPlane& bottomclip = get_bottom_clip_plane ();

	// --------------- calculate the planes ---------------------------

    float slope = tan (ANGLES_TO_RADIANS (Course.GetCourseAngle()));
//	TPlane left_edge_plane = MakePlane (1.0, 0.0, 0.0, 0.0);
//	TPlane right_edge_plane = MakePlane (-1.0, 0.0, 0.0, Course.width);

    bottom_plane.nml = TVector3(0.0, 1, -slope);
    float height = Course.GetBaseHeight (0);
    bottom_plane.d = -height * bottom_plane.nml.y;

    top_plane.nml = bottom_plane.nml;
    height = Course.GetMaxHeight (0) + fog.height;
    top_plane.d = -height * top_plane.nml.y;


    if (!IntersectPlanes (bottom_plane, farclip, leftclip,  &left)) return;
    if (!IntersectPlanes (bottom_plane, farclip, rightclip, &right)) return;
    if (!IntersectPlanes (top_plane,    farclip, leftclip,  &topleft)) return;
    if (!IntersectPlanes (top_plane,    farclip, rightclip, &topright)) return;
    if (!IntersectPlanes (bottomclip,   farclip, leftclip,  &bottomleft)) return;
    if (!IntersectPlanes (bottomclip,   farclip, rightclip, &bottomright)) return;

	TVector3 leftvec  = SubtractVectors (topleft, left);
    TVector3 rightvec = SubtractVectors (topright, right);

	// --------------- draw the fog plane -----------------------------

	ScopedRenderMode rm(FOG_PLANE);
    glEnable (GL_FOG);

	// only the alpha channel is used
	float bottom_dens[4]     = {0, 0, 0, 1.0};
	float top_dens[4]        = {0, 0, 0, 0.9};
	float leftright_dens[4]  = {0, 0, 0, 0.3};
	float top_bottom_dens[4] = {0, 0, 0, 0.0};

    glBegin (GL_QUAD_STRIP);
	    glColor4fv (bottom_dens);
	    glVertex3f (bottomleft.x, bottomleft.y, bottomleft.z);
    	glVertex3f (bottomright.x, bottomright.y, bottomright.z);
	    glVertex3f (left.x, left.y, left.z);
    	glVertex3f (right.x, right.y, right.z);

	    glColor4fv (top_dens);
    	glVertex3f (topleft.x, topleft.y, topleft.z);
    	glVertex3f (topright.x, topright.y, topright.z);

	    glColor4fv (leftright_dens);
    	vpoint = AddVectors (topleft, leftvec);
	    glVertex3f (vpoint.x, vpoint.y, vpoint.z);
    	vpoint = AddVectors (topright, rightvec);
	    glVertex3f (vpoint.x, vpoint.y, vpoint.z);

	    glColor4fv (top_bottom_dens);
	    vpoint = AddVectors (topleft, ScaleVector (3.0, leftvec));
    	glVertex3f (vpoint.x, vpoint.y, vpoint.z);
	    vpoint = AddVectors (topright, ScaleVector (3.0, rightvec));
    	glVertex3f (vpoint.x, vpoint.y, vpoint.z);
    glEnd();
}
bool DexMouseTracker::GetCurrentMarkerFrame( CodaFrame &frame ) {


	POINT mouse_position;
	GetCursorPos( &mouse_position );
	RECT rect;
	GetWindowRect( GetDesktopWindow(), &rect );

	Vector3		position, rotated;
	Vector3	x_dir, y_span, z_span;
	Vector3		x_displacement, y_displacement, z_displacement;

	double		x, y, z;

	Quaternion	Ry, Rz, Q, nominalQ, midQ;
	Matrix3x3	xform = {{-1.0, 0.0, 0.0},{0.0, 0.0, 1.0},{0.0, 1.0, 0.0}};

	int mrk, id;
	
	// Just set the target frame markers at their nominal fixed positions.
	for ( mrk = 0; mrk < nFrameMarkers; mrk++ ) {
		id = FrameMarkerID[mrk];
		CopyVector( frame.marker[id].position, TargetFrameBody[mrk] );
	}

	// Shift the vertical bar markers to simulate being in the left position.
	if ( IsDlgButtonChecked( dlg, IDC_LEFT ) ) {
		frame.marker[DEX_NEGATIVE_BAR_MARKER].position[X] += 300.0;
		frame.marker[DEX_POSITIVE_BAR_MARKER].position[X] += 300.0;
	}

	// Transform the marker positions of the target box and frame according 
	//  to whether the system was upright or supine when it was aligned and
	//  according to whether the system is currently installed in the upright
	//  or supine configuration.
	if ( ( IsDlgButtonChecked( dlg, IDC_SUPINE ) && TRACKER_ALIGNED_SUPINE  != SendDlgItemMessage( dlg, IDC_ALIGNMENT, CB_GETCURSEL, 0, 0 ) ) ||
		 ( IsDlgButtonChecked( dlg, IDC_SEATED ) && TRACKER_ALIGNED_UPRIGHT != SendDlgItemMessage( dlg, IDC_ALIGNMENT, CB_GETCURSEL, 0, 0 ) ) )	{	
		 for ( mrk = 0; mrk < nFrameMarkers; mrk++ ) {

			id = FrameMarkerID[mrk];
			position[X] = - frame.marker[id].position[X];
			position[Z] =   frame.marker[id].position[Y];
			position[Y] =   frame.marker[id].position[Z];

			CopyVector( frame.marker[id].position, position );
		}
		MatrixToQuaternion( nominalQ, xform );
	}
	else CopyQuaternion( nominalQ, nullQuaternion );

	// Now set the visibility flag as a funciton of the GUI.
	if ( IsDlgButtonChecked( dlg, IDC_BAR_OCCLUDED ) ) {
		frame.marker[DEX_NEGATIVE_BAR_MARKER].visibility = false;
		frame.marker[DEX_POSITIVE_BAR_MARKER].visibility = false;
	}
	else {
		frame.marker[DEX_NEGATIVE_BAR_MARKER].visibility = true;
		frame.marker[DEX_POSITIVE_BAR_MARKER].visibility = true;
	}
	if ( IsDlgButtonChecked( dlg, IDC_BOX_OCCLUDED ) ) {
		frame.marker[DEX_NEGATIVE_BOX_MARKER].visibility = false;
		frame.marker[DEX_POSITIVE_BOX_MARKER].visibility = false;
	}
	else {
		frame.marker[DEX_NEGATIVE_BOX_MARKER].visibility = true;
		frame.marker[DEX_POSITIVE_BOX_MARKER].visibility = true;
	}

	// Map mouse coordinates to world coordinates. The factors used here are empirical.
	
	y =  (double) ( mouse_position.y - rect.top ) / (double) ( rect.bottom - rect.top );
	z =  (double) (mouse_position.x - rect.right) / (double) ( rect.left - rect.right );
	x = 0.0;

	// By default, the orientation of the manipulandum is the nominal orientation.

	CopyQuaternion( Q, nominalQ );

	// Simulate wobbly movements of the manipulandum. This has not really been tested.

	if ( IsDlgButtonChecked( dlg, IDC_CODA_WOBBLY ) ) {
		// We will make the manipulandum rotate in a strange way as a function of the distance from 0.
		// This is just so that we can test the routines that compute the manipulandum position and orientation.
		double theta = y * 45.0;
		double gamma = - z * 45.0;
		SetQuaterniond( Ry, theta, iVector );
		SetQuaterniond( Rz, gamma, jVector );
		MultiplyQuaternions( midQ, Rz, nominalQ );
		MultiplyQuaternions( Q, Ry, midQ );
		// Make the movement a little bit in X as well so that we test the routines in 3D.
		x = 0.0 + 5.0 * sin( y / 80.0);
	}

	// Map screen position of the mouse pointer to 3D position of the wrist and manipulandum.
	// Top of the screen corresponds to the bottom of the bar and vice versa. It's inverted to protect the right hand rule.
	// Right of the screen correponds to the nearest horizontal target and left corresponds to the farthest.
	// The X position is set to be just to the right of the box.

	SubtractVectors( y_span, frame.marker[DEX_POSITIVE_BAR_MARKER].position, frame.marker[DEX_NEGATIVE_BAR_MARKER].position );
	SubtractVectors( x_dir, frame.marker[DEX_POSITIVE_BOX_MARKER].position, frame.marker[DEX_NEGATIVE_BOX_MARKER].position );
	NormalizeVector( x_dir );
	ComputeCrossProduct( z_span, x_dir, y_span );
	 
	ScaleVector( y_displacement, y_span, y );
	ScaleVector( z_displacement, z_span, z );
	ScaleVector( x_displacement, x_dir, x );

	// Reference position is the bottom target on the vertical target bar.
	CopyVector( position, frame.marker[DEX_NEGATIVE_BAR_MARKER].position );
	// Place the manipulandum to the right of the box, even if the target bar is in the left position.
	position[X] = frame.marker[DEX_NEGATIVE_BOX_MARKER].position[X];
	// Shift the position in X if the is any wobble to it.
	AddVectors( position, position, x_displacement );
	// Shift the position in Y and Z according to the displacements computed from the mouse position.
	AddVectors( position, position, y_displacement );
	AddVectors( position, position, z_displacement );

	frame.time = DexTimerElapsedTime( acquisitionTimer );

	// Displace the manipulandum with the mouse and make it rotate.
	for ( mrk = 0; mrk < nManipulandumMarkers; mrk++ ) {
		id = ManipulandumMarkerID[mrk];
		RotateVector( rotated, Q, ManipulandumBody[mrk] );
		AddVectors( frame.marker[id].position, position, rotated );
		frame.marker[id].visibility = true;
	}

	// Displace the wrist with the mouse, but don't rotate it.
	for ( mrk = 0; mrk < nWristMarkers; mrk++ ) {
		id = WristMarkerID[mrk];
		AddVectors( frame.marker[id].position, position, WristBody[mrk] );
		frame.marker[id].visibility = true;
	}

	// Output the position and orientation used to compute the simulated
	// marker positions. This is for testing only.
	fprintf( fp, "%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n",
		frame.time, 
		position[X], position[Y], position[Z],
		Q[X], Q[Y], Q[Z], Q[M] );

	return( true );

}
int DexMouseTracker::RetrieveMarkerFrames( CodaFrame frames[], int max_frames, int unit ) {

	int previous;
	int next;
	int frm;

	Vector3f	jump, delta;
	double	time, interval, offset, relative;

	// Copy data into an array.
	previous = 0;
	next = 1;

	// Fill an array of frames at a constant frequency by interpolating the
	// frames that were taken at a variable frequency in real time.
	for ( frm = 0; frm < max_frames; frm++ ) {

		// Compute the time of each slice at a constant sampling frequency.
		time = (double) frm * samplePeriod;
		frames[frm].time = (float) time;

		// Fill the first frames with the same position as the first polled frame;
		if ( time < polledMarkerFrames[previous].time ) {
			CopyMarkerFrame( frames[frm], polledMarkerFrames[previous] );
		}

		else {
			// See if we have caught up with the real-time data.
			if ( time > polledMarkerFrames[next].time ) {
				previous = next;
				// Find the next real-time frame that has a time stamp later than this one.
				while ( polledMarkerFrames[next].time <= time && next < nPolled ) next++;
				// If we reached the end of the real-time samples, then we are done.
				if ( next >= nPolled ) {
					break;
				}
			}

			// Compute the time difference between the two adjacent real-time frames.
			interval = polledMarkerFrames[next].time - polledMarkerFrames[previous].time;
			// Compute the time between the current frame and the previous real_time frame.
			offset = time - polledMarkerFrames[previous].time;
			// Use the relative time to interpolate.
			relative = offset / interval;

			for ( int j = 0; j < nMarkers; j++ ) {
				// Both the previous and next polled frame must be visible for the 
				// interpolated sample to be visible.
				frames[frm].marker[j].visibility = 
					 ( polledMarkerFrames[previous].marker[j].visibility
					   && polledMarkerFrames[next].marker[j].visibility );

				if ( frames[frm].marker[j].visibility ) {
					SubtractVectors( jump, 
										polledMarkerFrames[next].marker[j].position,
										polledMarkerFrames[previous].marker[j].position );
					ScaleVector( delta, jump, (float) relative );
					AddVectors( frames[frm].marker[j].position, polledMarkerFrames[previous].marker[j].position, delta );
				}
			}
		}
	}
	nAcqFrames = frm;
	return( nAcqFrames );

}
Beispiel #15
0
void CEnvironment::DrawFog () {
    TPlane bottom_plane, top_plane;
    TVector3 left, right;
    TVector3 topleft, topright;
    TVector3 bottomleft = NullVec; 
    TVector3 bottomright = NullVec;
    float height;

    if (!fog.is_on) return;

    // the clipping planes are calculated by view frustum (view.cpp)
    leftclip = get_left_clip_plane ();
    rightclip = get_right_clip_plane ();
    farclip = get_far_clip_plane ();
    bottomclip = get_bottom_clip_plane ();

    // --------------- calculate the planes ---------------------------

    float slope = tan (ANGLES_TO_RADIANS (Course.GetCourseAngle()));
//	TPlane left_edge_plane = MakePlane (1.0, 0.0, 0.0, 0.0);
//	TPlane right_edge_plane = MakePlane (-1.0, 0.0, 0.0, Course.width);

    bottom_plane.nml = MakeVector (0.0, 1, -slope);
    height = Course.GetBaseHeight (0);
    bottom_plane.d = -height * bottom_plane.nml.y;

    top_plane.nml = bottom_plane.nml;
    height = Course.GetMaxHeight (0) + fog.height;
    top_plane.d = -height * top_plane.nml.y;

    if (!IntersectPlanes (bottom_plane, farclip, leftclip,  &left)) return;
    if (!IntersectPlanes (bottom_plane, farclip, rightclip, &right)) return;
    if (!IntersectPlanes (top_plane,    farclip, leftclip,  &topleft)) return;
    if (!IntersectPlanes (top_plane,    farclip, rightclip, &topright)) return;
    if (!IntersectPlanes (bottomclip,   farclip, leftclip,  &bottomleft)) return;
    if (!IntersectPlanes (bottomclip,   farclip, rightclip, &bottomright)) return;

    TVector3 leftvec  = SubtractVectors (topleft, left);
    TVector3 rightvec = SubtractVectors (topright, right);

    TVector3 vpoint1 = AddVectors (topleft, leftvec);
    TVector3 vpoint2 = AddVectors (topright, rightvec);
    TVector3 vpoint3 = AddVectors (topleft, ScaleVector (3.0, leftvec));
    TVector3 vpoint4 = AddVectors (topright, ScaleVector (3.0, rightvec));

    // --------------- draw the fog plane -----------------------------

    set_gl_options (FOG_PLANE);
    glEnable (GL_FOG);

    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

	// only the alpha channel is used
	const GLfloat col[] = {
		// bottom density
		0, 0, 0, 1.0,
		0, 0, 0, 1.0,
		0, 0, 0, 1.0,
		0, 0, 0, 1.0,

		// top density
		0, 0, 0, 0.9,
		0, 0, 0, 0.9,

		// left/right density
		0, 0, 0, 0.3,
		0, 0, 0, 0.3,

		// top/bottom density
		0, 0, 0, 0.0,
		0, 0, 0, 0.0
	};

	const GLfloat vtx[] = {
		bottomleft.x, bottomleft.y, bottomleft.z,
		bottomright.x, bottomright.y, bottomright.z,
		left.x, left.y, left.z,
		right.x, right.y, right.z,
		topleft.x, topleft.y, topleft.z,
		topright.x, topright.y, topright.z,
		vpoint1.x, vpoint1.y, vpoint1.z,
		vpoint2.x, vpoint2.y, vpoint2.z,
		vpoint3.x, vpoint3.y, vpoint3.z,
		vpoint4.x, vpoint4.y, vpoint4.z
	};

	glColorPointer(4, GL_FLOAT, 0, col);
	glVertexPointer(3, GL_FLOAT, 0, vtx);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
}
void CCourse::CalcNormals () {
	for (int y=0; y<ny; y++) {
        for (int x=0; x<nx; x++) {
            TVector3 nml(0.0, 0.0, 0.0);
            TVector3 p0 (XCD(x), ELEV(x,y), ZCD(y));

			if ((x + y) % 2 == 0) {
				if (x > 0 && y > 0) {
					TVector3 p1 = NMLPOINT(x,  y-1);
					TVector3 p2 = NMLPOINT(x-1,y-1);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);

					p1 = NMLPOINT (x-1, y-1);
					p2 = NMLPOINT (x-1, y);
					v1 = SubtractVectors (p1, p0);
					v2 = SubtractVectors (p2, p0);
					n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);
				}
				if (x > 0 && y < ny-1) {
					TVector3 p1 = NMLPOINT(x-1,y);
					TVector3 p2 = NMLPOINT(x-1,y+1);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);

					p1 = NMLPOINT(x-1,y+1);
					p2 = NMLPOINT(x  ,y+1);
					v1 = SubtractVectors (p1, p0);
					v2 = SubtractVectors (p2, p0);
					n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);
				}
				if (x < nx-1 && y > 0) {
					TVector3 p1 = NMLPOINT(x+1,y);
					TVector3 p2 = NMLPOINT(x+1,y-1);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);

					p1 = NMLPOINT(x+1,y-1);
					p2 = NMLPOINT(x  ,y-1);
					v1 = SubtractVectors (p1, p0);
					v2 = SubtractVectors (p2, p0);
					n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);
				}
				if (x < nx-1 && y < ny-1) {
					TVector3 p1 = NMLPOINT(x+1,y);
					TVector3 p2 = NMLPOINT(x+1,y+1);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v1, v2);

					NormVector (n);
					nml = AddVectors (nml, n);

					p1 = NMLPOINT(x+1,y+1);
					p2 = NMLPOINT(x  ,y+1);
					v1 = SubtractVectors (p1, p0);
					v2 = SubtractVectors (p2, p0);
					n = CrossProduct (v1, v2);

					NormVector (n);
					nml = AddVectors (nml, n);

				}
			} else {
				if (x > 0 && y > 0) {
					TVector3 p1 = NMLPOINT(x,  y-1);
					TVector3 p2 = NMLPOINT(x-1,y);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);
				}
				if (x > 0 && y < ny-1) {
					TVector3 p1 = NMLPOINT(x-1,y);
					TVector3 p2 = NMLPOINT(x  ,y+1);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);
				}
				if (x < nx-1 && y > 0) {
					TVector3 p1 = NMLPOINT(x+1,y);
					TVector3 p2 = NMLPOINT(x  ,y-1);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v2, v1);

					NormVector (n);
					nml = AddVectors (nml, n);
				}
				if (x < nx-1 && y < ny-1) {
					TVector3 p1 = NMLPOINT(x+1,y);
					TVector3 p2 = NMLPOINT(x  ,y+1);
					TVector3 v1 = SubtractVectors (p1, p0);
					TVector3 v2 = SubtractVectors (p2, p0);
					TVector3 n = CrossProduct (v1, v2);

					NormVector (n);
					nml = AddVectors (nml, n);
				}
			}
            NormVector (nml);
			nmls [x + nx * y] = nml;
            continue;

		}
    }
}
int DexApparatus::CheckMovementCycles(  int min_cycles, int max_cycles, 
										   float dirX, float dirY, float dirZ,
										   float hysteresis, const char *msg, const char *picture ) {
	
	const char *fmt;
	bool  error = false;

	float	displacement = 0.0;
	bool	positive = false;
	int		cycles = 0;

	Vector3 direction, mean, delta;
	
	int i;

	int first, last;
	
	double N = 0.0;

	// Just make sure that the user gave a positive value for hysteresis.
	hysteresis = fabs( hysteresis );

	// TODO: Should normalize the direction vector here.
	direction[X] = dirX;
	direction[Y] = dirY;
	direction[Z] = dirZ;

	// First we should look for the start and end of the actual movement based on 
	// events such as when the subject reaches the first target. 
	FindAnalysisFrameRange( first, last );
	for ( first = first; first < last; first++ ) if ( acquiredManipulandumState[first].visibility ) break;

	// Compute the mean position. 
	N = 0.0;
	CopyVector( mean, zeroVector );
	for ( i = first; i < last; i++ ) {
		if ( acquiredManipulandumState[i].visibility ) {
			N++;
			AddVectors( mean, mean, acquiredManipulandumState[i].position );
		}
	}
	// If there is no valid position data, signal an error.
	if ( N <= 0.0 ) {
		monitor->SendEvent( "Movement cycles - No valid data." );
		cycles = 0;
		error = true;
	}
	else {
	
		// This is the mean.
		ScaleVector( mean, mean, 1.0 / N );

		// Step through the trajectory, counting positive zero crossings.
		for ( i = first; i < last; i ++ ) {
			// Compute the displacements around the mean.
			if ( acquiredManipulandumState[i].visibility ) {
				SubtractVectors( delta, acquiredManipulandumState[i].position, mean );
				displacement = DotProduct( delta, direction );
			}
			// If on the positive side of the mean, just look for the negative transition.
			if ( positive ) {
				if ( displacement < - hysteresis ) positive = false;
			}
			// If on the negative side, look for the positive transition.
			// If we find one, count another cycle.
			else {
				if ( displacement > hysteresis ) {
					positive = true;
					cycles++;
				}
			}
		}

		// Check if the computed number of cycles is in the desired range.
		error = ( cycles < min_cycles || cycles > max_cycles );

	}

	// If not, signal the error to the subject.
	// Here I take the approach of calling a method to signal the error.
	// We agree instead that the routine should either return a null pointer
	// if there is no error, or return the error message as a static string.
	if ( error ) {
		
		// If the user provided a message to signal a visibilty error, use it.
		// If not, generate a generic message.
		if ( !msg ) msg = "Movement cycles outside range.";
		// The message could be different depending on whether the maniplulandum
		// was not moved enough, or if it just could not be seen.
		if ( N <= 0.0 ) fmt = "%s\n Manipulandum not visible.";
		else fmt = "%s\n Measured cycles: %d\n Desired range: %d - %d\n Direction: < %.2f %.2f %.2f>";
		int response = fSignalError( MB_ABORTRETRYIGNORE, picture, fmt, msg, cycles, min_cycles, max_cycles, dirX, dirY, dirZ );
		
		if ( response == IDABORT ) return( ABORT_EXIT );
		if ( response == IDRETRY ) return( RETRY_EXIT );
		if ( response == IDIGNORE ) return( IGNORE_EXIT );
		
	}
	
	// This is my means of signalling the event.
	monitor->SendEvent( "Number of movements OK.\n Measured: %d\n Desired range: %d - %d\n Direction: < %.2f %.2f %.2f>", 
		cycles, min_cycles, max_cycles, dirX, dirY, dirZ );
	return( NORMAL_EXIT );
	
}