public void ApplyToRigidbodyAlongSurface() { // Get the information about the surface the character is on. SurfaceInfo info = GetSurfaceInfo(); // Calculate the height difference between where the character currently is and where the forward edge of the collider is. float heightDiff = info.predictHit.point.y - info.currentHit.point.y; // If this height difference is small, the character is on a flat surface so apply the normal root motion. if (heightDiff < k_ErrorMargin && heightDiff > -k_ErrorMargin) { RigidbodyApplication(m_Animator.deltaPosition); return; } // If the movement suggested at the edge of the collider has a positive y component, // then the character is about to go up a slope and this movement should be applied. if (info.predictMovement.y > k_ErrorMargin) { RigidbodyApplication(info.predictMovement); return; } // If the movement suggested for the character's current position has a positive y component (but the predicted movement doesn't), // then the character is coming to the top of a slope but needs to make it over the top. if (info.currentMovement.y > k_ErrorMargin) { RigidbodyApplication(info.currentMovement); return; } // If the current position is on a down slope, or the collider edge position is on a down slope, but not both, // then the character is on a down slope that's about to be flat or on a flat that's about to be a down slope so normal motion should be applied. if (info.currentMovement.y < -k_ErrorMargin ^ info.predictMovement.y < -k_ErrorMargin) { RigidbodyApplication(m_Animator.deltaPosition); return; } // If the current position is on a down slope and the collider edge position is on a down slope, // then apply the movement that has the least negative vertical motion. if (info.currentMovement.y < -k_ErrorMargin && info.predictMovement.y < -k_ErrorMargin) { Vector3 movement = info.currentMovement.y < info.predictMovement.y ? info.predictMovement : info.currentMovement; RigidbodyApplication(movement); return; } // If the height difference is negative then there's a step down so motion should be applied normally to step off. if (heightDiff < 0f) { RigidbodyApplication(m_Animator.deltaPosition); return; } // The only remaining possibility is that there is an up step, as such handle the step movement and apply movement appropriately. Vector3 stepMovement = HandleStepUp(info.predictHit.point); RigidbodyApplication(stepMovement); }
SurfaceInfo GroundRaycast(Vector3 footPosition) { SurfaceInfo tempGroundInfo = SurfaceInfo.zero; float rayOriginHeight = height - radius; float rayDistance = rayOriginHeight + stepHeight; // cast ray to check for level ground, ray because spherecast might touch only adjacent slope instead RaycastHit groundCastHit; Physics.Raycast( footPosition + (Vector3.up * rayOriginHeight), Vector3.down, out groundCastHit, rayDistance, levelGeometryLayerMask, QueryTriggerInteraction.Ignore); if (groundCastHit.collider != null) { tempGroundInfo.normal = groundCastHit.normal; tempGroundInfo.upwardAngle = Vector3.Angle(groundCastHit.normal, Vector3.up); tempGroundInfo.distance = groundCastHit.distance - rayOriginHeight; } return(tempGroundInfo); }
public void setRenderTarget(Surface target) { SurfaceInfo info = target.getInfo(); device.setRenderTarget(target); initializeViewport(info.width, info.height); }
public static void DoImpact(GameObject go, SurfaceInfoObject.ImpactType type, Vector3 worldPos, Quaternion rotation) { SurfaceInfoObject surfaceInfoFor = SurfaceInfo.GetSurfaceInfoFor(go, worldPos); UnityEngine.Object obj = UnityEngine.Object.Instantiate(surfaceInfoFor.GetImpactEffect(type), worldPos, rotation); UnityEngine.Object.Destroy(obj, 1f); }
private bool HandleLight(Ray ray, RaycastHit hit, out Ray newRay, ref SurfaceInfo surfaceInfo) { surfaceInfo.albedo = Min(new Vector3(1.0f, 1.0f, 1.0f) - surfaceInfo.specular, surfaceInfo.albedo); float specChance = energy(surfaceInfo.specular); float diffChance = energy(surfaceInfo.albedo); float roulette = Random.value; newRay = new Ray(); if (roulette < specChance) { newRay.origin = hit.point + hit.normal * 0.001f; float alpha = SmoothnessToPhongAlpha(surfaceInfo.smoothness); newRay.direction = SampleHemisphere(Vector3.Reflect(ray.direction, hit.normal), alpha); float f = (alpha + 2) / (alpha + 1); surfaceInfo.emission = Mul(surfaceInfo.emission, (1.0f / specChance) * surfaceInfo.specular * sdot(hit.normal, newRay.direction, f)); } else if (diffChance > 0 && roulette < specChance + diffChance) { newRay.origin = hit.point + hit.normal * 0.001f; newRay.direction = SampleHemisphere(hit.normal, 1.0f); surfaceInfo.emission = Mul(surfaceInfo.emission, (1.0f / diffChance) * surfaceInfo.albedo); } else { surfaceInfo.emission = new Vector3(0, 0, 0); } return(Vector3.Dot(newRay.direction, hit.normal) > 0); }
private Color RayTracing(Ray ray, int x, int y, out RaycastHit hit, int depth) { if (Physics.Raycast(ray, out hit, MAX_RAY_CAST_DISTANCE)) { Ray newRay; SurfaceInfo surfaceInfo = getSurfaceInfo(hit, x, y); if (depth < 100 && HandleLight(ray, hit, out newRay, ref surfaceInfo)) { Vector3 r = surfaceInfo.emission = MulColor(surfaceInfo.emission, RayTracing(newRay, x, y, out hit, depth + 1)); return(new Color(r.x, r.y, r.z)); } else { return(new Color(0, 0, 0)); } } hit = new RaycastHit(); return(mScreenTexture.GetPixel(x, y)); //return new Color(1, 1, 1); }
private void Update() { bool flag; if (this.terraincheck) { int textureIndex = TerrainTextureHelper.GetTextureIndex(base.origin); } if ((base.stateFlags.grounded && (!(flag = this.trait.timeLimited) || (this.nextAllowTime <= Time.time))) && ((base.masterControllable == null) || (base.masterControllable.idMain == base.idMain))) { bool crouch = base.stateFlags.crouch; Vector3 origin = base.origin; this.movedAmount += Vector3.Distance(this.lastFootstepPos, origin); this.lastFootstepPos = origin; if (this.movedAmount >= this.trait.sqrStrideDist) { this.movedAmount = 0f; AudioClip clip = null; if ((footsteps.quality >= 2) || ((footsteps.quality == 1) && base.character.localControlled)) { Collider belowObj = this.GetBelowObj(); if (belowObj != null) { SurfaceInfoObject surfaceInfoFor = SurfaceInfo.GetSurfaceInfoFor(belowObj, origin); if (surfaceInfoFor != null) { clip = !this.trait.animal ? surfaceInfoFor.GetFootstepBiped(this.lastPlayed) : surfaceInfoFor.GetFootstepAnimal(); this.lastPlayed = clip; } } } if (clip == null) { clip = this.trait.defaultFootsteps[UnityEngine.Random.Range(0, this.trait.defaultFootsteps.Length)]; if (clip == null) { return; } } float minAudioDist = this.trait.minAudioDist; float maxAudioDist = this.trait.maxAudioDist; if (crouch) { clip.Play(origin, 0.2f, UnityEngine.Random.Range((float)0.95f, (float)1.05f), minAudioDist * 0.333f, maxAudioDist * 0.333f, 30); } else { clip.Play(origin, 0.65f, UnityEngine.Random.Range((float)0.95f, (float)1.05f), minAudioDist, maxAudioDist, 30); } if (flag) { this.nextAllowTime = Time.time + this.trait.minInterval; } } } }
public virtual void DoMeleeEffects(Vector3 fromPos, Vector3 pos, Quaternion rot, GameObject hitObj) { if (!hitObj.CompareTag("Tree Collider")) { SurfaceInfo.DoImpact(hitObj, SurfaceInfoObject.ImpactType.Melee, pos, rot); return; } GameObject gameObject = UnityEngine.Object.Instantiate(this.impactEffectWood, pos, rot) as GameObject; UnityEngine.Object.Destroy(gameObject, 1.5f); this.impactSoundWood.Play(pos, 1f, 2f, 10f); }
public virtual void DoMeleeEffects(Vector3 fromPos, Vector3 pos, Quaternion rot, GameObject hitObj) { if (hitObj.CompareTag("Tree Collider")) { GameObject obj2 = Object.Instantiate(this.impactEffectWood, pos, rot) as GameObject; Object.Destroy(obj2, 1.5f); this.impactSoundWood.Play(pos, (float)1f, (float)2f, (float)10f); } else { SurfaceInfo.DoImpact(hitObj, SurfaceInfoObject.ImpactType.Melee, pos, rot); } }
// Update is called once per frame void FixedUpdate() { SurfaceInfo surfaceInfo = raycaster.GetSurfaceInfo(GetComponent <CapsuleCollider>()); Upright = surfaceInfo.Pitch <= maxUprightPitch && surfaceInfo.RaycastOriginResult; Grounded = surfaceInfo.Pitch <= maxUprightPitch && !surfaceInfo.RaycastOriginResult; Movement(Upright, surfaceInfo); InputJump(Grounded || Upright); InputBoost(); }
private Vector3 Shade(RaycastHit hit, Ray ray, Vector2 screenPosition) { Vector3 result = new Vector3(0.0f, 0.0f, 0.0f); List <Light> lightList = new List <Light>(mLightList); SurfaceInfo surfaceInfo = GetSurfaceInfo(screenPosition, hit); hit.normal = surfaceInfo.normal; if (surfaceInfo.light.x > 0.0f) { float degree = Vector3.Dot(Vector3.Normalize(hit.normal), Vector3.Normalize(ray.direction * -1.0f)); return(surfaceInfo.emission * degree * (10.0f / hit.distance) * 0.8f); } if (!TerminalTrace(screenPosition, hit, ray)) { //能反射的时候才反射 if (surfaceInfo.albedo > 0.0f) { mTraceCount++; //一定有反射,先不考虑折射 Ray reflectRay = new Ray(); reflectRay.origin = hit.point + hit.normal * 0.0001f; reflectRay.direction = Vector3.Reflect(ray.direction, hit.normal); //反射方向随机采样 //reflectRay.direction += Random.onUnitSphere; result += (Trace(reflectRay, screenPosition) * surfaceInfo.albedo); } } foreach (Light light in lightList) { foreach (LightHandler handler in mLightHandlerList) { if (handler != null) { result += handler.OnHandle(light, surfaceInfo, hit, ray); } } } result += ambientColor; if (surfaceInfo != null) { result = Util.Vector3MulVector3(result, surfaceInfo.emission); } return(result); }
private SurfaceInfo getSurfaceInfo(RaycastHit hit, int x, int y) { SurfaceInfo surfaceInfo = new SurfaceInfo(); MeshFilter filter = hit.transform.GetComponent <MeshFilter>(); Mesh mesh = filter.mesh; int limit = hit.triangleIndex * 3; int submesh; for (submesh = 0; submesh < mesh.subMeshCount; submesh++) { int numIndices = mesh.GetTriangles(submesh).Length; if (numIndices > limit) { break; } limit -= numIndices; } if (hit.transform.GetComponent <Renderer>() != null) { Material material = hit.transform.GetComponent <Renderer>().materials[submesh]; float metallic = material.GetFloat("_Metallic"); if (material.mainTexture != null) { Texture2D texture = material.mainTexture as Texture2D; surfaceInfo.emission = Util.ColorToVector3(texture.GetPixelBilinear(hit.textureCoord.x, hit.textureCoord.y)); } else { surfaceInfo.emission = Util.ColorToVector3(material.color); } } else { surfaceInfo.emission = Util.ColorToVector3(mScreenTexture.GetPixel(x, y)); } GameObject gameObject = hit.collider.gameObject; return(surfaceInfo); }
public void ApplyMovementForces(Rigidbody rb, InputController input, SurfaceInfo surfaceInfo) { rb.velocity = Vector3.ClampMagnitude(rb.velocity, MaxUprightVelocity); rb.maxAngularVelocity = MaxAngularVelocity; rb.angularVelocity = Vector3.Slerp(rb.angularVelocity, Vector3.zero, Time.fixedDeltaTime * AngularDampening); Vector3 appliedForce = Vector3.zero; appliedForce += CalculateInputForce(rb, input, surfaceInfo.Normal); KeepUpright(rb, input, surfaceInfo.Normal); rb.AddForce(appliedForce, ForceMode.Acceleration); }
public void ApplyToRigidbodyAlongSurface() { SurfaceInfo info = GetSurFaceInfo(); float diff = info.predictHit.point.y - info.currentHit.point.y; //水平走 if (diff < k_ErrorMargin || diff > -k_ErrorMargin) { RigidbodyApplication(info.currentMotion); return; } //上坡 if (info.predictMotion.y > k_ErrorMargin) { RigidbodyApplication(info.predictMotion); return; } //即将爬完上坡 if (info.currentMotion.y > k_ErrorMargin) { RigidbodyApplication(info.currentMotion); return; } //下坡 if (info.currentMotion.y < -k_ErrorMargin || info.predictMotion.y < -k_ErrorMargin) { RigidbodyApplication(m_Animator.deltaPosition); return; } if (info.currentMotion.y < -k_ErrorMargin && info.predictMotion.y < -k_ErrorMargin) { Vector3 movement = info.currentMotion.y < info.predictMotion.y ? info.predictMotion : info.currentMotion; RigidbodyApplication(movement); return; } //下楼梯 if (diff < 0f) { RigidbodyApplication(m_Animator.deltaPosition); return; } //上楼梯 Vector3 stepMovement = handleStepUp(info.predictHit.point); RigidbodyApplication(stepMovement); }
public unsafe SdlBuffer(int *data, int w, int h, bool makeCopy = false) : this() { if (makeCopy) { Handle = SdlFactory.CreateSurface(w, h); } else { Handle = SdlFactory.CreateSurface((IntPtr)data, w, h, Factory.PixelFormat); } surface = Handle.ToStruct <SurfaceInfo>(); if (makeCopy) { Implementation.CopyMemory(data, 0, (int *)surface.Pixels, 0, w * h); } }
public static SurfaceInfoObject GetSurfaceInfoFor(GameObject obj, Vector3 worldPos) { SurfaceInfo component = obj.GetComponent <SurfaceInfo>(); if (component != null) { return(component.SurfaceObj(worldPos)); } IDBase base2 = obj.GetComponent <IDBase>(); if (base2 != null) { SurfaceInfo info2 = base2.idMain.GetComponent <SurfaceInfo>(); if (info2 != null) { return(info2.SurfaceObj(worldPos)); } } return(SurfaceInfoObject.GetDefault()); }
public static SurfaceInfoObject GetSurfaceInfoFor(GameObject obj, Vector3 worldPos) { SurfaceInfo component = obj.GetComponent <SurfaceInfo>(); if (component) { return(component.SurfaceObj(worldPos)); } IDBase dBase = obj.GetComponent <IDBase>(); if (dBase) { SurfaceInfo surfaceInfo = dBase.idMain.GetComponent <SurfaceInfo>(); if (surfaceInfo) { return(surfaceInfo.SurfaceObj(worldPos)); } } return(SurfaceInfoObject.GetDefault()); }
public SurfaceInfo GetSurfaceInfo(CapsuleCollider capsule) { RaycastHit hit; bool rayResult = Physics.Raycast(RaycastOrigin.position, capsule.transform.up * -1, out hit, RayDistance, GroundLayer); // if the first ray fails to return a result, check the overlapping capsule if (!rayResult) { Vector3 p1 = capsule.transform.position + capsule.center + Vector3.up * -capsule.height * 0.5F; Vector3 p2 = p1 + Vector3.up * capsule.height; //Physics.CapsuleCast(p1, p2, capsule.radius * 1.05f,new Vector3(0,1,0), out hit, 10f, GroundLayer); Collider[] colliders = Physics.OverlapCapsule(p1, p2, capsule.radius * 1.05f, GroundLayer); if (colliders.Length != 0) { RaycastHit capsuleHit; Physics.Raycast(capsule.transform.position, Vector3.down, out capsuleHit, capsule.radius * 1.05f, GroundLayer); hit = capsuleHit; } } float friction = 0; if (hit.collider) { friction = hit.collider.material.dynamicFriction; } SurfaceInfo hitInfo = new SurfaceInfo { RaycastOriginResult = rayResult, Friction = friction, Normal = hit.normal, Pitch = GetSurfacePitch(hit.normal) }; return(hitInfo); }
void Movement(bool Upright, SurfaceInfo surfaceInfo) { if (Upright) { //rb.freezeRotation = true; uprightMovement.ApplyMovementForces(rb, input, surfaceInfo); friction.ApplyFriction(2f, rb); } else { //rb.freezeRotation = false; if (Grounded) { airMovement.ApplyMovementForces(rb, input); friction.ApplyFriction(1f, rb); } else { airMovement.ApplyMovementForces(rb, input); } } }
public void LayoutSurfaces(List <SurfaceInfo> surfacesInfo, List <RenderTexture> renderTextures) { // 1. Calculate the width of the central screen and maximum width of a side wall. float centerWidth = 0; float rightWidth = 0; foreach (SurfaceInfo surfaceInfo in surfacesInfo) { switch (surfaceInfo.position) { case SurfacePosition.Center: case SurfacePosition.Back: var newCenterWidth = surfaceInfo.aspectRatio; centerWidth = Mathf.Max(centerWidth, newCenterWidth); break; case SurfacePosition.Left: break; case SurfacePosition.Right: rightWidth = surfaceInfo.aspectRatio; break; } } //Keep track of surfaces which are in use List <SurfacePosition> surfacePositions = new List <SurfacePosition>(); //Resize all screens for (int i = 0; i < surfacesInfo.Count; i++) { SurfaceInfo surfaceInfo = surfacesInfo[i]; RenderTexture renderTexture = renderTextures[i]; surfacePositions.Add(surfaceInfo.position); switch (surfaceInfo.position) { case SurfacePosition.Left: var left = screens.GetChild(0); var width = surfaceInfo.aspectRatio; left.localPosition = new Vector3(-(centerWidth + width) / 2 - screenSeperation, 0, 0); left.localScale = new Vector3(width, 1, 1); SetScreenTexture(renderTexture, left); break; case SurfacePosition.Center: var center = screens.GetChild(1); center.localScale = new Vector3(centerWidth, 1, 1); SetScreenTexture(renderTexture, center); break; case SurfacePosition.Right: var right = screens.GetChild(2); width = surfaceInfo.aspectRatio; right.localPosition = new Vector3((centerWidth + width) / 2 + screenSeperation, 0, 0); right.localScale = new Vector3(width, 1, 1); SetScreenTexture(renderTexture, right); break; case SurfacePosition.Back: var back = screens.GetChild(3); width = surfaceInfo.aspectRatio; back.localPosition = new Vector3((centerWidth + width) / 2 + rightWidth + screenSeperation * 2, 0, 0); back.localScale = new Vector3(width, 1, 1); SetScreenTexture(renderTexture, back); break; case SurfacePosition.Floor: var floor = screens.GetChild(4); floor.localScale = new Vector3(surfaceInfo.aspectRatio, 1, 1); floor.localPosition = new Vector3(0, -1 - screenSeperation, 0); SetScreenTexture(renderTexture, floor); break; } } //Disable Screens which are not in used screens.GetChild(0).gameObject.SetActive(surfacePositions.Contains(SurfacePosition.Left)); screens.GetChild(1).gameObject.SetActive(surfacePositions.Contains(SurfacePosition.Center)); screens.GetChild(2).gameObject.SetActive(surfacePositions.Contains(SurfacePosition.Right)); screens.GetChild(3).gameObject.SetActive(surfacePositions.Contains(SurfacePosition.Back)); screens.GetChild(4).gameObject.SetActive(surfacePositions.Contains(SurfacePosition.Floor)); //Get Leftmost Screen var leftmostScreen = GetLeftmostScreen(); //Get Rightmost Screen var rightMostScreen = GetRightmostScreen(); var topMostScreen = GetTopScreen(); //Get Bottom Screen var bottomMostScreen = screens.GetChild(screens.childCount - 1); //CALCULATE POSITION BOUNDS. maxXPosition = (rightMostScreen.localPosition.x + rightMostScreen.localScale.x / 2 + screenSeperation); minXPosition = (leftmostScreen.localPosition.x - leftmostScreen.localScale.x / 2 - screenSeperation); maxYPosition = topMostScreen.localPosition.y + topMostScreen.localScale.y / 2 + screenSeperation; minYPosition = bottomMostScreen.localPosition.y - bottomMostScreen.localScale.y / 2 - screenSeperation; maxOrthographicWidth = maxXPosition - minXPosition; maxOrthographicWidth /= 2; maxOrthographicHeight = maxYPosition - minYPosition; maxOrthographicHeight /= 2; minOrthographicSize = 0.5f + screenSeperation; if (surfacePositions.Contains(SurfacePosition.Floor)) { zoomedOutYPosition = -0.5f; zoomedOutHeight = 1 + screenSeperation; } else { zoomedOutYPosition = 0; zoomedOutHeight = 0.5f; } zoomedOutXPosition = (maxXPosition + minXPosition) / 2; var aspectRatio = (float)cam.pixelWidth / (float)cam.pixelHeight; cam.orthographicSize = maxOrthographicWidth * aspectRatio; PositionCamera(); }
private void Update() { Vector3 vector3; Vector3 vector31; GameObject gameObject; Rigidbody rigidbody; if (this.impacted) { return; } float single = Time.time - this.lastUpdateTime; this.lastUpdateTime = Time.time; RaycastHit raycastHit = new RaycastHit(); RaycastHit2 raycastHit2 = RaycastHit2.invalid; base.transform.Rotate(Vector3.right, this.dropDegreesPerSec * single); Ray ray = new Ray(base.transform.position, base.transform.forward); bool flag = true; if (!Physics2.Raycast2(ray, out raycastHit2, this.speedPerSec * single, this.layerMask)) { Transform transforms = base.transform; transforms.position = transforms.position + ((base.transform.forward * this.speedPerSec) * single); ArrowMovement arrowMovement = this; arrowMovement.distance = arrowMovement.distance + this.speedPerSec * single; } else { if (!flag) { vector31 = raycastHit.normal; vector3 = raycastHit.point; gameObject = raycastHit.collider.gameObject; rigidbody = raycastHit.rigidbody; } else { vector31 = raycastHit2.normal; vector3 = raycastHit2.point; gameObject = raycastHit2.gameObject; rigidbody = raycastHit2.rigidbody; } Quaternion quaternion = Quaternion.LookRotation(vector31); Vector3 vector32 = Vector3.zero; int num = gameObject.layer; bool flag1 = true; if (rigidbody && !rigidbody.isKinematic && !rigidbody.CompareTag("Door")) { rigidbody.AddForceAtPosition(Vector3.up * 200f, vector3); rigidbody.AddForceAtPosition(ray.direction * 1000f, vector3); } if (num == 17 || num == 18 || num == 27 || num == 21) { flag1 = false; } else { vector32 = vector3 + (vector31 * 0.01f); } this.impacted = true; base.transform.position = vector3; this.TryReportHit(gameObject); base.transform.parent = gameObject.transform; TrailRenderer component = base.GetComponent <TrailRenderer>(); if (component) { component.enabled = false; } base.audio.enabled = false; if (gameObject) { SurfaceInfoObject surfaceInfoFor = SurfaceInfo.GetSurfaceInfoFor(gameObject, vector3); surfaceInfoFor.GetImpactEffect(SurfaceInfoObject.ImpactType.Bullet); UnityEngine.Object obj = UnityEngine.Object.Instantiate(surfaceInfoFor.GetImpactEffect(SurfaceInfoObject.ImpactType.Bullet), vector3, quaternion); UnityEngine.Object.Destroy(obj, 1.5f); this.TryReportMiss(); } UnityEngine.Object.Destroy(base.gameObject, 20f); } if (this.distance > this.maxRange || Time.time - this.spawnTime > this.maxLifeTime) { UnityEngine.Object.Destroy(base.gameObject); } }
private void Update() { Vector3 vector3; Vector3 vector31; GameObject gameObject; Rigidbody rigidbody; float single = Time.time - this.lastUpdateTime; this.lastUpdateTime = Time.time; if (this.distance > this.fadeDistStart) { base.transform.localScale = Vector3.Lerp(base.transform.localScale, this.startScale, Mathf.Clamp((this.distance - this.fadeDistStart) / this.fadeDistLength, 0f, 1f)); } RaycastHit raycastHit = new RaycastHit(); RaycastHit2 raycastHit2 = RaycastHit2.invalid; Ray ray = new Ray(base.transform.position, base.transform.forward); float single1 = this.speedPerSec * single; bool flag = (!this.thereIsACollider || !this.colliderToHit ? 0 : (int)this.colliderToHit.enabled) == 0; if ((!flag ? !this.colliderToHit.Raycast(ray, out raycastHit, single1) : !Physics2.Raycast2(ray, out raycastHit2, this.speedPerSec * single, this.layerMask))) { Transform transforms = base.transform; transforms.position = transforms.position + ((base.transform.forward * this.speedPerSec) * single); Tracer tracer = this; tracer.distance = tracer.distance + this.speedPerSec * single; } else { if (Vector3.Distance(Camera.main.transform.position, base.transform.position) > 75f) { UnityEngine.Object.Destroy(base.gameObject); return; } if (!flag) { vector31 = raycastHit.normal; vector3 = raycastHit.point; gameObject = raycastHit.collider.gameObject; rigidbody = raycastHit.rigidbody; } else { vector31 = raycastHit2.normal; vector3 = raycastHit2.point; gameObject = raycastHit2.gameObject; rigidbody = raycastHit2.rigidbody; } Quaternion quaternion = Quaternion.LookRotation(vector31); int num = gameObject.layer; GameObject gameObject1 = this.impactPrefab; bool flag1 = true; if (rigidbody && !rigidbody.isKinematic && !rigidbody.CompareTag("Door")) { rigidbody.AddForceAtPosition(Vector3.up * 200f, vector3); rigidbody.AddForceAtPosition(ray.direction * 1000f, vector3); } SurfaceInfo.DoImpact(gameObject, SurfaceInfoObject.ImpactType.Bullet, vector3 + (vector31 * 0.01f), quaternion); if (num == 17 || num == 18 || num == 27 || num == 21) { flag1 = false; } UnityEngine.Object.Destroy(base.gameObject); if (flag1) { this.impactSounds[UnityEngine.Random.Range(0, (int)this.impactSounds.Length)].Play(vector3, 1f, 2f, 15f, 180); GameObject gameObject2 = UnityEngine.Object.Instantiate(this.decalPrefab, vector3 + (vector31 * UnityEngine.Random.Range(0.01f, 0.03f)), quaternion * Quaternion.Euler(0f, 0f, (float)UnityEngine.Random.Range(-30, 30))) as GameObject; if (gameObject) { gameObject2.transform.parent = gameObject.transform; } UnityEngine.Object.Destroy(gameObject2, 15f); } } if (this.distance > this.maxRange) { UnityEngine.Object.Destroy(base.gameObject); } }
private void Update() { float num = Time.time - this.lastUpdateTime; this.lastUpdateTime = Time.time; if (this.distance > this.fadeDistStart) { base.transform.localScale = Vector3.Lerp(base.transform.localScale, this.startScale, Mathf.Clamp((float)((this.distance - this.fadeDistStart) / this.fadeDistLength), (float)0f, (float)1f)); } RaycastHit hitInfo = new RaycastHit(); RaycastHit2 invalid = RaycastHit2.invalid; Ray ray = new Ray(base.transform.position, base.transform.forward); float distance = this.speedPerSec * num; bool flag = !((this.thereIsACollider && (this.colliderToHit != null)) && this.colliderToHit.enabled); if (!flag ? this.colliderToHit.Raycast(ray, out hitInfo, distance) : Physics2.Raycast2(ray, out invalid, this.speedPerSec * num, this.layerMask)) { Vector3 point; Vector3 normal; GameObject gameObject; Rigidbody rigidbody; if (Vector3.Distance(Camera.main.transform.position, base.transform.position) > 75f) { Object.Destroy(base.gameObject); return; } if (flag) { normal = invalid.normal; point = invalid.point; gameObject = invalid.gameObject; rigidbody = invalid.rigidbody; } else { normal = hitInfo.normal; point = hitInfo.point; gameObject = hitInfo.collider.gameObject; rigidbody = hitInfo.rigidbody; } Quaternion rotation = Quaternion.LookRotation(normal); int layer = gameObject.layer; GameObject impactPrefab = this.impactPrefab; bool flag2 = true; if (((rigidbody != null) && !rigidbody.isKinematic) && !rigidbody.CompareTag("Door")) { rigidbody.AddForceAtPosition((Vector3)(Vector3.up * 200f), point); rigidbody.AddForceAtPosition((Vector3)(ray.direction * 1000f), point); } SurfaceInfo.DoImpact(gameObject, SurfaceInfoObject.ImpactType.Bullet, point + ((Vector3)(normal * 0.01f)), rotation); switch (layer) { case 0x11: case 0x12: case 0x1b: case 0x15: flag2 = false; break; } Object.Destroy(base.gameObject); if (flag2) { this.impactSounds[Random.Range(0, this.impactSounds.Length)].Play(point, 1f, 2f, 15f, 180); GameObject obj4 = Object.Instantiate(this.decalPrefab, point + ((Vector3)(normal * Random.Range((float)0.01f, (float)0.03f))), rotation * Quaternion.Euler(0f, 0f, (float)Random.Range(-30, 30))) as GameObject; if (gameObject != null) { obj4.transform.parent = gameObject.transform; } Object.Destroy(obj4, 15f); } } else { Transform transform = base.transform; transform.position += (Vector3)((base.transform.forward * this.speedPerSec) * num); this.distance += this.speedPerSec * num; } if (this.distance > this.maxRange) { Object.Destroy(base.gameObject); } }
abstract public Vector3 OnHandle(Light light, SurfaceInfo surfaceInfo, RaycastHit hit, Ray ray);
public static SurfaceInfoObject GetSurfaceInfoFor(Collider collider, Vector3 worldPos) { return(SurfaceInfo.GetSurfaceInfoFor(collider.gameObject, worldPos)); }
private void Update() { if (!this.impacted) { float num = Time.time - this.lastUpdateTime; this.lastUpdateTime = Time.time; RaycastHit hit = new RaycastHit(); RaycastHit2 invalid = RaycastHit2.invalid; base.transform.Rotate(Vector3.right, (float)(this.dropDegreesPerSec * num)); Ray ray = new Ray(base.transform.position, base.transform.forward); float num2 = this.speedPerSec * num; bool flag = true; if (!Physics2.Raycast2(ray, out invalid, this.speedPerSec * num, this.layerMask)) { Transform transform = base.transform; transform.position += (Vector3)((base.transform.forward * this.speedPerSec) * num); this.distance += this.speedPerSec * num; } else { Vector3 point; Vector3 normal; GameObject gameObject; Rigidbody rigidbody; if (flag) { normal = invalid.normal; point = invalid.point; gameObject = invalid.gameObject; rigidbody = invalid.rigidbody; } else { normal = hit.normal; point = hit.point; gameObject = hit.collider.gameObject; rigidbody = hit.rigidbody; } Quaternion rotation = Quaternion.LookRotation(normal); Vector3 zero = Vector3.zero; int layer = gameObject.layer; bool flag2 = true; if (((rigidbody != null) && !rigidbody.isKinematic) && !rigidbody.CompareTag("Door")) { rigidbody.AddForceAtPosition((Vector3)(Vector3.up * 200f), point); rigidbody.AddForceAtPosition((Vector3)(ray.direction * 1000f), point); } switch (layer) { case 0x11: case 0x12: case 0x1b: case 0x15: flag2 = false; break; default: zero = point + ((Vector3)(normal * 0.01f)); break; } this.impacted = true; base.transform.position = point; this.TryReportHit(gameObject); base.transform.parent = gameObject.transform; TrailRenderer component = base.GetComponent <TrailRenderer>(); if (component != null) { component.enabled = false; } base.audio.enabled = false; if (gameObject != null) { SurfaceInfoObject surfaceInfoFor = SurfaceInfo.GetSurfaceInfoFor(gameObject, point); surfaceInfoFor.GetImpactEffect(SurfaceInfoObject.ImpactType.Bullet); Object.Destroy(Object.Instantiate(surfaceInfoFor.GetImpactEffect(SurfaceInfoObject.ImpactType.Bullet), point, rotation), 1.5f); this.TryReportMiss(); } Object.Destroy(base.gameObject, 20f); } if ((this.distance > this.maxRange) || ((Time.time - this.spawnTime) > this.maxLifeTime)) { Object.Destroy(base.gameObject); } } }
private void Update() { if (this.terraincheck) { TerrainTextureHelper.GetTextureIndex(base.origin); } if (base.stateFlags.grounded) { bool flag = this.trait.timeLimited; bool flag1 = flag; if ((!flag || this.nextAllowTime <= Time.time) && (!base.masterControllable || !(base.masterControllable.idMain != base.idMain))) { bool flag2 = base.stateFlags.crouch; Vector3 vector3 = base.origin; FootstepEmitter footstepEmitter = this; footstepEmitter.movedAmount = footstepEmitter.movedAmount + Vector3.Distance(this.lastFootstepPos, vector3); this.lastFootstepPos = vector3; if (this.movedAmount >= this.trait.sqrStrideDist) { this.movedAmount = 0f; AudioClip item = null; if (footsteps.quality >= 2 || footsteps.quality == 1 && base.character.localControlled) { Collider belowObj = this.GetBelowObj(); if (belowObj) { SurfaceInfoObject surfaceInfoFor = SurfaceInfo.GetSurfaceInfoFor(belowObj, vector3); if (surfaceInfoFor) { item = (!this.trait.animal ? surfaceInfoFor.GetFootstepBiped(this.lastPlayed) : surfaceInfoFor.GetFootstepAnimal()); this.lastPlayed = item; } } } if (!item) { item = this.trait.defaultFootsteps[UnityEngine.Random.Range(0, this.trait.defaultFootsteps.Length)]; if (!item) { return; } } float single = this.trait.minAudioDist; float single1 = this.trait.maxAudioDist; if (!flag2) { item.Play(vector3, 0.65f, UnityEngine.Random.Range(0.95f, 1.05f), single, single1, 30); } else { item.Play(vector3, 0.2f, UnityEngine.Random.Range(0.95f, 1.05f), single * 0.333f, single1 * 0.333f, 30); } if (flag1) { this.nextAllowTime = Time.time + this.trait.minInterval; } } return; } } }
public override void OnClick() { _plugin.CurrentTool = this; ToolSceneDrawFlyByPath.m_frm.Application = this._plugin; this.isurface_0 = SurfaceInfo.GetSurfaceFromLayer(this._plugin.CurrentLayer); }
void FixedUpdate() { groundInfo = GroundRaycast(transform.position); // determine move input FpsControllerInput input = new FpsControllerInput(); if (getInput != null) { input = getInput(); } // reset jump input if (grounded && input.jump == false) { jumpReleased = true; } // determine walking velocity to move toward Vector3 moveVelocityTarget = CalculateMoveVelocityTarget(input); // determine how to interact with ground (either stand on it, land on it, step up/down or fall) if (Mathf.Abs(groundInfo.distance) <= stepHeight && groundInfo.upwardAngle <= slopeMaxAngle && body.velocity.y <= jumpSpeed * jumpSpeedLandPercentage) // check if grounded { if (!grounded) { // land if (body.velocity.y <= -minLandSfxSpeed) { sfxLand.Play(scrListener.personalEffects); vibLand.Play(scrListener.personalEffects); } EnterGrounded(); } //step transform.position = Vector3.Lerp( transform.position, transform.position + Vector3.down * groundInfo.distance, stepLerp); } if (grounded) { // enter free fall if not touching any ground if (groundInfo.distance == Mathf.Infinity) { EnterFreefall(); } // if touching steep slope, start falling if there is no level ground nearby else if (groundInfo.upwardAngle > slopeMaxAngle && groundInfo.upwardAngle < 90) { SurfaceInfo checkForFooting = GroundRaycast(transform.position + Math.OnlyHorizontal(groundInfo.normal).normalized *radius); if (checkForFooting.distance == Mathf.Infinity || checkForFooting.upwardAngle > slopeMaxAngle) { EnterFreefall(); } } } if (!grounded) { // fall body.velocity = body.velocity + (Vector3.down * gravity); // extend feet to avoid clipping into slopes when falling capsule.height = Mathf.Lerp(capsule.height, height, jumpFootExtensionLerp); capsule.center = Vector3.Lerp( capsule.center, new Vector3(0f, height / 2f, 0f), jumpFootExtensionLerp); } // jump conditions are checked if (input.jump && jumpReleased) { Jump(); } if (grounded || groundInfo.upwardAngle <= slopeMaxAngle) // no friction during sliding only when grounded or in air { if (Vector3.Dot(moveVelocityTarget, body.velocity) <= 0f) // if walking opposite direction or input 0 apply friction { body.velocity = Math.HorizontalOverride(body.velocity, body.velocity * moveDamping); } if (moveVelocityTarget.sqrMagnitude != 0f) // if move input move { body.velocity = Math.HorizontalOverride(body.velocity, Vector3.MoveTowards(body.velocity, moveVelocityTarget, moveAccel * Time.fixedDeltaTime)); } } }
static void Main(string[] args) { // Check parameters if (args.Length == 0) { Console.WriteLine("Usage: ProcessForcePlanes <input.obj>"); return; } // Get full object path var inputObj = Path.GetFullPath(args[0]); var fileName = Path.GetFileNameWithoutExtension(inputObj); var debugImages = Path.Combine(Path.GetDirectoryName(inputObj), @"DebugImages"); var maskOutput = Path.Combine(Path.GetDirectoryName(inputObj), @"..\textures\" + fileName + "_fp_mask.png"); var equOutput = Path.Combine(Path.GetDirectoryName(inputObj), @"..\kernels\" + fileName + "_equ.txt"); Directory.CreateDirectory(debugImages); // Load object ObjLoader obj = new ObjLoader(); obj.LoadObj(inputObj); string glslCode = ""; var surfaceList = new List <SurfaceInfo>(); // Compute areas foreach (var face in obj.meshs.SelectMany(t => t.faces)) { // Ensure tri if (face.positionIdx.Length != 3) { throw new Exception("Non-triangle polygon detected"); } // Compute quad area var v = face.vertices = face.positionIdx.Select(t => obj.positions[t - 1]).ToArray(); var E0 = Vector3F.Subtract(v[2], v[0]); var E1 = Vector3F.Subtract(v[1], v[0]); face.area = Vector3F.CrossProduct(E0, E1).GetLength(); // Compute normal face.computedNormal = Vector3F.CrossProduct(E0, E1); if (face.computedNormal.GetLengthSquared() > 0) { face.computedNormal.Normalize(); } else { 0.ToString(); } // Tri has half of quad size face.area = face.area / 2; } // Remove zero area faces var faces = obj.meshs.SelectMany(t => t.faces).Where(t => t.area > 0).ToList(); // Sort according to area faces.Sort((a, b) => b.area.CompareTo(a.area)); // Scan triangles for faces for (int iFace = 0; iFace < faces.Count; iFace++) { // Check if face is marked for active force var face = faces[iFace]; // Create a face list for it var surface = new SurfaceInfo(); surfaceList.Add(surface); surface.faces.Add(face); // Get surface vectors var B = face.vertices[0]; var E0 = Vector3F.Subtract(face.vertices[1], face.vertices[0]); var E1 = Vector3F.Subtract(face.vertices[2], face.vertices[0]); // Project all vertices agains quad for (int iOtherFaces = faces.Count - 1; iOtherFaces >= iFace + 1; iOtherFaces--) { // Get "other" face var othFace = faces[iOtherFaces]; // Ignore if diffrent normals if (Vector3F.DotProduct(face.computedNormal, othFace.computedNormal) < 0.7) { continue; } // Ignore if any of the "other" triangle points is too far from surface if (othFace.vertices.Any(vert => Math.Abs(PointQuadDistance(vert, B, E0, E1).dist) > 0.001)) { continue; } // Add to this face triangle list surface.faces.Add(othFace); // Remove from mesh faces faces.RemoveAt(iOtherFaces); } } // Sort according to size surfaceList.Sort((a, b) => a.faces.Count.CompareTo(b.faces.Count)); // Build edge list foreach (var surface in surfaceList) { // Add all edges of all faces foreach (var face in surface.faces) { UpdateEdgeList(surface.edges, face.vertices[0], face.vertices[1], face.computedNormal); UpdateEdgeList(surface.edges, face.vertices[1], face.vertices[2], face.computedNormal); UpdateEdgeList(surface.edges, face.vertices[2], face.vertices[0], face.computedNormal); } } // Expand edges foreach (var surface in surfaceList) { // Create surface vertices list surface.vertices = surface.faces.SelectMany(face => face.vertices).Distinct().ToArray(); // Create vertex=>edges map foreach (var vertex in surface.vertices) { surface.vertexEdges[vertex] = surface.edges.Where(edge => (edge.p1 == vertex) || (edge.p2 == vertex)).ToList(); } foreach (var vertex in surface.vertices) { foreach (var edge in surface.vertexEdges[vertex]) { // Internal edge? if (edge.normals.Count > 1) { continue; } // Create if doesn't exists if (!surface.vertexNormal.ContainsKey(edge.p1)) { surface.vertexNormal[edge.p1] = Vector3F.Zero; } if (!surface.vertexNormal.ContainsKey(edge.p2)) { surface.vertexNormal[edge.p2] = Vector3F.Zero; } // Shift point surface.vertexNormal[edge.p1] = Vector3F.Add(surface.vertexNormal[edge.p1], edge.normals[0]); surface.vertexNormal[edge.p2] = Vector3F.Add(surface.vertexNormal[edge.p2], edge.normals[0]); } } // Normalize and scale offset foreach (var vertex in surface.vertices) { // Find one of the external edges of the vertex var vertexExtEdge = surface.vertexEdges[vertex].FirstOrDefault(t => t.normals.Count == 1); // Compute the ratio between the movement along the vertex normal and the movement along the edge normal var vertexNormal = surface.vertexNormal[vertex].GetUnit(); var projectedNormalLen = Vector3F.DotProduct(vertexNormal, vertexExtEdge.normals[0]); // Compute acutal offset var vertexOffset = Vector3F.Multiply(vertexNormal, Math.Min(1.0f, 1.0f / projectedNormalLen)); // Move vertices foreach (var face in surface.faces) { for (int iVertex = 0; iVertex < face.vertices.Length; iVertex++) { if (face.vertices[iVertex] == vertex) { face.vertices[iVertex] = Vector3F.Add(face.vertices[iVertex], vertexOffset); } } } } // Create surface expanded vertices list surface.expanded_vertices = surface.faces.SelectMany(face => face.vertices).Distinct().ToArray(); } // Compute face equation and mask size foreach (var surface in surfaceList) { // Get the points that are farther apart float Best_Mark = 0; Vector3F Best_Pivot = new Vector3F(); EdgeInfo[] Best_Edges = null; foreach (var pivotVert in surface.vertexEdges) { // Get external edges list var edges = pivotVert.Value.Where(t => t.normals.Count == 1).ToArray(); if (edges.Length != 2) { continue; } // Compute mark var edge1 = Vector3F.Subtract(edges[0].p1, edges[0].p2); var edge2 = Vector3F.Subtract(edges[1].p1, edges[1].p2); var mark = (1 - Math.Abs(Vector3F.DotProduct(edge1.GetUnit(), edge2.GetUnit())));// *edge1.GetLengthSquared() * edge2.GetLengthSquared(); // Does this bet the beat result? if (mark > Best_Mark) { Best_Mark = mark; Best_Pivot = pivotVert.Key; Best_Edges = edges; } } surface.anchors = new Vector3F[] { Best_Pivot, Best_Edges[0].p1 == Best_Pivot ? Best_Edges[0].p2 : Best_Edges[0].p1, Best_Edges[1].p1 == Best_Pivot ? Best_Edges[1].p2 : Best_Edges[1].p1 }; // Define initail surface equation var B = surface.anchors[0]; var E0 = Vector3F.Subtract(surface.anchors[1], B); var E1 = Vector3F.Subtract(surface.anchors[2], B); var Normal = Vector3F.CrossProduct(E0, E1).GetUnit(); // Should we flip the normal? //if (E0.GetLengthSquared() > E1.GetLengthSquared()) if (Vector3F.DotProduct(surface.faces[0].computedNormal, Normal) < 0.5) { var temp = E0; E0 = E1; E1 = temp; // Recompute normal Normal = Vector3F.CrossProduct(E0, E1).GetUnit(); } // Normalize edges E0 = Vector3F.CrossProduct(E1, Normal).GetUnit(); E1.Normalize(); // Get surface space 2d bounding box var minS = float.MaxValue; var maxS = float.MinValue; var minT = float.MaxValue; var maxT = float.MinValue; for (int iv = 0; iv < surface.expanded_vertices.Length; iv++) { var res = PointQuadDistance(surface.expanded_vertices[iv], B, E0, E1); if (res.s > maxS) { maxS = res.s; } if (res.s < minS) { minS = res.s; } if (res.t > maxT) { maxT = res.t; } if (res.t < minT) { minT = res.t; } } // Scale edges so the entire polygoin will fit 0..1 surface.surface_B = B = Vector3F.Add(B, Vector3F.Add(Vector3F.Multiply(E0, minS), Vector3F.Multiply(E1, minT))); surface.surface_E0 = E0 = Vector3F.Multiply(E0, (maxS - minS)); surface.surface_E1 = E1 = Vector3F.Multiply(E1, (maxT - minT)); // Compute image size surface.maskSize = new Size(512, (int)(512 * E0.GetLength() / E1.GetLength())); } // Create main mask image var totalHeight = surfaceList.Sum(t => t.maskSize.Height); var maskImg = new Bitmap(512, totalHeight, PixelFormat.Format24bppRgb); var mask_g = Graphics.FromImage(maskImg); mask_g.FillRectangle(Brushes.Black, new Rectangle(0, 0, maskImg.Width, maskImg.Height)); var topPos = 0; // Draw mask and debug images int counter = 0; foreach (var surface in surfaceList) { // Skip empty suurfaces if (surface.maskSize.Height == 0) { continue; } // Cache things var B = surface.surface_B; var E0 = surface.surface_E0; var E1 = surface.surface_E1; // Define debug image size var dbgImgBorder = 10; var dbgImgSize = new Size(surface.maskSize.Width + dbgImgBorder * 2, surface.maskSize.Height + dbgImgBorder * 2 + 40); var dbgImgRect = new Rectangle(ImgBorder, ImgBorder, surface.maskSize.Width, surface.maskSize.Height); // Define mask position var maskImgRect = new Rectangle(0, topPos, surface.maskSize.Width, surface.maskSize.Height); glslCode += string.Format("future = BouncePointQuad(positions[i].xyz, future, (float3)({0:+d;-d;0}, {1}, {2}), (float3)({3}, {4}, {5}), (float3)({6}, {7}, {8}), surfacesMask, {9}, {10}, edgeOffset);\r\n", F2S(B.X), F2S(B.Y), F2S(B.Z), F2S(E0.X), F2S(E0.Y), F2S(E0.Z), F2S(E1.X), F2S(E1.Y), F2S(E1.Z), topPos, surface.maskSize.Height); // Move position in mask topPos += surface.maskSize.Height; // Draw triangles var dbgImage = new Bitmap(dbgImgRect.Width + ImgBorder * 2, dbgImgRect.Height + ImgBorder * 2 + 40); var g = Graphics.FromImage(dbgImage); g.FillRectangle(Brushes.White, new Rectangle(0, 0, dbgImage.Width, dbgImage.Height)); foreach (var face in surface.faces) { // Draw debug var points = new[] { PointInQuad2D(face.vertices[0], B, E0, E1, dbgImgRect), PointInQuad2D(face.vertices[1], B, E0, E1, dbgImgRect), PointInQuad2D(face.vertices[2], B, E0, E1, dbgImgRect) }; g.FillPolygon(Brushes.Pink, points); // Draw mask var maskPoints = new[] { PointInQuad2D(face.vertices[0], B, E0, E1, maskImgRect), PointInQuad2D(face.vertices[1], B, E0, E1, maskImgRect), PointInQuad2D(face.vertices[2], B, E0, E1, maskImgRect) }; mask_g.FillPolygon(Brushes.White, maskPoints); mask_g.DrawPolygon(Pens.LightGray, maskPoints); } // Draw anchor points var qs1 = PointInQuad2D(surface.anchors[0], B, E0, E1, dbgImgRect); var qs2 = PointInQuad2D(surface.anchors[1], B, E0, E1, dbgImgRect); var qs3 = PointInQuad2D(surface.anchors[2], B, E0, E1, dbgImgRect); //g.DrawEllipse(Pens.Green, qs1.X - 2, qs1.Y - 2, 5, 5); //g.DrawEllipse(Pens.Green, qs2.X - 2, qs2.Y - 2, 5, 5); //g.DrawEllipse(Pens.Green, qs3.X - 2, qs3.Y - 2, 5, 5); var fnt = new Font("Courier New", 10.0f, FontStyle.Regular); g.DrawString("B", fnt, Brushes.DarkBlue, qs1); g.DrawString("E0(s)", fnt, Brushes.DarkBlue, qs2); g.DrawString("E1(t)", fnt, Brushes.DarkBlue, qs3); // Draw Edges foreach (var edge in surface.edges) { // Check if an inner edge var innerEdge = (edge.normals.Count > 1); // Draw Edge g.DrawLine(innerEdge ? Pens.Red : Pens.Green, PointInQuad2D(edge.p1, B, E0, E1, dbgImgRect), PointInQuad2D(edge.p2, B, E0, E1, dbgImgRect)); // Draw Edge normal if (!innerEdge) { var mid = Vector3F.Multiply(Vector3F.Add(edge.p1, edge.p2), 0.5f); var norm = Vector3F.Add(mid, Vector3F.Multiply(edge.normals[0], 0.2f)); g.DrawLine(Pens.Purple, PointInQuad2D(mid, B, E0, E1, dbgImgRect), PointInQuad2D(norm, B, E0, E1, dbgImgRect)); } } //var fnt = new Font("Courier New", 10.0f, FontStyle.Regular); foreach (var vertex in surface.vertices) { var pnt = PointInQuad2D(vertex, B, E0, E1, dbgImgRect); //g.DrawString(surface.vertexEdges[vertex].Count.ToString(), fnt, Brushes.DarkCyan, pnt); } g.DrawString("v0 = " + obj.positions[surface.faces[0].positionIdx[0] - 1].ToString(), fnt, Brushes.Black, new PointF(10, dbgImage.Height - 50)); g.DrawString("B = " + B.ToString(), fnt, Brushes.Black, new PointF(10, dbgImage.Height - 40)); g.DrawString("E0 = " + E0.ToString(), fnt, Brushes.Black, new PointF(10, dbgImage.Height - 30)); g.DrawString("E1 = " + E1.ToString(), fnt, Brushes.Black, new PointF(10, dbgImage.Height - 20)); g.Dispose(); dbgImage.Save(Path.Combine(debugImages, "face_" + counter++ + ".bmp"), ImageFormat.Bmp); } mask_g.Dispose(); // Write equations File.WriteAllText(equOutput, glslCode); // Write mask bitmap maskImg.Save(maskOutput, ImageFormat.Png); }
private SurfaceInfo DistanceToSurface(Vector3 point, BIHNode node) { if (node == null) return new SurfaceInfo(); if (node.children != null){ /** * If the current node is not a leaf, figure out which side of the split plane that contains the query point, and recurse down that side. * You will get the index and distance to the closest triangle in that subtree. * Then, check if the distance to the nearest triangle is closer to the query point than the distance between the query point and the split plane. * If it is closer, there is no need to recurse down the other side of the KD tree and you can just return. * Otherwise, you will need to recurse down the other way too, and return whichever result is closer. */ SurfaceInfo si = new SurfaceInfo(); // child nodes overlap if (node.pivots[0] > node.pivots[1]){ // CASE 1: we are in the overlapping zone: recurse down both. if (point[node.axis] <= node.pivots[0] && point[node.axis] >= node.pivots[1]){ si = DistanceToSurface(point, nodes[node.children[0]]); SurfaceInfo si2 = DistanceToSurface(point, nodes[node.children[1]]); if (si2.distanceSqr < si.distanceSqr) si = si2; } // CASE 2: to the right of left pivot, that is: in the right child only. else if (point[node.axis] > node.pivots[0]){ si = DistanceToSurface(point, nodes[node.children[1]]); // only recurse down left child if nearest surface in right child is furthest than left pivot. float pivotDistance = point[node.axis] - node.pivots[0]; if (si.distanceSqr > pivotDistance*pivotDistance){ SurfaceInfo si2 = DistanceToSurface(point, nodes[node.children[0]]); if (si2.distanceSqr < si.distanceSqr) si = si2; } } // CASE 3: to the left of right pivot, that is: in the left child only. else{ si = DistanceToSurface(point, nodes[node.children[0]]); // only recurse down right child if nearest surface in left child is furthest than right pivot. float pivotDistance = node.pivots[1] - point[node.axis]; if (si.distanceSqr > pivotDistance*pivotDistance){ SurfaceInfo si2 = DistanceToSurface(point, nodes[node.children[1]]); if (si2.distanceSqr < si.distanceSqr) si = si2; } } } // child nodes dont overlap. else{ // CASE 4: we are in the middle. just pick up one child (I chose right), get minimum, and if the other child pivot is nearer, recurse down it too. // Just like case 2. if (point[node.axis] > node.pivots[0] && point[node.axis] < node.pivots[1]){ si = DistanceToSurface(point, nodes[node.children[1]]); // only recurse down left child if nearest surface in right child is furthest than left pivot. float pivotDistance = point[node.axis] - node.pivots[0]; if (si.distanceSqr > pivotDistance*pivotDistance){ SurfaceInfo si2 = DistanceToSurface(point, nodes[node.children[0]]); if (si2.distanceSqr < si.distanceSqr) si = si2; } } // CASE 5: in the left child. Just like case 3. else if (point[node.axis] <= node.pivots[0]){ si = DistanceToSurface(point, nodes[node.children[0]]); // only recurse down right child if nearest surface in left child is furthest than right pivot. float pivotDistance = node.pivots[1] - point[node.axis]; if (si.distanceSqr > pivotDistance*pivotDistance){ SurfaceInfo si2 = DistanceToSurface(point, nodes[node.children[1]]); if (si2.distanceSqr < si.distanceSqr) si = si2; } } // CASE 6: in the right child. Just like case 2 else if (point[node.axis] >= node.pivots[1]){ si = DistanceToSurface(point, nodes[node.children[1]]); // only recurse down left child if nearest surface in right child is furthest than left pivot. float pivotDistance = point[node.axis] - node.pivots[0]; if (si.distanceSqr > pivotDistance*pivotDistance){ SurfaceInfo si2 = DistanceToSurface(point, nodes[node.children[0]]); if (si2.distanceSqr < si.distanceSqr) si = si2; } } } return si; }else{ return DistanceToTriangles(point,node.triangles); } }