예제 #1
0
        protected unsafe override void OnUpdate()
        {
            var    contexts     = new NativeList <UIContextData>(8, Allocator.TempJob);
            var    graphData    = new NativeList <UIGraphData>(8, Allocator.TempJob);
            Entity schemaEntity = Entity.Null;
            int    nodeCount    = 0;

            meshes.Clear();
            Entities.ForEach((UIObject obj) =>
            {
                //TODO: Writes every conversion frame but will crash under certain conditions otherwise. Crashes observed involving opening and closing subscenes without modifying anything after script reload.

                var guid = obj.model?.GetOutputGuid();

                if (!string.IsNullOrEmpty(guid))
                {
                    IntPtr ptr;
                    long allocatedLength;
                    using (var fs = File.OpenRead(UnityEditor.AssetDatabase.GUIDToAssetPath(guid))) {
                        allocatedLength = math.ceilpow2(fs.Length);
                        ptr             = (IntPtr)UnsafeUtility.Malloc(allocatedLength, 0, Allocator.Persistent);
                        using (var us = new UnmanagedMemoryStream((byte *)ptr.ToPointer(), 0, fs.Length, FileAccess.Write)) {
                            fs.CopyTo(us);
                        }
                    }
                    var gd = new UIGraphData {
                        value = ptr, allocatedLength = allocatedLength
                    };
                    graphData.Add(gd);
                    nodeCount += gd.GetNodeCount();
                    contexts.Add(UIContextData.CreateContext(obj.camera));
                    meshes.Add(new Mesh());
                    if (schemaEntity == Entity.Null)
                    {
                        schemaEntity = CreateAdditionalEntity(obj);
                        DstEntityManager.SetName(schemaEntity, "UI Schema");
                        DstEntityManager.AddSharedComponentData(schemaEntity, new UISchemaData {
                            value = schema
                        });
                    }
                    DeclareAssetDependency(obj.gameObject, schema);
                }
                obj.cachedGuid = guid;
            });

            if (graphData.Length > 0)
            {
                var graphDataArray = graphData.AsArray();
                var meshData       = Mesh.AllocateWritableMeshData(graphData.Length);
                var submeshes      = new NativeArray <int>(graphData.Length, Allocator.TempJob);
                var stream         = new NativeStream(nodeCount, Allocator.TempJob);
                new UILayoutJob
                {
                    schema        = compiledSchema,
                    graphs        = graphDataArray,
                    contexts      = contexts,
                    meshDataArray = meshData
                }.Schedule(graphData.Length, 1).Complete();
                new UINodeDecompositionJob
                {
                    schema       = compiledSchema,
                    graphs       = graphDataArray,
                    nodes        = stream.AsWriter(),
                    submeshCount = submeshes
                }.Schedule(graphData.Length, 1).Complete();
                Mesh.ApplyAndDisposeWritableMeshData(meshData, meshes);
                var result = stream.ToNativeArray <DedicatedNodeInfo>(Allocator.Temp);
                var nodes  = new NativeMultiHashMap <int, DedicatedNodeInfo>(graphData.Length, Allocator.Temp);
                for (int i = 0; i < result.Length; i++)
                {
                    nodes.Add(result[i].graphIndex, result[i]);
                }
                stream.Dispose();
                submeshes.Dispose();
                int index        = 0;
                var nodeEntities = new NativeList <Entity>(Allocator.Temp);
                Entities.ForEach((UIObject obj) =>
                {
                    if (!string.IsNullOrEmpty(obj.cachedGuid))
                    {
                        var entity = GetPrimaryEntity(obj);
                        var gd     = graphDataArray[index];
                        DstEntityManager.AddComponentData(entity, new UIGraph {
                            value = new BlittableAssetReference(obj.cachedGuid)
                        });
                        DstEntityManager.AddSharedComponentData <UIDirtyState>(entity, false);
                        Material material;
                        if (gd.TryGetConfigBlock(0, UIConfigLayoutTable.MaterialConfig, out IntPtr result))
                        {
                            material = UnityEditor.AssetDatabase.LoadAssetAtPath <Material>(UnityEditor.AssetDatabase.GUIDToAssetPath(((MaterialConfig *)(result.ToPointer()))->material.ToHex()));
                        }
                        else
                        {
                            material = obj.model.GetMaterial();
                        }



                        DeclareAssetDependency(obj.gameObject, obj.model);


                        DeclareAssetDependency(obj.gameObject, material);

                        DstEntityManager.AddSharedComponentData(entity, new RenderMesh
                        {
                            mesh                 = meshes[index],
                            material             = material,
                            subMesh              = 0,
                            castShadows          = ShadowCastingMode.Off,
                            receiveShadows       = false,
                            needMotionVectorPass = false,
                            layer                = obj.gameObject.layer
                        });
                        DstEntityManager.AddComponentData(entity, new UIPixelScale {
                            value = obj.pixelScale
                        });
                        var bounds = meshes[index].GetSubMesh(0).bounds.ToAABB();
                        DstEntityManager.AddComponentData(entity, new RenderBounds {
                            Value = bounds
                        });

                        DstEntityManager.AddComponent <UIContext>(entity);

                        if (obj.camera != null)
                        {
                            DstEntityManager.AddComponentData(entity, new UIContextSource {
                                value = GetPrimaryEntity(obj.camera)
                            });
                            var ltc = new LocalToCamera
                            {
                                cameraLTW = obj.camera.transform.localToWorldMatrix,
                                clipPlane = new float2(obj.camera.nearClipPlane, obj.camera.farClipPlane),
                                alignment = obj.alignment,
                                offsetX   = obj.offsetX,
                                offsetY   = obj.offsetY
                            };
                            DstEntityManager.AddComponentData(entity, ltc);
                            var rotation  = quaternion.LookRotation(ltc.cameraLTW.c2.xyz, ltc.cameraLTW.c1.xyz);
                            var translate = ltc.cameraLTW.c3.xyz + new float3(ltc.alignment.GetOffset(bounds.Size.xy, new float2(Screen.currentResolution.height * obj.camera.aspect, Screen.currentResolution.height)), 0) + math.mul(rotation, math.forward() * ltc.clipPlane.x * 2f) + (math.mul(rotation, math.right()) * ltc.offsetX.Normalize(contexts[index])) + (math.mul(rotation, math.up()) * ltc.offsetY.Normalize(contexts[index]));
                            DstEntityManager.SetComponentData(entity, new LocalToWorld {
                                Value = float4x4.TRS(translate, rotation, obj.pixelScale)
                            });
                            DeclareDependency(obj, obj.camera);
                        }

                        DstEntityManager.AddComponent <PerInstanceCullingTag>(entity);

                        nodeEntities.Clear();
                        var nodeInfoIter = nodes.GetValuesForKey(index);
                        while (nodeInfoIter.MoveNext())
                        {
                            var nodeInfo   = nodeInfoIter.Current;
                            var nodeEntity = CreateAdditionalEntity(obj);
                            var name       = graphData[index].GetNodeName(nodeInfo.nodeIndex);
                            if (string.IsNullOrEmpty(name))
                            {
                                name = $"Node#{nodeInfo.nodeIndex}";
                            }
                            DstEntityManager.SetName(nodeEntity, $"{DstEntityManager.GetName(entity)}[{name}]");
                            DstEntityManager.AddComponentData(nodeEntity, new UINodeInfo {
                                index = nodeInfo.nodeIndex, submesh = nodeInfo.submesh
                            });
                            DstEntityManager.AddComponentData(nodeEntity, new UIParent {
                                value = entity
                            });
                            DstEntityManager.AddComponentData(nodeEntity, new Parent {
                                Value = entity
                            });
                            DstEntityManager.AddComponentData(nodeEntity, new LocalToWorld {
                                Value = float4x4.identity
                            });
                            DstEntityManager.AddComponentData(nodeEntity, new Rotation {
                                Value = quaternion.identity
                            });
                            DstEntityManager.AddComponentData(nodeEntity, new Scale {
                                Value = 1f
                            });
                            DstEntityManager.AddComponentData(nodeEntity, new LocalToParent {
                                Value = float4x4.identity
                            });
                            if (gd.TryGetConfigBlock(0, UIConfigLayoutTable.MaterialConfig, out result))
                            {
                                material = UnityEditor.AssetDatabase.LoadAssetAtPath <Material>(UnityEditor.AssetDatabase.GUIDToAssetPath(((MaterialConfig *)result.ToPointer())->material.ToHex()));
                            }
                            else
                            {
                                material = obj.model.GetMaterial();
                            }
                            DstEntityManager.AddSharedComponentData(nodeEntity, new RenderMesh
                            {
                                mesh                 = meshes[index],
                                material             = material,
                                subMesh              = nodeInfo.submesh,
                                castShadows          = ShadowCastingMode.Off,
                                receiveShadows       = false,
                                needMotionVectorPass = false,
                                layer                = obj.gameObject.layer
                            });
                            DstEntityManager.AddComponentData(nodeEntity, new RenderBounds {
                                Value = meshes[index].GetSubMesh(nodeInfo.submesh).bounds.ToAABB()
                            });
                            DstEntityManager.AddComponent <PerInstanceCullingTag>(nodeEntity);
                            nodeEntities.Add(nodeEntity);
                            ConfigureEditorRenderData(nodeEntity, obj.gameObject, true);
                        }
                        var buffer = DstEntityManager.AddBuffer <UINode>(entity);
                        buffer.AddRange(nodeEntities.AsArray().Reinterpret <UINode>());
                        UnsafeUtility.Free(graphData[index].value.ToPointer(), Allocator.TempJob);
                        index++;
                        ConfigureEditorRenderData(entity, obj.gameObject, true);
                    }
                });
            }

            contexts.Dispose();
            graphData.Dispose();
        }
예제 #2
0
        public override void UpdateNode()
        {
            TerrainMaterial.renderQueue = (int)ParentBody.RenderQueue + ParentBody.RenderQueueOffset;

            // NOTE : Body shape dependent...
            LocalToWorld = Matrix4x4d.ToMatrix4x4d(ParentBody.transform.localToWorldMatrix) * FaceToLocal;

            TangentFrameToWorld = new Matrix3x3d(LocalToWorld.m[0, 0], LocalToWorld.m[0, 1], LocalToWorld.m[0, 2],
                                                 LocalToWorld.m[1, 0], LocalToWorld.m[1, 1], LocalToWorld.m[1, 2],
                                                 LocalToWorld.m[2, 0], LocalToWorld.m[2, 1], LocalToWorld.m[2, 2]);

            LocalToCamera = GodManager.Instance.View.WorldToCameraMatrix * LocalToWorld;
            LocalToScreen = GodManager.Instance.View.CameraToScreenMatrix * LocalToCamera;

            var invLocalToCamera = LocalToCamera.Inverse();

            DeformedCameraPosition = invLocalToCamera * Vector3d.zero;
            DeformedFrustumPlanes  = Frustum3d.GetFrustumPlanes(LocalToScreen); // NOTE : Extract frustum planes from LocalToScreen matrix...

            LocalCameraPosition = Deformation.DeformedToLocal(DeformedCameraPosition);

            DeformedLocalToTangent = Deformation.DeformedToTangentFrame(GodManager.Instance.View.WorldCameraPosition) * LocalToWorld * Deformation.LocalToDeformedDifferential(LocalCameraPosition);

            var m = Deformation.LocalToDeformedDifferential(LocalCameraPosition, true);

            var left  = DeformedFrustumPlanes[0].xyz.Normalized();
            var right = DeformedFrustumPlanes[1].xyz.Normalized();

            var fov = (float)Functions.Safe_Acos(-left.Dot(right));

            SplitDistance  = SplitFactor * Screen.width / 1024.0f * Mathf.Tan(40.0f * Mathf.Deg2Rad) / Mathf.Tan(fov / 2.0f);
            DistanceFactor = (float)Math.Max(new Vector3d(m.m[0, 0], m.m[1, 0], m.m[2, 0]).Magnitude(), new Vector3d(m.m[0, 1], m.m[1, 1], m.m[2, 1]).Magnitude());

            if (SplitDistance < 1.1f || SplitDistance > 128.0f || !Functions.IsFinite(SplitDistance))
            {
                SplitDistance = 1.1f;
            }

            var splitDistanceBlending = SplitDistance + 1.0f;

            DistanceBlending = new Vector2(splitDistanceBlending, 2.0f * SplitDistance - splitDistanceBlending);

            // Initializes data structures for horizon occlusion culling
            if (UseHorizonCulling && LocalCameraPosition.z <= TerrainQuadRoot.ZMax)
            {
                var deformedDirection = invLocalToCamera * Vector3d.forward;
                var localDirection    = (Deformation.DeformedToLocal(deformedDirection) - LocalCameraPosition).Normalized();

                LocalCameraDirection = new Matrix2x2d(localDirection.y, -localDirection.x, -localDirection.x, -localDirection.y);

                for (var i = 0; i < HORIZON_SIZE; ++i)
                {
                    Horizon[i] = float.NegativeInfinity;
                }
            }

            if (ParentBody.UpdateLOD)
            {
                TerrainQuadRoot.UpdateLOD();
            }

            SetUniforms(TerrainMaterial);
        }