public virtual Object CastRay(ref IndexedVector3 from,ref IndexedVector3 to, ref VehicleRaycasterResult result)
        {
            //	RayResultCallback& resultCallback;
	        ClosestRayResultCallback rayCallback = new ClosestRayResultCallback(ref from,ref to);

	        m_dynamicsWorld.RayTest(ref from, ref to, rayCallback);

            if (rayCallback.HasHit())
            {

                RigidBody body = RigidBody.Upcast(rayCallback.m_collisionObject);
                if (body != null && body.HasContactResponse())
                {
                    result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
                    result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld;
                    result.m_hitNormalInWorld.Normalize();
                    result.m_distFraction = rayCallback.m_closestHitFraction;
                    return body;
                }
            }
            else
            {
                int ibreak = 0;
                ClosestRayResultCallback rayCallback2 = new ClosestRayResultCallback(ref from, ref to);

                m_dynamicsWorld.RayTest(ref from, ref to, rayCallback2);

            }
            rayCallback.Cleanup();
            return null;
        }
        //----------------------------------------------------------------------------------------------

        public virtual void MouseFunc(ref MouseState oldMouseState, ref MouseState newMouseState)
        {
            IndexedVector3 rayTo = GetRayTo(newMouseState.X, newMouseState.Y);

            if (WasReleased(ref oldMouseState,ref newMouseState,2))
            {
                ShootBox(rayTo);
            }
            else if (WasReleased(ref oldMouseState,ref newMouseState,1))
            {
                //apply an impulse
                if (m_dynamicsWorld != null)
                {
                    ClosestRayResultCallback rayCallback = new ClosestRayResultCallback(new IndexedVector3(m_cameraPosition), rayTo);
                    IndexedVector3 ivPos = new IndexedVector3(m_cameraPosition);
                    IndexedVector3 ivTo = new IndexedVector3(rayTo);
                    m_dynamicsWorld.RayTest(ref ivPos,ref ivTo, rayCallback);
                    if (rayCallback.HasHit())
                    {
                        RigidBody body = RigidBody.Upcast(rayCallback.m_collisionObject);
                        if (body != null)
                        {
                            body.SetActivationState(ActivationState.ACTIVE_TAG);
                            IndexedVector3 impulse = rayTo;
                            impulse.Normalize();
                            float impulseStrength = 10f;
                            impulse *= impulseStrength;
                            IndexedVector3 relPos = rayCallback.m_hitPointWorld - body.GetCenterOfMassPosition();
                            body.ApplyImpulse(ref impulse, ref relPos);
                        }
                    }
                }
            }
            else if (newMouseState.LeftButton == ButtonState.Pressed)
            {
                //add a point to point constraint for picking
                if (m_dynamicsWorld != null)
                {

					IndexedVector3 rayFrom;
					if (m_ortho)
					{
						rayFrom = rayTo;
						rayFrom.Z = -100.0f;
					}
					else
					{
						rayFrom = new IndexedVector3(m_cameraPosition);
					}


                    ClosestRayResultCallback rayCallback = new ClosestRayResultCallback(ref rayFrom, ref rayTo);
                    IndexedVector3 ivPos = new IndexedVector3(m_cameraPosition);
                    IndexedVector3 ivTo = new IndexedVector3(rayTo);
                    m_dynamicsWorld.RayTest(ref ivPos, ref ivTo, rayCallback);
                    if (rayCallback.HasHit())
                    {
                        RigidBody body = RigidBody.Upcast(rayCallback.m_collisionObject);
                        if (body != null)
                        {
                            //other exclusions?
                            if (!(body.IsStaticObject() || body.IsKinematicObject()))
                            {
                                pickedBody = body;
                                pickedBody.SetActivationState(ActivationState.DISABLE_DEACTIVATION);


                                IndexedVector3 pickPos = rayCallback.m_hitPointWorld;

                                IndexedVector3 localPivot = body.GetCenterOfMassTransform().Inverse() * pickPos;

                                if (use6Dof)
                                {
                                    IndexedMatrix tr = IndexedMatrix.Identity;
                                    tr._origin = localPivot;
                                    Generic6DofConstraint dof6 = new Generic6DofConstraint(body, ref tr, false);
                                    dof6.SetLinearLowerLimit(new IndexedVector3(0, 0, 0));
                                    dof6.SetLinearUpperLimit(new IndexedVector3(0, 0, 0));
                                    dof6.SetAngularLowerLimit(new IndexedVector3(0, 0, 0));
                                    dof6.SetAngularUpperLimit(new IndexedVector3(0, 0, 0));

                                    m_dynamicsWorld.AddConstraint(dof6);
                                    m_pickConstraint = dof6;

                                    dof6.SetParam(ConstraintParams.BT_CONSTRAINT_STOP_CFM, 0.8f, 0);
                                    dof6.SetParam(ConstraintParams.BT_CONSTRAINT_STOP_CFM, 0.8f, 1);
                                    dof6.SetParam(ConstraintParams.BT_CONSTRAINT_STOP_CFM, 0.8f, 2);
                                    dof6.SetParam(ConstraintParams.BT_CONSTRAINT_STOP_CFM, 0.8f, 3);
                                    dof6.SetParam(ConstraintParams.BT_CONSTRAINT_STOP_CFM, 0.8f, 4);
                                    dof6.SetParam(ConstraintParams.BT_CONSTRAINT_STOP_CFM, 0.8f, 5);

                                    dof6.SetParam(ConstraintParams.BT_CONSTRAINT_STOP_ERP, 0.1f, 0);
                                    dof6.SetParam(ConstraintParams.BT_CONSTRAINT_STOP_ERP, 0.1f, 1);
                                    dof6.SetParam(ConstraintParams.BT_CONSTRAINT_STOP_ERP, 0.1f, 2);
                                    dof6.SetParam(ConstraintParams.BT_CONSTRAINT_STOP_ERP, 0.1f, 3);
                                    dof6.SetParam(ConstraintParams.BT_CONSTRAINT_STOP_ERP, 0.1f, 4);
                                    dof6.SetParam(ConstraintParams.BT_CONSTRAINT_STOP_ERP, 0.1f, 5);
                                }
                                else
                                {
                                    Point2PointConstraint p2p = new Point2PointConstraint(body, ref localPivot);
                                    m_dynamicsWorld.AddConstraint(p2p, false);

                                    p2p.m_setting.m_impulseClamp = mousePickClamping;
                                    p2p.m_setting.m_tau = 0.001f;


                                    if (m_pickConstraint != null)
                                    {
                                        int ibreak = 0;
                                    }
                                    m_pickConstraint = p2p;
                                }
                                //save mouse position for dragging
                                gOldPickingPos = rayTo;
								gHitPos = pickPos;

								gOldPickingDist = (pickPos - rayFrom).Length();

                                //very weak constraint for picking
                            }
                        }
                    }
                }

            }
            else if (WasReleased(ref oldMouseState,ref newMouseState,0))
            {
                if (m_pickConstraint != null && m_dynamicsWorld != null)
                {
                    m_dynamicsWorld.RemoveConstraint(m_pickConstraint);
                    m_pickConstraint = null;
                    //printf("removed constraint %i",gPickingConstraintId);
                    m_pickConstraint = null;
                    pickedBody.ForceActivationState(ActivationState.ACTIVE_TAG);
                    pickedBody.SetDeactivationTime(0f);
                    pickedBody = null;
                }
            }
        }
	public void cast (CollisionWorld cw)
	{
#if USE_BT_CLOCK
		frame_timer.reset ();
#endif //USE_BT_CLOCK

#if BATCH_RAYCASTER
		if (gBatchRaycaster == null)
        {
			return;
        }

		gBatchRaycaster.clearRays ();
		for (int i = 0; i < NUMRAYS_IN_BAR; i++)
		{
			gBatchRaycaster.addRay (source[i], dest[i]);
		}
		gBatchRaycaster.performBatchRaycast ();
		for (int i = 0; i < gBatchRaycaster.getNumRays (); i++)
		{
			const SpuRaycastTaskWorkUnitOut& outResult = (*gBatchRaycaster)[i];
			hit[i].setInterpolate3(source[i],dest[i],outResult.hitFraction);
			normal[i] = outResult.hitNormal;
			normal[i] = normal[i].Normalize();
		}
#else
		for (int i = 0; i < NUMRAYS_IN_BAR; i++)
		{
			ClosestRayResultCallback cb = new ClosestRayResultCallback(source[i], dest[i]);
			
			cw.RayTest (ref source[i], ref dest[i], cb);
			if (cb.HasHit ())
			{
				hit[i] = cb.m_hitPointWorld;
				normal[i] = cb.m_hitNormalWorld;
			    normal[i] = IndexedVector3.Normalize(normal[i]);
			} 
            else 
            {
				hit[i] = dest[i];
				normal[i] = new IndexedVector3(1.0f, 0.0f, 0.0f);
			}

		}
#if USE_BT_CLOCK
		ms += frame_timer.getTimeMilliseconds ();
#endif //USE_BT_CLOCK
		frame_counter++;
		if (frame_counter > 50)
		{
			min_ms = ms < min_ms ? ms : min_ms;
			max_ms = ms > max_ms ? ms : max_ms;
			sum_ms += ms;
			sum_ms_samples++;
			float mean_ms = (float)sum_ms/(float)sum_ms_samples;
            //printf("%d rays in %d ms %d %d %f\n", NUMRAYS_IN_BAR * frame_counter, ms, min_ms, max_ms, mean_ms);
			ms = 0;
			frame_counter = 0;
		}
#endif
	}