private Vector3 XXXSteerToEvadeAllDefenders() { // sum up weighted evasion Vector3 evade = Vector3.Zero; foreach (CtfEnemy e in Plugin.CtfEnemies) { Vector3 eOffset = e.Position - Position; float eDistance = eOffset.Length(); // xxx maybe this should take into account e's heading? xxx float timeEstimate = 0.5f * eDistance / e.Speed; //xxx Vector3 eFuture = e.PredictFuturePosition(timeEstimate); // annotation annotation.CircleXZ(e.Radius, eFuture, Globals.EvadeColor.ToVector3().FromXna(), 20); // steering to flee from eFuture (enemy's future position) Vector3 flee = SteerForFlee(eFuture); float eForwardDistance = Vector3.Dot(Forward, eOffset); float behindThreshold = Radius * -2; float distanceWeight = 4 / eDistance; float forwardWeight = ((eForwardDistance > behindThreshold) ? 1.0f : 0.5f); Vector3 adjustedFlee = flee * distanceWeight * forwardWeight; evade += adjustedFlee; } return(evade); }
public override void Redraw(float currentTime, float elapsedTime) { // selected vehicle (user can mouse click to select another) IVehicle selected = Demo.SelectedVehicle; // vehicle nearest mouse (to be highlighted) IVehicle nearMouse = Demo.VehicleNearestToMouse(); // update camera Demo.UpdateCamera(elapsedTime, selected); // draw "ground plane" centered between base and selected vehicle Vector3 goalOffset = Globals.HomeBaseCenter - Demo.Camera.Position; Vector3 goalDirection = Vector3.Normalize(goalOffset); Vector3 cameraForward = Demo.Camera.xxxls().Forward; float goalDot = Vector3.Dot(cameraForward, goalDirection); float blend = Utilities.RemapIntervalClip(goalDot, 1, 0, 0.5f, 0); Vector3 gridCenter = Vector3.Lerp(selected.Position, Globals.HomeBaseCenter, blend); Demo.GridUtility(gridCenter); // draw the seeker, obstacles and home base CtfSeeker.Draw(); DrawObstacles(); DrawHomeBase(); // draw each enemy foreach (CtfEnemy enemy in CtfEnemies) { enemy.Draw(); } // highlight vehicle nearest mouse Demo.HighlightVehicleUtility(nearMouse); }
public Vector3 SteerToEvadeAllDefenders() { Vector3 evade = Vector3.Zero; float goalDistance = Vector3.Distance(Globals.HomeBaseCenter, Position); // sum up weighted evasion foreach (CtfEnemy e in Plugin.CtfEnemies) { Vector3 eOffset = e.Position - Position; float eDistance = eOffset.Length(); float eForwardDistance = Vector3.Dot(Forward, eOffset); float behindThreshold = Radius * 2; bool behind = eForwardDistance < behindThreshold; if ((!behind) || (eDistance < 5)) { if (eDistance < (goalDistance * 1.2)) //xxx { // const float timeEstimate = 0.5f * eDistance / e.speed;//xxx float timeEstimate = 0.15f * eDistance / e.Speed; //xxx Vector3 future = e.PredictFuturePosition(timeEstimate); annotation.CircleXZ(e.Radius, future, Globals.EvadeColor.ToVector3().FromXna(), 20); // xxx Vector3 offset = future - Position; Vector3 lateral = Vector3Helpers.PerpendicularComponent(offset, Forward); float d = lateral.Length(); float weight = -1000 / (d * d); evade += (lateral / d) * weight; } } } return(evade); }
public override Transform Step(double time, LocationOptions options) { var dt = (float)(time - _time); var v = _vel * dt + 0.5f * _acc * dt * dt; if (Vec3.Dot(v, v) == 0.0) { return(base.Step(time, options)); } position = _pos + v; if (!options.RotationOptions.HasFlag(RotationOptions.AlignToVelocity)) { return(base.Step(time, options)); } v = _vel + _acc * dt; v.Normalize(); var n = new Vector3(local_orientation.v13, local_orientation.v23, local_orientation.v33); var u = new Vector3(v.x, v.y, v.z); var proj = u - Vector3.Dot(u, n) * n; var north = new Vector3(local_orientation.v12, local_orientation.v22, local_orientation.v32); var dot = Vector3.Dot(proj, north); var det = Vector3.Dot(n, Vector3.Cross(north, proj)); _euler.y = -(float)Math.Atan2(det, dot); return(base.Step(time, options)); }
public static NQuaternion GetDeltaQuaternionWithDirectionVectors(NVector3 a, NVector3 b) { var dot = NVector3.Dot(a, b); if (dot < -0.999999) { var cross = NVector3.Cross(a, b); if (cross.Length() < 0.000001) { cross = NVector3.Cross(NVector3.UnitY, a); } cross = NVector3.Normalize(cross); return(NQuaternion.CreateFromAxisAngle(cross, Pi)); } else if (dot > 0.999999) { return(new NQuaternion(0, 0, 0, 1)); } else { var xyz = NVector3.Cross(a, b); var w = (float)(Math.Sqrt(a.Length() * a.Length() + b.Length() * b.Length()) + dot); return(new NQuaternion(xyz.X, xyz.Y, xyz.Z, w)); } }
public RangeFit(ColourSet colours, CompressionOptions flags) : base(colours) { // initialise the metric bool perceptual = ((flags & CompressionOptions.ColourMetricPerceptual) != 0); m_metric = perceptual ? new Vec3(0.2126f, 0.7152f, 0.0722f) : Vec3.One; // initialise the best error m_besterror = float.MaxValue; // cache some values var count = m_colours.Count; var values = m_colours.Points; var weights = m_colours.Weights; // get the covariance matrix Sym3x3 covariance = Sym3x3.ComputeWeightedCovariance(count, values, weights); // compute the principle component Vec3 principle = Sym3x3.ComputePrincipleComponent(covariance); // get the min and max range as the codebook endpoints Vec3 start = Vec3.Zero; Vec3 end = Vec3.Zero; if (count > 0) { float min, max; // compute the range start = end = values[0]; min = max = Vec3.Dot(values[0], principle); for (int i = 1; i < count; ++i) { float val = Vec3.Dot(values[i], principle); if (val < min) { start = values[i]; min = val; } else if (val > max) { end = values[i]; max = val; } } } // clamp the output to [0, 1] start = start.Clamp(Vec3.Zero, Vec3.One); end = end.Clamp(Vec3.Zero, Vec3.One); // clamp to the grid and save m_start = (GRID * start + HALF).Truncate() * GRIDRCP; m_end = (GRID * end + HALF).Truncate() * GRIDRCP; }
public override RayCastResult Intersection(Ray ray, float nowbest) { { float distance = (Position - ray.Origin).Length(); if (nowbest + R < distance) { return(null); } } Vector3f A = ray.Origin, B = ray.Direction, C = Position; Float a = Vector3f.Dot(B, B); Float b = Vector3f.Dot(B, (A - C)) * 2.0f; Float c = (A - C).LengthSquared() - R * R; float drt = b * b - 4 * a * c; if (drt < 0) { return(null); } drt = Math.Sqrt(drt); float x1 = (-b + drt) / a / 2; float x2 = (-b - drt) / a / 2; if (x1 < 0 && x2 < 0) { return(null); } float d; if (x1 > 0 && x2 > 0) { d = Math.Max(x1, x2); } else if (x1 > 0) { d = x1; } else { d = x2; } RayCastResult result = new RayCastResult(); //result.happened = true; result.obj = this; result.material = Material; result.coords = ray.Origin + ray.Direction * d; result.distance = d; result.normal = Vector3f.Normalize(result.coords - Position); return(result); }
public override RayCastResult Intersection(Ray ray, float nowbest) { if (ray.OriginObject == this) { return(null); } { (bool happened, Float mint) = BoundBox.Intersection(ray); if (!happened || mint > nowbest) // 未相交 或 当前最小解已不是最优 { return(null); } } Float u, v, t_tmp = 0; Vector3f pvec = Vector3f.Cross(ray.Direction, e2); // S1 Float det = Vector3f.Dot(e1, pvec); Float det_inv = 1.0f / det; Vector3f tvec = ray.Origin - v0; // S u = Vector3f.Dot(tvec, pvec) * det_inv; if (u < 0 || u > 1) { return(null); } Vector3f qvec = Vector3f.Cross(tvec, e1); // S2 v = Vector3f.Dot(ray.Direction, qvec) * det_inv; if (v < 0 || u + v > 1) { return(null); } t_tmp = Vector3f.Dot(e2, qvec) * det_inv; if (t_tmp < 0) { return(null); } RayCastResult result = new RayCastResult(); result.distance = t_tmp; result.obj = this; result.coords = ray.Origin + t_tmp * ray.Direction; result.uv = new Vector2f(u, v); result.normal = Tools.UVMerge(u, v, n0, n1, n2); result.internalPoint = (Vector3f.Dot(result.normal, ray.Direction) > 0); if (result.internalPoint) { result.normal = -result.normal; } return(result); }
/// <summary> /// 返回折射光方向 /// </summary> /// <param name="dir"></param> /// <param name="niOverNt">入射折射率/出射折射率</param> /// <returns></returns> public static Vector3f Refract(Vector3f dir, Vector3f normal, float niOverNt) { dir = -dir; Float cosAlpha = Vector3f.Dot(dir, normal); Float sinAlphaSq = 1.0f - cosAlpha * cosAlpha; Float sinBetaSq = niOverNt * niOverNt * sinAlphaSq; Float cosBetaSq = 1.0f - sinBetaSq; Float cosBeta = Math.Sqrt(cosBetaSq); Vector3f re = ((normal * cosAlpha) - dir) * niOverNt - normal * cosBeta; return(re); }
public static float Angle(this Vector3d A, Vector3d B) { float vDot = Vector3d.Dot(A, B) / (A.Length() * B.Length()); if (vDot < -1.0f) { vDot = -1.0f; } if (vDot > 1.0f) { vDot = 1.0f; } return((float)Math.Acos(vDot)); }
// called when steerToAvoidCloseNeighbors decides steering is required public void AnnotateAvoidCloseNeighbor(IVehicle other) { // draw the word "Ouch!" above colliding vehicles bool headOn = Vector3.Dot(Forward, other.Forward) < 0; Color green = new Color((byte)(255.0f * 0.4f), (byte)(255.0f * 0.8f), (byte)(255.0f * 0.1f)); Color red = new Color((byte)(255.0f * 1), (byte)(255.0f * 0.1f), 0); Color color = headOn ? red : green; String text = headOn ? "OUCH!" : "pardon me"; Vector3 location = Position + new Vector3(0, 0.5f, 0); if (annotation.IsEnabled) { Drawing.Draw2dTextAt3dLocation(text, location, color); } }
//--------------------------------OTHERS----------------------------------------// /** * Computes the distance from the line point to another point * * @param otherPoint the point to compute the distance from the line point. The point * is supposed to be on the same line. * @return points distance. If the point submitted is behind the direction, the * distance is negative */ public double computePointToPointDistance(Point3d otherPoint) { //float distance = otherPoint.distance(point); float distance = Vector3d.Distance(otherPoint, point); Vector3d vec = Vector3d.Normalize(new Vector3d(otherPoint.X - point.X, otherPoint.Y - point.Y, otherPoint.Z - point.Z)); if (Vector3d.Dot(vec, direction) < 0) { return(-distance); } else { return(distance); } }
/// <summary> /// 返回折射光方向和能量强度 /// </summary> /// <param name="dir"></param> /// <param name="niOverNt"></param> /// <returns></returns> public static (float, Vector3) Refract(Vector3 dir, Vector3 normal, float niOverNt) { dir = -Vector3.Normalize(dir); float cosAlpha = Vector3.Dot(dir, normal); float discriminant = 1.0f - niOverNt * niOverNt * (1.0f - cosAlpha * cosAlpha); if (discriminant > 0) { float cosGamma = MathF.Sqrt(discriminant); Vector3 re = ((normal * cosAlpha) - dir) * niOverNt - normal * cosGamma; return(1.0f - Schlick(cosAlpha, niOverNt), re); } else { return(float.NegativeInfinity, Vector3.Zero); } }
private bool ConstructOrdering(Vec3 axis) { // cache some values var count = m_colours.Count; var values = m_colours.Points; // build the list of dot products var dps = new float[count]; for (int i = 0; i < count; ++i) { dps[i] = Vec3.Dot(values[i], axis); m_order[i] = (Byte)i; } // stable sort using them for (int i = 0; i < dps.Length; ++i) { for (int j = i; j > 0 && dps[j] < dps[j - 1]; --j) { dps.SwapElements(j, j - 1); m_order.SwapElements(j, j - 1); } } // copy the ordering and weight all the points var unweighted = m_colours.Points; var weights = m_colours.Weights; for (int i = 0; i < count; ++i) { int j = m_order[i]; m_weights[i] = weights[j]; m_unweighted[i] = new Vec4(unweighted[j], 1); m_weighted[i] = m_unweighted[i] * m_weights[i]; } return(true); }
virtual public Transform Step(double time, LocationOptions options) { Clamp(options); var up = new Vector3(normal.x, normal.y, -normal.z); Vector3 east = new Vector3(local_orientation.v11, local_orientation.v21, local_orientation.v31);; Vector3 north; if (options.RotationOptions.HasFlag(RotationOptions.AlignToSurface)) { east = Vector3.Normalize(east - (Vector3.Dot(east, up) * up)); north = Vector3.Cross(east, up); } else { north = new Vector3(-local_orientation.v12, -local_orientation.v22, -local_orientation.v32); } var m = new Matrix4x4(east.X, east.Y, east.Z, 0, up.X, up.Y, up.Z, 0, north.X, north.Y, north.Z, 0, 0, 0, 0, 1); var qm = Quaternion.CreateFromRotationMatrix(m); var r = qm * Rotation; return(new Transform { Pos = { X = (float)position.x, Y = (float)position.y, Z = (float)position.z }, Rot = r }); }
private bool ConstructOrdering(Vec3 axis, int iteration) { // cache some values var count = m_colours.Count; var values = m_colours.Points; var orderIndex = 16 * iteration; // build the list of dot products var dps = new float[count]; for (int i = 0; i < count; ++i) { dps[i] = Vec3.Dot(values[i], axis); m_order[orderIndex + i] = (Byte)i; } // stable sort using them for (int i = 0; i < dps.Length; ++i) { for (int j = i; j > 0 && dps[j] < dps[j - 1]; --j) { dps.SwapElements(j, j - 1); m_order.SwapElements(orderIndex + j, orderIndex + j - 1); } } // check this ordering is unique for (int it = 0; it < iteration; ++it) { var prevIdx = 16 * it; bool same = true; for (int i = 0; i < count; ++i) { if (m_order[orderIndex + i] != m_order[prevIdx + i]) { same = false; break; } } if (same) { return(false); } } // copy the ordering and weight all the points var unweighted = m_colours.Points; var weights = m_colours.Weights; m_xsum_wsum = Vec4.Zero; for (int i = 0; i < count; ++i) { int j = m_order[orderIndex + i]; var p = new Vec4(unweighted[j], 1); var w = new Vec4(weights[j]); var x = p * w; m_points_weights[i] = x; m_xsum_wsum += x; } return(true); }
private void CreateGeometry() { // Create box Geometry box = new Geometry(OptixContext); box.PrimitiveCount = 1; box.BoundingBoxProgram = new OptixProgram(OptixContext, boxPath, "box_bounds");; box.IntersectionProgram = new OptixProgram(OptixContext, boxPath, "box_intersect");; box["boxmin"].Set(-2.0f, 0.0f, -2.0f); box["boxmax"].Set(2.0f, 7.0f, 2.0f); Geometry chull = null; if (mTutorial >= 9) { chull = new Geometry(OptixContext); chull.PrimitiveCount = 1u; chull.BoundingBoxProgram = new OptixProgram(OptixContext, shaderPath, "chull_bounds"); chull.IntersectionProgram = new OptixProgram(OptixContext, shaderPath, "chull_intersect"); uint nsides = 6; float radius = 1; Vector3 xlate = new Vector3(-1.4f, 0, -3.7f); BufferDesc desc = new BufferDesc() { Width = nsides + 2u, Type = BufferType.Input, Format = Format.Float4 }; Buffer chullBuffer = new Buffer(OptixContext, desc); float angle = 0.0f; BufferStream stream = chullBuffer.Map(); for (uint i = 0; i < nsides; i++) { angle = (float)i / (float)nsides * (float)Math.PI * 2.0f; float x = (float)Math.Cos(angle); float y = (float)Math.Sin(angle); stream.Write <Vector4>(Utils.CreatePlane(new Vector3(x, 0, y), new Vector3(x * radius, 0, y * radius) + xlate)); } float min = 0.02f; float max = 3.5f; angle = 5.0f / (float)nsides * (float)Math.PI * 2.0f; stream.Write <Vector4>(Utils.CreatePlane(new Vector3(0, -1, 0), new Vector3(0, min, 0) + xlate)); stream.Write <Vector4>(Utils.CreatePlane(new Vector3((float)Math.Cos(angle), 0.7f, (float)Math.Sin(angle)), new Vector3(0, max, 0) + xlate)); chullBuffer.Unmap(); chull["planes"].Set(chullBuffer); chull["chull_bbmin"].Set(-radius + xlate.X, min + xlate.Y, -radius + xlate.Z); chull["chull_bbmax"].Set(radius + xlate.X, max + xlate.Y, radius + xlate.Z); } // Floor geometry Geometry parallelogram = new Geometry(OptixContext); parallelogram.PrimitiveCount = 1; parallelogram.BoundingBoxProgram = new OptixProgram(OptixContext, parrallelPath, "bounds");; parallelogram.IntersectionProgram = new OptixProgram(OptixContext, parrallelPath, "intersect");; Vector3 anchor = new Vector3(-64.0f, 0.01f, -64.0f); Vector3 v1 = new Vector3(128.0f, 0.0f, 0.0f); Vector3 v2 = new Vector3(0.0f, 0.0f, 128.0f); Vector3 normal = Vector3.Normalize(Vector3.Cross(v2, v1)); v1 *= 1.0f / (v1.LengthSquared()); v2 *= 1.0f / (v2.LengthSquared()); float d = Vector3.Dot(normal, anchor); Vector4 plane = new Vector4(normal, d); parallelogram["plane"].Set(ref plane); parallelogram["v1"].Set(ref v1); parallelogram["v2"].Set(ref v2); parallelogram["anchor"].Set(ref anchor); string boxMtrlName = mTutorial >= 8 ? "box_closest_hit_radiance" : "closest_hit_radiance"; string floorMtrlName = mTutorial >= 4 ? "floor_closest_hit_radiance" : "closest_hit_radiance"; Material boxMtrl = new Material(OptixContext); boxMtrl.SetSurfaceProgram(0, new SurfaceProgram(OptixContext, RayHitType.Closest, shaderPath, boxMtrlName)); if (mTutorial >= 3) { boxMtrl.SetSurfaceProgram(1, new SurfaceProgram(OptixContext, RayHitType.Any, shaderPath, "any_hit_shadow")); } boxMtrl["Ka"].Set(0.3f, 0.3f, 0.3f); boxMtrl["Kd"].Set(0.6f, 0.7f, 0.8f); boxMtrl["Ks"].Set(0.8f, 0.9f, 0.8f); boxMtrl["phong_exp"].Set(88.0f); boxMtrl["reflectivity_n"].Set(0.2f, 0.2f, 0.2f); Material floorMtrl = new Material(OptixContext); floorMtrl.SetSurfaceProgram(0, new SurfaceProgram(OptixContext, RayHitType.Closest, shaderPath, floorMtrlName)); if (mTutorial >= 3) { floorMtrl.SetSurfaceProgram(1, new SurfaceProgram(OptixContext, RayHitType.Any, shaderPath, "any_hit_shadow")); } floorMtrl["Ka"].Set(0.3f, 0.3f, 0.1f); floorMtrl["Kd"].Set(194 / 255.0f * .6f, 186 / 255.0f * .6f, 151 / 255.0f * .6f); floorMtrl["Ks"].Set(0.4f, 0.4f, 0.4f); floorMtrl["reflectivity"].Set(0.1f, 0.1f, 0.1f); floorMtrl["reflectivity_n"].Set(0.05f, 0.05f, 0.05f); floorMtrl["phong_exp"].Set(88.0f); floorMtrl["tile_v0"].Set(0.25f, 0, .15f); floorMtrl["tile_v1"].Set(-.15f, 0, 0.25f); floorMtrl["crack_color"].Set(0.1f, 0.1f, 0.1f); floorMtrl["crack_width"].Set(0.02f); Material glassMtrl = null; if (chull != null) { glassMtrl = new Material(OptixContext); glassMtrl.SetSurfaceProgram(0, new SurfaceProgram(OptixContext, RayHitType.Closest, shaderPath, "glass_closest_hit_radiance")); glassMtrl.SetSurfaceProgram(1, new SurfaceProgram(OptixContext, RayHitType.Any, shaderPath, mTutorial > 9 ? "glass_any_hit_shadow" : "any_hit_shadow")); Vector3 extinction = new Vector3(.80f, .89f, .75f); glassMtrl["importance_cutoff"].Set(1e-2f); glassMtrl["cutoff_color"].Set(0.34f, 0.55f, 0.85f); glassMtrl["fresnel_exponent"].Set(3.0f); glassMtrl["fresnel_minimum"].Set(0.1f); glassMtrl["fresnel_maximum"].Set(1.0f); glassMtrl["refraction_index"].Set(1.4f); glassMtrl["refraction_color"].Set(1.0f, 1.0f, 1.0f); glassMtrl["reflection_color"].Set(1.0f, 1.0f, 1.0f); glassMtrl["refraction_maxdepth"].Set(100); glassMtrl["reflection_maxdepth"].Set(100); glassMtrl["extinction_constant"].Set((float)Math.Log(extinction.X), (float)Math.Log(extinction.Y), (float)Math.Log(extinction.Z)); glassMtrl["shadow_attenuation"].Set(0.4f, 0.7f, 0.4f); } GeometryInstance boxInst = new GeometryInstance(OptixContext); boxInst.Geometry = box; boxInst.AddMaterial(boxMtrl); GeometryInstance parallelInst = new GeometryInstance(OptixContext); parallelInst.Geometry = parallelogram; parallelInst.AddMaterial(floorMtrl); GeometryGroup group = new GeometryGroup(OptixContext); group.AddChild(boxInst); group.AddChild(parallelInst); if (chull != null) { GeometryInstance chullInst = new GeometryInstance(OptixContext); chullInst.Geometry = chull; chullInst.AddMaterial(glassMtrl); group.AddChild(chullInst); } group.Acceleration = new Acceleration(OptixContext, AccelBuilder.Bvh, AccelTraverser.Bvh); OptixContext["top_object"].Set(group); OptixContext["top_shadower"].Set(group); }
/** * Classifies the face based on the ray trace technique * * @param object object3d used to compute the face status */ public void rayTraceClassify(Object3D obj) { //creating a ray starting starting at the face baricenter going to the normal direction Point3d p0 = new Point3d(); p0.X = (v1.X + v2.X + v3.X) / 3.0f; p0.Y = (v1.Y + v2.Y + v3.Y) / 3.0f; p0.Z = (v1.Z + v2.Z + v3.Z) / 3.0f; Line ray = new Line(getNormal(), p0); bool success; double dotProduct, distance; Point3d?intersectionPoint; Face closestFace = null; double closestDistance; do { success = true; closestDistance = Double.MaxValue; //for each face from the other solid... for (int i = 0; i < obj.getNumFaces(); i++) { Face face = obj.getFace(i); //dotProduct = face.getNormal().dot(ray.getDirection()); dotProduct = Vector3d.Dot(face.getNormal(), ray.getDirection()); intersectionPoint = ray.computePlaneIntersection(face.getNormal(), face.v1.getPosition()); //if ray intersects the plane... if (intersectionPoint != null) { distance = ray.computePointToPointDistance(intersectionPoint.Value); //if ray lies in plane... if (Math.Abs(distance) < TOL && Math.Abs(dotProduct) < TOL) { //disturb the ray in order to not lie into another plane ray.perturbDirection(); success = false; break; } //if ray starts in plane... if (Math.Abs(distance) < TOL && Math.Abs(dotProduct) > TOL) { //if ray intersects the face... if (face.hasPoint(intersectionPoint.Value)) { //faces coincide closestFace = face; closestDistance = 0; break; } } //if ray intersects plane... else if (Math.Abs(dotProduct) > TOL && distance > TOL) { if (distance < closestDistance) { //if ray intersects the face; if (face.hasPoint(intersectionPoint.Value)) { //this face is the closest face untill now closestDistance = distance; closestFace = face; } } } } } } while (success == false); //none face found: outside face if (closestFace == null) { status = OUTSIDE; } //face found: test dot product else { //dotProduct = closestFace.getNormal().dot(ray.getDirection()); dotProduct = Vector3d.Dot(closestFace.getNormal(), ray.getDirection()); //distance = 0: coplanar faces if (Math.Abs(closestDistance) < TOL) { if (dotProduct > TOL) { status = SAME; } else if (dotProduct < -TOL) { status = OPPOSITE; } } //dot product > 0 (same direction): inside face else if (dotProduct > TOL) { status = INSIDE; } //dot product < 0 (opposite direction): outside face else if (dotProduct < -TOL) { status = OUTSIDE; } } }
/// <summary> /// 相交点辐射光 /// </summary> /// <param name="point"></param> /// <param name="normal"></param> /// <param name="deep"></param> /// <returns></returns> public virtual Light IntersectLight(Vector3 point, Vector3 dir, Vector3 normal, int deep) { #if RayDebugger SceneDebug Debugger = Scene.debugger; if (Debugger != null) { Debugger.BeginBranch(point); } #endif Light returnlight = default; // 发光体返回发光颜色 if (Material.LightAble) { returnlight = Material.LightColor; goto returnPoint; } // 递归深度极限 if (deep <= 1) { returnlight = Material.BaseColor * 0.3f; goto returnPoint; } dir = Vector3.Normalize(dir); bool IsBackFace = false; if (Vector3.Dot(dir, normal) > 0) // 背面 { IsBackFace = true; normal = -normal; } #region 计算追踪光线总数 int traceRayNum = RenderConfiguration.Configurations.ReflectSmapingLevel - RenderConfiguration.Configurations.RayTraceDeep + deep; { traceRayNum = (int)(traceRayNum * Material.AMetalDegree); if (traceRayNum < 1) { traceRayNum = 1; } traceRayNum = traceRayNum * 3 - 2; } #endregion #region 计算折射光 Light refractl = default; // 折射光 float refractPower = 0.0f; // 折射光强度 if (Material.IsTransparent) { float riindex = Material.RefractiveIndices; if (!IsBackFace) { riindex = 1.0f / riindex; } // 计算折射光线 (float pow, Vector3 rdir) = Tools.Refract(dir, normal, riindex); if (pow < 0) { goto endRefract; } refractPower = pow * Material.TransparentIndex; int raycount = (int)(traceRayNum * refractPower); traceRayNum -= raycount; float randomScale = Material.AMetalDegree * Material.AMetalDegree * 0.5f; //raycount = (int)(traceRayNum * randomScale); //raycount = (int)(traceRayNum * Material.AMetalDegree); if (raycount < 1 && refractPower > 0.00001) { raycount = 1; } if (raycount == 0) { refractl = Material.BaseColor; goto endRefract; } rdir = normal * randomScale + rdir * (1.0f - randomScale); for (int nsmap = 0; nsmap < raycount; nsmap++) { Vector3 raydir = Tools.RandomPointInSphere() * randomScale + rdir; Ray r = new Ray(point, raydir); //Console.WriteLine('\t' + this.Name + " [refract] : " + r); (Light c, float distance) = Scene.Light(r, deep - 1, this); if (IsBackFace) //内部光线,进行吸收计算 { float xsl = Math.Log(distance + 1.0f) + 1.0f; refractl *= Material.BaseColor / xsl; } refractl += c; } refractl /= raycount; } endRefract: #endregion #region 计算反射光 Light reflectl = default; // 反射光 { int raycount = traceRayNum; if (raycount < 1) { if (refractPower < 0.99f) { raycount = 1; } else { reflectl = Material.BaseColor; goto endReflact; } } Vector3 spO; { //Vector3 spRO = Tools.Reflect(dir, normal); Vector3 spRO = Vector3.Reflect(dir, normal); //spO = normal * (1.0f - Material.MetalDegree) + spRO * Material.MetalDegree; spO = Vector3.Lerp(normal, spRO, Material.MetalDegree); } for (int nsmap = 0; nsmap < raycount; nsmap++) { Vector3 tp = Tools.RandomPointInSphere() * Material.AMetalDegree + spO; Vector3 raydir = tp; while (raydir.LengthSquared() < 0.1) { tp = Tools.RandomPointInSphere() + spO; raydir = tp; } Ray r = new Ray(point, raydir); //Console.WriteLine('\t' + this.Name + " [reflact] : " + r); (Light c, float _) = Scene.Light(r, deep - 1, this); //, this); reflectl += c; } reflectl /= raycount; reflectl *= (0.06f * Material.MetalDegree + 0.93f) * Material.BaseColor; } #endregion returnlight = refractl * refractPower + reflectl * (1.0f - refractPower); endReflact: returnPoint: #if RayDebugger if (Debugger != null) { Debugger.EndBranch(); } #endif return(returnlight); }
public static byte GetLuminance(this Vector3 rgb) => (((int)(Math.Round(Vector3.Dot(rgb, new Vector3(66, 129, 25))) + 128) >> 8) + 16).ToByte();
/// <summary> /// 获取入射方向在法线n的反射 /// </summary> /// <param name="dir"></param> /// <param name="n"></param> /// <returns></returns> public static Vector3 Reflect(Vector3 dir, Vector3 n) { return(dir - Vector3.Dot(dir, n) * 2.0f * n); }
// is there a clear path to the goal? private bool IsPathToGoalClear() { float sideThreshold = Radius * 8.0f; float behindThreshold = Radius * 2.0f; Vector3 goalOffset = Globals.HomeBaseCenter - Position; float goalDistance = goalOffset.Length(); Vector3 goalDirection = goalOffset / goalDistance; bool goalIsAside = this.IsAside(Globals.HomeBaseCenter, 0.5f); // for annotation: loop over all and save result, instead of early return bool xxxReturn = true; // loop over enemies foreach (CtfEnemy e in Plugin.CtfEnemies) { float eDistance = Vector3.Distance(Position, e.Position); float timeEstimate = 0.3f * eDistance / e.Speed; //xxx Vector3 eFuture = e.PredictFuturePosition(timeEstimate); Vector3 eOffset = eFuture - Position; float alongCorridor = Vector3.Dot(goalDirection, eOffset); bool inCorridor = ((alongCorridor > -behindThreshold) && (alongCorridor < goalDistance)); float eForwardDistance = Vector3.Dot(Forward, eOffset); // xxx temp move this up before the conditionals annotation.CircleXZ(e.Radius, eFuture, Globals.ClearPathColor.ToVector3().FromXna(), 20); //xxx // consider as potential blocker if within the corridor if (inCorridor) { Vector3 perp = eOffset - (goalDirection * alongCorridor); float acrossCorridor = perp.Length(); if (acrossCorridor < sideThreshold) { // not a blocker if behind us and we are perp to corridor float eFront = eForwardDistance + e.Radius; //annotation.annotationLine (position, forward*eFront, gGreen); // xxx //annotation.annotationLine (e.position, forward*eFront, gGreen); // xxx // xxx // std::ostringstream message; // message << "eFront = " << std::setprecision(2) // << std::setiosflags(std::ios::fixed) << eFront << std::ends; // draw2dTextAt3dLocation (*message.str(), eFuture, gWhite); bool eIsBehind = eFront < -behindThreshold; bool eIsWayBehind = eFront < (-2 * behindThreshold); bool safeToTurnTowardsGoal = ((eIsBehind && goalIsAside) || eIsWayBehind); if (!safeToTurnTowardsGoal) { // this enemy blocks the path to the goal, so return false annotation.Line(Position, e.Position, Globals.ClearPathColor.ToVector3().FromXna()); // return false; xxxReturn = false; } } } } // no enemies found along path, return true to indicate path is clear // clearPathAnnotation (sideThreshold, behindThreshold, goalDirection); // return true; //if (xxxReturn) ClearPathAnnotation(sideThreshold, behindThreshold, goalDirection); return(xxxReturn); }
public static byte GetIntensity(this Vector3 rgb) => Vector3.Dot(rgb, new Vector3(1 / 3f)).ToByte();