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); }
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(); }