Пример #1
0
    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);
    }
Пример #2
0
        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);
        }
Пример #3
0
        public void setRenderTarget(Surface target)
        {
            SurfaceInfo info = target.getInfo();

            device.setRenderTarget(target);
            initializeViewport(info.width, info.height);
        }
Пример #4
0
    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);
    }
Пример #5
0
    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);
    }
Пример #6
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);
    }
Пример #7
0
    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;
                }
            }
        }
    }
Пример #8
0
    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);
    }
Пример #9
0
 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();
    }
Пример #11
0
    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);
    }
Пример #12
0
    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);
    }
Пример #13
0
        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);
        }
Пример #14
0
    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);
    }
Пример #15
0
        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);
            }
        }
Пример #16
0
    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());
    }
Пример #17
0
    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());
    }
Пример #18
0
    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();
    }
Пример #21
0
    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);
        }
    }
Пример #22
0
    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);
        }
    }
Пример #23
0
    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);
        }
    }
Пример #24
0
 abstract public Vector3 OnHandle(Light light, SurfaceInfo surfaceInfo, RaycastHit hit, Ray ray);
Пример #25
0
 public static SurfaceInfoObject GetSurfaceInfoFor(Collider collider, Vector3 worldPos)
 {
     return(SurfaceInfo.GetSurfaceInfoFor(collider.gameObject, worldPos));
 }
Пример #26
0
    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);
            }
        }
    }
Пример #27
0
 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;
         }
     }
 }
Пример #28
0
 public override void OnClick()
 {
     _plugin.CurrentTool = this;
     ToolSceneDrawFlyByPath.m_frm.Application = this._plugin;
     this.isurface_0 = SurfaceInfo.GetSurfaceFromLayer(this._plugin.CurrentLayer);
 }
Пример #29
0
        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));
                }
            }
        }
Пример #30
0
        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);
        }
Пример #31
0
        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);
            }
        }