private bool ConvertSplineRenderDataToData(Data data, CreatureStateBodyVisual.SplineRenderData splineRenderData, UnityEngine.Camera mainCamera, float scale)
    {
        var tempP0  = mainCamera.WorldToScreenPoint(new UnityEngine.Vector3(splineRenderData.p0.x, splineRenderData.p0.y, splineRenderData.p0.z));
        var tempP1  = mainCamera.WorldToScreenPoint(new UnityEngine.Vector3(splineRenderData.p1.x, splineRenderData.p1.y, splineRenderData.p1.z));
        var tempP2  = mainCamera.WorldToScreenPoint(new UnityEngine.Vector3(splineRenderData.p2.x, splineRenderData.p2.y, splineRenderData.p2.z));
        var radius0 = splineRenderData.p0.w * scale; // * 0.5f;
        var radius1 = splineRenderData.p1.w * scale; // * 0.5f;
        var radius2 = splineRenderData.p2.w * scale; // * 0.5f;

        //bail if all three spheres are less than near plane, The z position is in world units from the camera.
        float nearPlane = 0.01f;

        if ((tempP0.z + radius0 < nearPlane) && (tempP1.z + radius1 < nearPlane) && (tempP2.z + radius2 < nearPlane))
        {
            return(false);
        }
        tempP0.z = UnityEngine.Mathf.Max(nearPlane, tempP0.z);
        tempP1.z = UnityEngine.Mathf.Max(nearPlane, tempP1.z);
        tempP2.z = UnityEngine.Mathf.Max(nearPlane, tempP2.z);
        float averageZ = (tempP0.z + tempP1.z + tempP2.z) / 3.0f;
        //todo: reduce radius as we get close to near plane?

        //at depth averageZ, what is our conversion factor between world units and screen pixels
        var verScale = UnityEngine.Mathf.Tan(UnityEngine.Mathf.Deg2Rad * (_fov / 2.0f)) * 2.0f * averageZ;
        var hozScale = verScale * _aspect;

        var worldUnitsToPixels = UnityEngine.Screen.height / verScale;

        //projected onto averageZ, xy [0 ... width pixels, 0 ... screen pixels] z pixel radius
        var projectedP0 = ProjectXYRadius(tempP0, averageZ, radius0, worldUnitsToPixels);
        var projectedP1 = ProjectXYRadius(tempP1, averageZ, radius1, worldUnitsToPixels);
        var projectedP2 = ProjectXYRadius(tempP2, averageZ, radius2, worldUnitsToPixels);

        //get screen pixel space bounds
        // clamp to screen bounds
        var minX = UnityEngine.Mathf.Clamp(UnityEngine.Mathf.Min(UnityEngine.Mathf.Min(projectedP0.x - projectedP0.z, projectedP1.x - projectedP1.z), projectedP2.x - projectedP2.z), 0.0f, UnityEngine.Screen.width);
        var minY = UnityEngine.Mathf.Clamp(UnityEngine.Mathf.Min(UnityEngine.Mathf.Min(projectedP0.y - projectedP0.z, projectedP1.y - projectedP1.z), projectedP2.y - projectedP2.z), 0.0f, UnityEngine.Screen.height);

        var maxX = UnityEngine.Mathf.Clamp(UnityEngine.Mathf.Max(UnityEngine.Mathf.Max(projectedP0.x + projectedP0.z, projectedP1.x + projectedP1.z), projectedP2.x + projectedP2.z), 0.0f, UnityEngine.Screen.width);
        var maxY = UnityEngine.Mathf.Clamp(UnityEngine.Mathf.Max(UnityEngine.Mathf.Max(projectedP0.y + projectedP0.z, projectedP1.y + projectedP1.z), projectedP2.y + projectedP2.z), 0.0f, UnityEngine.Screen.height);

        // zero area, off screen
        if ((minX == maxX) || (minY == maxY))
        {
            return(false);
        }

        var worldSpaceCenterOffest = new UnityEngine.Vector3(
            ((((maxX + minX) * 0.5f) - (0.5f * UnityEngine.Screen.width)) / UnityEngine.Screen.width) * hozScale,
            ((((maxY + minY) * 0.5f) - (0.5f * UnityEngine.Screen.height)) / UnityEngine.Screen.height) * verScale,
            0.0f
            );

        //var screenPixelBounds = new UnityEngine.Rect(minX, minY, maxX - minX, maxY - minY);
        var meshWorldSpaceOrigin = mainCamera.transform.position + (mainCamera.transform.forward * averageZ)
                                   + (mainCamera.transform.right * worldSpaceCenterOffest.x)
                                   + (mainCamera.transform.up * worldSpaceCenterOffest.y);
        var meshWorldSpaceScale = new UnityEngine.Vector3(
            ((maxX - minX) / UnityEngine.Screen.width) * hozScale,
            ((maxY - minY) / UnityEngine.Screen.height) * verScale,
            1.0f
            );

        //get the mesh transform
        data.gameObject.transform.position   = meshWorldSpaceOrigin;
        data.gameObject.transform.rotation   = mainCamera.transform.rotation;
        data.gameObject.transform.localScale = meshWorldSpaceScale;

        //get the spline data into shader coordinates (uv)
        var screenRect = new UnityEngine.Rect(0.0f, 0.0f, UnityEngine.Screen.width, UnityEngine.Screen.height);
        var aspectRect = new UnityEngine.Rect(0.5f - (_aspect / 2.0f), 0.0f, _aspect, 1.0f);

        {
            var pos  = DscUtils.UnclampedRectSpaceConvertTo(screenRect, new UnityEngine.Vector2(projectedP0.x, projectedP0.y));
            var pos2 = DscUtils.UnclampedRectSpaceConvertFrom(aspectRect, pos);
            data.splineComponent.p0.Set(pos2.x, pos2.y, projectedP0.z / UnityEngine.Screen.height, 0.0f);
        }
        {
            var pos  = DscUtils.UnclampedRectSpaceConvertTo(screenRect, new UnityEngine.Vector2(projectedP1.x, projectedP1.y));
            var pos2 = DscUtils.UnclampedRectSpaceConvertFrom(aspectRect, pos);
            data.splineComponent.p1.Set(pos2.x, pos2.y, projectedP1.z / UnityEngine.Screen.height, 0.0f);
        }
        {
            var pos  = DscUtils.UnclampedRectSpaceConvertTo(screenRect, new UnityEngine.Vector2(projectedP2.x, projectedP2.y));
            var pos2 = DscUtils.UnclampedRectSpaceConvertFrom(aspectRect, pos);
            data.splineComponent.p2.Set(pos2.x, pos2.y, projectedP2.z / UnityEngine.Screen.height, 0.0f);
        }

        {
            var posLow   = DscUtils.UnclampedRectSpaceConvertTo(screenRect, new UnityEngine.Vector2(minX, minY));
            var pos2Low  = DscUtils.UnclampedRectSpaceConvertFrom(aspectRect, posLow);
            var posHigh  = DscUtils.UnclampedRectSpaceConvertTo(screenRect, new UnityEngine.Vector2(maxX, maxY));
            var pos2High = DscUtils.UnclampedRectSpaceConvertFrom(aspectRect, posHigh);

            data.splineComponent.uvScale.Set(pos2Low.x, pos2Low.y, pos2High.x - pos2Low.x, pos2High.y - pos2Low.y);
        }

        data.splineComponent.color = splineRenderData.color;

        data.splineComponent.ManualUpdate();

        return(true);
    }
Example #2
0
    private void UpdateFace(CreatureState creatureState, UnityEngine.Camera mainCamera, float scale)
    {
        var e0 = new UnityEngine.Vector3(creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p1.x - creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p0.x, creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p1.y - creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p0.y, creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p1.z - creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p0.z);
        var e1 = new UnityEngine.Vector3(creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p2.x - creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p0.x, creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p2.y - creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p0.y, creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p2.z - creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p0.z);

        var right = UnityEngine.Vector3.Cross(e1, e0);
        var up    = UnityEngine.Vector3.Cross(right, e0).normalized;

        var eyeFactor = UnityEngine.Vector3.Dot(e0.normalized, mainCamera.transform.forward) < 0.5f ? 1.0f : 0.0f;

        var faceBase = new UnityEngine.Vector3(creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p0.x, creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p0.y, creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p0.z)
                       + (up * (creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p0.w * 0.25f * scale));

        var tempP = mainCamera.WorldToScreenPoint(faceBase);

        var radiusP  = creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.p0.w * 2.0f * scale;// * 0.5f;
        var averageZ = tempP.z - radiusP;

        var yMul = (0.0f < UnityEngine.Vector3.Dot(mainCamera.transform.up, up)) ? 1.0f : -1.0f;


        var verScale = UnityEngine.Mathf.Tan(UnityEngine.Mathf.Deg2Rad * (_fov / 2.0f)) * 2.0f * averageZ;
        var hozScale = verScale * _aspect;

        var worldUnitsToPixels = UnityEngine.Screen.height / verScale;

        //projected onto averageZ, xy [0 ... width pixels, 0 ... screen pixels] z pixel radius
        var projectedP = ProjectXYRadius(tempP, averageZ, radiusP, worldUnitsToPixels);

        var eye0x      = projectedP.x - (0.2f * projectedP.z);
        var eyeY       = projectedP.y;
        var eye1x      = projectedP.x + (0.2f * projectedP.z);
        var eyeRx      = projectedP.z * 0.15f * eyeFactor; //* blink
        var eyeRy      = projectedP.z * 0.2f;
        var eyeBrow0a  = new UnityEngine.Vector2(projectedP.x - (0.075f * projectedP.z), eyeY + (yMul * eyeRy * 0.95f));
        var eyeBrow0b  = new UnityEngine.Vector2(projectedP.x - (0.5f * projectedP.z), eyeY + (yMul * eyeRy * 2.0f));
        var browThick0 = projectedP.z * 0.1f;
        var browThick1 = projectedP.z * 0.125f;

        var eyeBrow1a = new UnityEngine.Vector2(projectedP.x + (0.075f * projectedP.z), eyeY + (yMul * eyeRy * 0.95f));
        var eyeBrow1b = new UnityEngine.Vector2(projectedP.x + (0.5f * projectedP.z), eyeY + (yMul * eyeRy * 2.0f));

        float minX = UnityEngine.Mathf.Clamp(UnityEngine.Mathf.Min(eye0x - eyeRx, eyeBrow0b.x - browThick1), 0.0f, UnityEngine.Screen.width);
        float minY = UnityEngine.Mathf.Clamp(UnityEngine.Mathf.Min(eyeY - eyeRy, eyeBrow0b.y - browThick1), 0.0f, UnityEngine.Screen.height);

        float maxX = UnityEngine.Mathf.Clamp(UnityEngine.Mathf.Max(eye1x + eyeRx, eyeBrow1b.x + browThick1), 0.0f, UnityEngine.Screen.width);
        float maxY = UnityEngine.Mathf.Clamp(UnityEngine.Mathf.Max(eyeY + eyeRy, eyeBrow1b.y + browThick1), 0.0f, UnityEngine.Screen.height);

        var worldSpaceCenterOffest = new UnityEngine.Vector3(
            ((((maxX + minX) * 0.5f) - (0.5f * UnityEngine.Screen.width)) / UnityEngine.Screen.width) * hozScale,
            ((((maxY + minY) * 0.5f) - (0.5f * UnityEngine.Screen.height)) / UnityEngine.Screen.height) * verScale,
            0.0f
            );

        //var screenPixelBounds = new UnityEngine.Rect(minX, minY, maxX - minX, maxY - minY);
        var meshWorldSpaceOrigin = mainCamera.transform.position + (mainCamera.transform.forward * averageZ)
                                   + (mainCamera.transform.right * worldSpaceCenterOffest.x)
                                   + (mainCamera.transform.up * worldSpaceCenterOffest.y);
        var meshWorldSpaceScale = new UnityEngine.Vector3(
            ((maxX - minX) / UnityEngine.Screen.width) * hozScale,
            ((maxY - minY) / UnityEngine.Screen.height) * verScale,
            1.0f
            );

        //get the mesh transform
        _faceGameObject.transform.position   = meshWorldSpaceOrigin;
        _faceGameObject.transform.rotation   = mainCamera.transform.rotation;
        _faceGameObject.transform.localScale = meshWorldSpaceScale;

        var screenRect = new UnityEngine.Rect(0.0f, 0.0f, UnityEngine.Screen.width, UnityEngine.Screen.height);
        var aspectRect = new UnityEngine.Rect(0.5f - (_aspect / 2.0f), 0.0f, _aspect, 1.0f);

        _facePropertyBlock.colorA = creatureState.creatureStateBody.creatureStateBodyVisual.faceRenderData.color;

        {
            var posLow   = DscUtils.UnclampedRectSpaceConvertTo(screenRect, new UnityEngine.Vector2(minX, minY));
            var pos2Low  = DscUtils.UnclampedRectSpaceConvertFrom(aspectRect, posLow);
            var posHigh  = DscUtils.UnclampedRectSpaceConvertTo(screenRect, new UnityEngine.Vector2(maxX, maxY));
            var pos2High = DscUtils.UnclampedRectSpaceConvertFrom(aspectRect, posHigh);

            _facePropertyBlock.uvScale.Set(pos2Low.x, pos2Low.y, pos2High.x - pos2Low.x, pos2High.y - pos2Low.y);
        }

        {
            var pos  = DscUtils.UnclampedRectSpaceConvertTo(screenRect, new UnityEngine.Vector2(eye0x, eyeY));
            var pos2 = DscUtils.UnclampedRectSpaceConvertFrom(aspectRect, pos);
            _facePropertyBlock.eye0.Set(pos2.x, pos2.y, eyeRx / UnityEngine.Screen.height, eyeRy / UnityEngine.Screen.height);
        }

        {
            var posA  = DscUtils.UnclampedRectSpaceConvertTo(screenRect, eyeBrow0a);
            var posA2 = DscUtils.UnclampedRectSpaceConvertFrom(aspectRect, posA);
            var posB  = DscUtils.UnclampedRectSpaceConvertTo(screenRect, eyeBrow0b);
            var posB2 = DscUtils.UnclampedRectSpaceConvertFrom(aspectRect, posB);

            _facePropertyBlock.eyeBrow0.Set(posA2.x, posA2.y, posB2.x, posB2.y);
        }

        {
            var pos  = DscUtils.UnclampedRectSpaceConvertTo(screenRect, new UnityEngine.Vector2(eye1x, eyeY));
            var pos2 = DscUtils.UnclampedRectSpaceConvertFrom(aspectRect, pos);
            _facePropertyBlock.eye1.Set(pos2.x, pos2.y, eyeRx / UnityEngine.Screen.height, eyeRy / UnityEngine.Screen.height);
        }

        {
            var posA  = DscUtils.UnclampedRectSpaceConvertTo(screenRect, eyeBrow1a);
            var posA2 = DscUtils.UnclampedRectSpaceConvertFrom(aspectRect, posA);
            var posB  = DscUtils.UnclampedRectSpaceConvertTo(screenRect, eyeBrow1b);
            var posB2 = DscUtils.UnclampedRectSpaceConvertFrom(aspectRect, posB);

            _facePropertyBlock.eyeBrow1.Set(posA2.x, posA2.y, posB2.x, posB2.y);
        }

        {
            _facePropertyBlock.data0.Set(0.0f, 1.0f, browThick0 / UnityEngine.Screen.height, browThick1 / UnityEngine.Screen.height);
        }

        _facePropertyBlock.ManualUpdate();
    }