/// <summary> /// Whether the plane and a ray intersect and where /// http://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection /// </summary> public bool intersects(ref SSRay ray, out Vector3 intersectPt) { Vector3 n = this.normal; var rayDirDotPlaneN = Vector3.Dot(ray.dir, n); if (Math.Abs(rayDirDotPlaneN) < epsilon) { // rayDirDotPlaneN == 0; ray and the plane are parallel intersectPt = new Vector3(float.NaN); return(false); } else { // plug parametric equation of a line into the plane normal equation // solve (rayPos + rayDir * t - planeP0) dot planeN == 0 // rayDir dot planeN + (rayPos - planeP0) dot planeN == 0 Vector3 p0 = this.pickASurfacePoint(); float t = Vector3.Dot(p0 - ray.pos, n) / rayDirDotPlaneN; if (t < -epsilon) { // this means that the line-plane intersection is behind the ray origin (in the wrong // direction). in the context of a ray this means no intersection intersectPt = new Vector3(float.NaN); return(false); } intersectPt = ray.pos + ray.dir * t; return(true); } }
public void setupInput() { // hook mouse drag input... this.MouseDown += (object sender, MouseButtonEventArgs e) => { this.mouseButtonDown = true; // cast ray for mouse click var clientRect = new System.Drawing.Size(ClientRectangle.Width, ClientRectangle.Height); Vector2 mouseLoc = new Vector2(e.X, e.Y); SSRay ray = OpenTKHelper.MouseToWorldRay( this.scene.ProjectionMatrix, this.scene.InvCameraViewMatrix, clientRect, mouseLoc); // Console.WriteLine("mouse ({0},{1}) unproject to ray ({2})",e.X,e.Y,ray); // scene.addObject(new SSObjectRay(ray)); selectedObject = scene.Intersect(ref ray); }; this.MouseUp += (object sender, MouseButtonEventArgs e) => { this.mouseButtonDown = false; }; this.MouseMove += (object sender, MouseMoveEventArgs e) => { if (this.mouseButtonDown) { // Console.WriteLine("mouse dragged: {0},{1}",e.XDelta,e.YDelta); this.scene.ActiveCamera.MouseDeltaOrient(e.XDelta, e.YDelta); // this.activeModel.MouseDeltaOrient(e.XDelta,e.YDelta); } }; this.MouseWheel += (object sender, MouseWheelEventArgs e) => { // Console.WriteLine("mousewheel {0} {1}",e.Delta,e.DeltaPrecise); SSCameraThirdPerson ctp = scene.ActiveCamera as SSCameraThirdPerson; if (ctp != null) { ctp.followDistance += -e.DeltaPrecise; } }; this.KeyPress += (object sender, KeyPressEventArgs e) => { switch (e.KeyChar) { case 'w': scene.DrawWireFrameMode = SSRenderConfig.NextWireFrameMode(scene.DrawWireFrameMode); updateWireframeDisplayText(scene.DrawWireFrameMode); // if we need single-pass wireframes, set the GLSL uniform variable shaderPgm.Activate(); shaderPgm.u_ShowWireframes = (scene.DrawWireFrameMode == WireframeMode.GLSL_SinglePass); break; } }; }
public override bool preciseIntersect(ref SSRay localRay, out float nearestLocalRayContact) { nearestLocalRayContact = float.PositiveInfinity; foreach (var s in _renderSubMeshes) { float contact; if (s.preciseIntersect(ref localRay, out contact) && contact < nearestLocalRayContact) { nearestLocalRayContact = contact; } } return(nearestLocalRayContact < float.PositiveInfinity); }
protected virtual void mouseDownHandler(object sender, MouseButtonEventArgs e) { if (!base.Focused) { return; } this.mouseButtonDown = true; // cast ray for mouse click var clientRect = new System.Drawing.Size(ClientRectangle.Width, ClientRectangle.Height); Vector2 mouseLoc = new Vector2(e.X, e.Y); SSRay ray = OpenTKHelper.MouseToWorldRay( this.scene.renderConfig.projectionMatrix, this.scene.renderConfig.invCameraViewMatrix, clientRect, mouseLoc); // Console.WriteLine("mouse ({0},{1}) unproject to ray ({2})",e.X,e.Y,ray); // scene.addObject(new SSObjectRay(ray)); selectedObject = scene.Intersect(ref ray); updateWireframeDisplayText(); }
public static bool intersectRayAABox1(SSRay ray, SSAABB box, ref float tnear, ref float tfar) { // r.dir is unit direction vector of ray Vector3 dirfrac = new Vector3(); float t; dirfrac.X = 1.0f / ray.dir.X; dirfrac.Y = 1.0f / ray.dir.Y; dirfrac.Z = 1.0f / ray.dir.Z; // lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner // r.org is origin of ray float t1 = (box.Min.X - ray.pos.X) * dirfrac.X; float t2 = (box.Max.X - ray.pos.X) * dirfrac.X; float t3 = (box.Min.Y - ray.pos.Y) * dirfrac.Y; float t4 = (box.Max.Y - ray.pos.Y) * dirfrac.Y; float t5 = (box.Min.Z - ray.pos.Z) * dirfrac.Z; float t6 = (box.Max.Z - ray.pos.Z) * dirfrac.Z; float tmin = Math.Max(Math.Max(Math.Min(t1, t2), Math.Min(t3, t4)), Math.Min(t5, t6)); float tmax = Math.Min(Math.Min(Math.Max(t1, t2), Math.Max(t3, t4)), Math.Max(t5, t6)); // if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us if (tmax < 0) { t = tmax; return(false); } // if tmin > tmax, ray doesn't intersect AABB if (tmin > tmax) { t = tmax; return(false); } t = tmin; return(true); }
public virtual bool hitTest(SSpaceMissileData missile, out Vector3 hitLocation) { var mParams = missile.parameters; float simStep = missile.parameters.simulationStep; float nextTickDist = missile.velocity.LengthFast * simStep; float testDistSq = (nextTickDist + targetObj.worldBoundingSphereRadius); testDistSq *= testDistSq; float toTargetDistSq = (targetObj.Pos - missile.position).LengthSquared; if (toTargetDistSq <= mParams.atTargetDistance * mParams.atTargetDistance) { hitLocation = missile.position; return(true); } else if (testDistSq > toTargetDistSq) { Vector3 velNorm = (missile.velocity - this.velocity); velNorm.NormalizeFast(); SSRay ray = new SSRay(missile.position, velNorm); float rayDistance = 0f; if (targetObj.PreciseIntersect(ref ray, ref rayDistance)) { if (rayDistance - nextTickDist < mParams.atTargetDistance) { hitLocation = missile.position + this.velocity * simStep + velNorm * rayDistance; return(true); } } } hitLocation = new Vector3(float.PositiveInfinity); return(false); }
public void update(float absoluteTimeS) { float periodicT = absoluteTimeS + _periodicTOffset; var laserParams = _laser.parameters; // update variables _interferenceOffset = laserParams.middleInterferenceUFunc(periodicT); _periodicIntensity = laserParams.intensityPeriodicFunction(periodicT); _periodicIntensity *= laserParams.intensityModulation(periodicT); // evaluate start position for this update Vector3 beamOriginLocal = Vector3.Zero; if (_laser.beamOriginPresets != null && _laser.beamOriginPresets.Count > 1) { var presetIdx = _beamId; if (presetIdx >= _laser.beamOriginPresets.Count) { presetIdx %= _laser.beamOriginPresets.Count; } beamOriginLocal = _laser.beamOriginPresets [presetIdx]; } _beamStartWorld = _laser.txfmSourceToWorld(beamOriginLocal); _beamEndWorld = _laser.txfmTargetToWorld(Vector3.Zero); Vector3 beamDirWorld = (_beamEndWorld - _beamStartWorld).Normalized(); Vector3 laserXaxisWorld, laserYaxisWorld; OpenTKHelper.TwoPerpAxes(beamDirWorld, out laserXaxisWorld, out laserYaxisWorld); // local placement to start start placement in world coordinates Vector3 localPlacement = laserParams.getBeamPlacementVector(_beamId, laserParams.numBeams, absoluteTimeS); Vector3 startPlacement = localPlacement * laserParams.beamStartPlacementScale; Vector3 startPlacementWorldOffset = laserXaxisWorld * startPlacement.X + laserYaxisWorld * startPlacement.Y + beamDirWorld * startPlacement.Z; _beamStartWorld += startPlacementWorldOffset; // end position in world coordinates including drift; before intersection test float driftX = laserParams.driftXFunc (periodicT); float driftY = laserParams.driftYFunc (periodicT); var driftMod = laserParams.driftModulationFunc (periodicT); Vector3 driftedEndPlacement = laserParams.beamDestSpread * localPlacement + new Vector3(driftX, driftY, 0f) * driftMod; Vector3 endPlacementWorldOffset = laserXaxisWorld * driftedEndPlacement.X + laserYaxisWorld * driftedEndPlacement.Y + beamDirWorld * driftedEndPlacement.Z; _beamEndWorld += endPlacementWorldOffset; _hitsAnObstacle = false; // intersects with any of the intersecting objects if (_laser.beamObstacles != null) { //if (false) { // TODO note the code below is slow. Wen you start having many lasers // this will cause problems. Consider using BVH for ray tests or analyzing // intersection math. float closestDistance = float.PositiveInfinity; foreach (var obj in _laser.beamObstacles) { float distanceToInterect; var ray = new SSRay(_beamStartWorld, (_beamEndWorld - _beamStartWorld).Normalized()); if (obj.Intersect(ref ray, out distanceToInterect)) { if (distanceToInterect < closestDistance) { closestDistance = distanceToInterect; _hitsAnObstacle = true; _beamEndWorld = _beamStartWorld + ray.dir * closestDistance; } } } } }
public List <ssBVHNode <GO> > traverse(SSRay ray) { float tnear = 0f, tfar = 0f; return(traverse(box => OpenTKHelper.intersectRayAABox1(ray, box, ref tnear, ref tfar))); }
public void update(float absoluteTimeS) { float periodicT = absoluteTimeS + _periodicTOffset; var laserParams = _laser.parameters; // update variables _interferenceOffset = laserParams.middleInterferenceUFunc(periodicT); _periodicIntensity = laserParams.intensityPeriodicFunction(periodicT); _periodicIntensity *= laserParams.intensityModulation(periodicT); // evaluate start position for this update Vector3 beamOriginLocal = Vector3.Zero; if (_laser.beamOriginPresets != null && _laser.beamOriginPresets.Count > 1) { var presetIdx = _beamId; if (presetIdx >= _laser.beamOriginPresets.Count) { presetIdx %= _laser.beamOriginPresets.Count; } beamOriginLocal = _laser.beamOriginPresets [presetIdx]; } _beamStartWorld = _laser.txfmSourceToWorld(beamOriginLocal); _beamEndWorld = _laser.txfmTargetToWorld(Vector3.Zero); Vector3 beamDirWorld = (_beamEndWorld - _beamStartWorld).Normalized(); Vector3 laserXaxisWorld, laserYaxisWorld; OpenTKHelper.TwoPerpAxes(beamDirWorld, out laserXaxisWorld, out laserYaxisWorld); // local placement to start start placement in world coordinates Vector3 localPlacement = laserParams.getBeamPlacementVector(_beamId, laserParams.numBeams, absoluteTimeS); Vector3 startPlacement = localPlacement * laserParams.beamStartPlacementScale; Vector3 startPlacementWorldOffset = laserXaxisWorld * startPlacement.X + laserYaxisWorld * startPlacement.Y + beamDirWorld * startPlacement.Z; _beamStartWorld += startPlacementWorldOffset; // end position in world coordinates including drift; before intersection test float driftX = laserParams.driftXFunc(periodicT); float driftY = laserParams.driftYFunc(periodicT); var driftMod = laserParams.driftModulationFunc(periodicT); Vector3 driftedEndPlacement = laserParams.beamDestSpread * localPlacement + new Vector3(driftX, driftY, 0f) * driftMod; Vector3 endPlacementWorldOffset = laserXaxisWorld * driftedEndPlacement.X + laserYaxisWorld * driftedEndPlacement.Y + beamDirWorld * driftedEndPlacement.Z; _beamEndWorld += endPlacementWorldOffset; _hitsAnObstacle = false; // intersects with any of the intersecting objects if (_laser.beamObstacles != null) { //if (false) { // TODO note the code below is slow. Wen you start having many lasers // this will cause problems. Consider using BVH for ray tests or analyzing // intersection math. float closestDistance = float.PositiveInfinity; foreach (var obj in _laser.beamObstacles) { float distanceToInterect; var ray = new SSRay(_beamStartWorld, (_beamEndWorld - _beamStartWorld).Normalized()); if (obj.Intersect(ref ray, out distanceToInterect)) { if (distanceToInterect < closestDistance) { closestDistance = distanceToInterect; _hitsAnObstacle = true; _beamEndWorld = _beamStartWorld + ray.dir * closestDistance; } } } } }
public virtual bool hitTest(SSpaceMissileData missile, out Vector3 hitLocation) { var mParams = missile.cluster.parameters; float simStep = missile.cluster.parameters.simulationStep; float nextTickDist = missile.velocity.LengthFast * simStep; float testDistSq = (nextTickDist + targetObj.worldBoundingSphereRadius); testDistSq *= testDistSq; float toTargetDistSq = (targetObj.Pos - missile.position).LengthSquared; if (toTargetDistSq <= mParams.atTargetDistance * mParams.atTargetDistance) { hitLocation = missile.position; return true; } else if (testDistSq > toTargetDistSq) { Vector3 velNorm = (missile.velocity - this.velocity); velNorm.NormalizeFast(); SSRay ray = new SSRay (missile.position, velNorm); float rayDistance = 0f; if (targetObj.PreciseIntersect(ref ray, ref rayDistance)) { if (rayDistance - nextTickDist < mParams.atTargetDistance) { hitLocation = missile.position + this.velocity * simStep + velNorm * rayDistance; return true; } } } hitLocation = new Vector3(float.PositiveInfinity); return false; }