Example #1
0
        /// <summary>
        /// <para>Creates a preview <see cref="Texture2D"/> of a model.</para>
        /// </summary>
        /// <param name="model">The object to render a preview of.</param>
        /// <param name="style">The style to render the model with.</param>
        /// <param name="width">The width (in pixels) of the rendered <see cref="Texture2D"/>.</param>
        /// <param name="height">The height (in pixels) of the rendered <see cref="Texture2D"/>.</param>
        /// <returns>
        /// <para>A rendered preview <see cref="Texture2D"/>.</para>
        /// </returns>
        public static Texture2D RenderModel(GameObject model, CameraSetup style, int width = 64, int height = 64)
        {
            if (model == null || model.Equals(null))
            {
                return(null);
            }

#if USE_PREVIEW_SCENE
            var previewObject = (GameObject)PrefabUtility.InstantiatePrefab(model, RenderCamera.scene);
#else
            var previewObject = (GameObject)PrefabUtility.InstantiatePrefab(model);
#endif

            previewObject.gameObject.hideFlags = HideFlags.HideAndDontSave;
            SetLayerRecursively(previewObject.transform);
            previewObject.SetActive(true);

            Texture2D result = null;

            style.ApplyToCamera(RenderCamera);

            try
            {
                var previewDir = previewObject.transform.rotation * style.PreviewDirection.normalized;

                prefabRenderers.Clear();
                previewObject.GetComponentsInChildren(prefabRenderers);

                var  previewBounds = new Bounds();
                bool anyRenderers  = false;
                for (int i = 0; i < prefabRenderers.Count; i++)
                {
                    var renderer = prefabRenderers[i];
                    if (!renderer.enabled)
                    {
                        continue;
                    }

                    if (!anyRenderers)
                    {
                        previewBounds = renderer.bounds;
                        anyRenderers  = true;
                    }
                    else
                    {
                        previewBounds.Encapsulate(renderer.bounds);
                    }
                }

                if (!anyRenderers)
                {
                    return(null);
                }

                var boundsCenter  = previewBounds.center;
                var boundsExtents = previewBounds.extents;
                var boundsSize    = 2f * boundsExtents;

                float aspect = (float)width / height;
                RenderCamera.aspect             = aspect;
                RenderCamera.transform.rotation = Quaternion.LookRotation(previewDir, previewObject.transform.up);

                float distance;
                if (style.Orthographic)
                {
                    RenderCamera.transform.position = boundsCenter;

                    minX = minY = Mathf.Infinity;
                    maxX = maxY = Mathf.NegativeInfinity;

                    var point = boundsCenter + boundsExtents;
                    ProjectBoundingBoxMinMax(point);
                    point.x -= boundsSize.x;
                    ProjectBoundingBoxMinMax(point);
                    point.y -= boundsSize.y;
                    ProjectBoundingBoxMinMax(point);
                    point.x += boundsSize.x;
                    ProjectBoundingBoxMinMax(point);
                    point.z -= boundsSize.z;
                    ProjectBoundingBoxMinMax(point);
                    point.x -= boundsSize.x;
                    ProjectBoundingBoxMinMax(point);
                    point.y += boundsSize.y;
                    ProjectBoundingBoxMinMax(point);
                    point.x += boundsSize.x;
                    ProjectBoundingBoxMinMax(point);

                    distance = boundsExtents.magnitude + 1f;
                    RenderCamera.orthographicSize = (1f + style.Padding * 2f) * Mathf.Max(maxY - minY, (maxX - minX) / aspect) * 0.5f;
                }
                else
                {
                    projectionPlaneHorizontal = new Plane(RenderCamera.transform.up, boundsCenter);
                    projectionPlaneVertical   = new Plane(RenderCamera.transform.right, boundsCenter);

                    float maxDistance = Mathf.NegativeInfinity;

                    var point = boundsCenter + boundsExtents;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style);
                    point.x    -= boundsSize.x;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style);
                    point.y    -= boundsSize.y;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style);
                    point.x    += boundsSize.x;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style);
                    point.z    -= boundsSize.z;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style);
                    point.x    -= boundsSize.x;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style);
                    point.y    += boundsSize.y;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style);
                    point.x    += boundsSize.x;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style);

                    distance = (1f + style.Padding * 2f) * Mathf.Sqrt(maxDistance);
                }

                RenderCamera.transform.position = boundsCenter - previewDir * distance;
                RenderCamera.farClipPlane       = distance * 4f;

                var temp      = RenderTexture.active;
                var renderTex = RenderTexture.GetTemporary(width, height, 16, RenderTextureFormat.ARGB32);
                RenderTexture.active = renderTex;

                if (style.TransparentBackground)
                {
                    GL.Clear(false, true, style.BackgroundColor);
                }

                RenderCamera.targetTexture = renderTex;

                RenderCamera.Render();
                RenderCamera.targetTexture = null;

                var textureFormat = style.TransparentBackground ? TextureFormat.ARGB32 : TextureFormat.RGB24;

                result = new Texture2D(width, height, textureFormat, false)
                {
                    wrapMode   = TextureWrapMode.Clamp,
                    filterMode = FilterMode.Point
                };
                result.ReadPixels(new Rect(0, 0, width, height), 0, 0, false);
                result.Apply(false, true);

                RenderTexture.active = temp;
                RenderTexture.ReleaseTemporary(renderTex);
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }
            finally
            {
                UnityEngine.Object.DestroyImmediate(previewObject);
            }

            return(result);
        }