Пример #1
0
        /// <summary>
        /// Get the size diviser used for the displayability of the Ocean dataset (structured grid)
        /// </summary>
        /// <returns>The field diviser applied along all axis</returns>
        public UInt32 GetFieldSizeDiviser()
        {
            VTKStructuredPoints ptsDesc = m_parser.GetStructuredPointsDescriptor();
            UInt32 x = (ptsDesc.Size[0] + DesiredDensity - 1) / DesiredDensity;
            UInt32 y = (ptsDesc.Size[1] + DesiredDensity - 1) / DesiredDensity;
            UInt32 z = (ptsDesc.Size[2] + DesiredDensity - 1) / DesiredDensity;

            return(Math.Max(Math.Max(x, y), z));
        }
Пример #2
0
        /// <summary>
        /// get the displayable size of the vector field. Indeed, due to hardware limitation, we cannot display all the vector field at once
        /// </summary>
        /// <returns>The vector field size displayable</returns>
        public Vector3Int GetDisplayableSize()
        {
            VTKStructuredPoints ptsDesc = m_parser.GetStructuredPointsDescriptor();

            if (ptsDesc.Size[0] == 0 || ptsDesc.Size[1] == 0 || ptsDesc.Size[2] == 0)
            {
                return(new Vector3Int(0, 0, 0));
            }

            int maxRatio = (int)GetFieldSizeDiviser();

            return(new Vector3Int((int)ptsDesc.Size[0] / maxRatio, (int)ptsDesc.Size[1] / maxRatio, (int)ptsDesc.Size[2] / maxRatio));
        }
Пример #3
0
        /// <summary>
        /// Create a small multiple object
        /// </summary>
        /// <param name="dataID">The parameter ID to use. Use Parser.GetPointFieldValueDescriptors(); to get the field ID</param>
        /// <returns>A VTKUnitySmallMultiple object.</returns>
        public VTKUnitySmallMultiple CreatePointFieldSmallMultiple(Int32 dataID)
        {
            VTKStructuredPoints   ptsDesc = m_parser.GetStructuredPointsDescriptor();
            VTKUnitySmallMultiple sm      = GameObject.Instantiate(SmallMultiplePrefab);
            Vector3Int            density = Density;

            unsafe
            {
                if (sm.InitFromPointField(m_parser, m_mesh, m_availableUVIDs[m_availableUVIDs.Count - 1], dataID,
                                          new Vector3Int((int)(ptsDesc.Size[0] / density.x),
                                                         (int)(ptsDesc.Size[1] / density.y * ptsDesc.Size[0]),
                                                         (int)(ptsDesc.Size[2] / density.z * ptsDesc.Size[1] * ptsDesc.Size[0])),
                                          density, m_mask))
                {
                    m_smallMultiples.Add(sm);
                    m_availableUVIDs.RemoveAt(m_availableUVIDs.Count - 1);
                    return(sm);
                }
            }

            Destroy(sm);
            return(null);
        }
Пример #4
0
        /// <summary>
        /// Initialize the StructuredGrid representation
        /// </summary>
        /// <param name="parser">The VKTParser to use.
        /// It should not be closed while this object is intented to being modified (e.g adding small multiples)</param>
        /// <param name="mask">The mask to apply point per point. if mask==null, we do not use it</param>
        /// <returns></returns>
        public unsafe bool Init(VTKParser parser, byte *mask = null)
        {
            m_parser = parser;
            m_mask   = mask;

            if (m_parser.GetDatasetType() != VTKDatasetType.VTK_STRUCTURED_POINTS)
            {
                Debug.Log("Error: The dataset should be a structured points dataset");
                return(false);
            }

            //Get the points and modify the points / normals buffer
            VTKStructuredPoints ptsDesc = m_parser.GetStructuredPointsDescriptor();
            Vector3Int          density = Density;

            Vector3[] pts = new Vector3[density.x * density.y * density.z];

            //Determine the positions for "normalizing" the object (the biggest axis of the object at "size = 1")
            Vector3 minPos = new Vector3((float)((density.x / 2) * ptsDesc.Size[0] / density.x * ptsDesc.Spacing[0]),
                                         (float)((density.y / 2) * ptsDesc.Size[1] / density.y * ptsDesc.Spacing[1]),
                                         (float)((density.z / 2) * ptsDesc.Size[2] / density.z * ptsDesc.Spacing[2]));
            Vector3 maxPos = new Vector3((float)((density.x - 1 + density.x / 2) * ptsDesc.Size[0] / density.x * ptsDesc.Spacing[0]),
                                         (float)((density.y - 1 + density.y / 2) * ptsDesc.Size[1] / density.y * ptsDesc.Spacing[1]),
                                         (float)((density.z - 1 + density.z / 2) * ptsDesc.Size[2] / density.z * ptsDesc.Spacing[2]));

            float maxAxis = Math.Max(maxPos.x - minPos.x, Math.Max(maxPos.y - minPos.y, maxPos.z - minPos.z));

            for (int k = 0; k < density.z; k++)
            {
                for (int j = 0; j < density.y; j++)
                {
                    for (int i = 0; i < density.x; i++)
                    {
                        pts[i + density.x * j + density.x * density.y * k] = new Vector3((float)((i - density.x / 2) * ptsDesc.Size[0] / density.x * ptsDesc.Spacing[0]) / maxAxis,
                                                                                         (float)((j - density.y / 2) * ptsDesc.Size[1] / density.y * ptsDesc.Spacing[1]) / maxAxis,
                                                                                         (float)((k - density.z / 2) * ptsDesc.Size[2] / density.z * ptsDesc.Spacing[2]) / maxAxis);
                    }
                }
            }

            //Store the maximas positions
            m_minPos = pts[0];
            m_maxPos = pts[pts.Length - 1];

            //The element buffer
            Vector3Int offsetMask = new Vector3Int((int)(ptsDesc.Size[0] / density.x),
                                                   (int)(ptsDesc.Size[1] / density.y * ptsDesc.Size[0]),
                                                   (int)(ptsDesc.Size[2] / density.z * ptsDesc.Size[1] * ptsDesc.Size[0]));

            int[] triangles = new int[(density.x - 1) * (density.y - 1) * (density.z - 1) * 36];
            for (int k = 0; k < density.z - 1; k++)
            {
                for (int j = 0; j < density.y - 1; j++)
                {
                    for (int i = 0; i < density.x - 1; i++)
                    {
                        int offset = (i + j * (density.x - 1) + k * (density.x - 1) * (density.y - 1)) * 36;
                        //Test the mask
                        //If we are encountering a missing mask, put the triangles to to point "0" (i.e empty triangle)
                        //And go at the end of the loop
                        if (mask != null)
                        {
                            for (int k2 = 0; k2 < 2; k2++)
                            {
                                for (int j2 = 0; j2 < 2; j2++)
                                {
                                    for (int i2 = 0; i2 < 2; i2++)
                                    {
                                        if (*(mask + (i + i2) * offsetMask.x + (j + j2) * offsetMask.y + (k + k2) * offsetMask.z) == 0)
                                        {
                                            for (int t = 0; t < 36; t++)
                                            {
                                                triangles[offset + t] = 0;
                                            }
                                            goto endTriangleLoop;
                                        }
                                    }
                                }
                            }
                        }

                        //Front
                        triangles[offset]     = i + 1 + j * density.x + k * density.x * density.y;
                        triangles[offset + 1] = i + j * density.x + k * density.x * density.y;
                        triangles[offset + 2] = i + 1 + (j + 1) * density.x + k * density.x * density.y;
                        triangles[offset + 3] = i + 1 + (j + 1) * density.x + k * density.x * density.y;
                        triangles[offset + 4] = i + j * density.x + k * density.x * density.y;
                        triangles[offset + 5] = i + (j + 1) * density.x + k * density.x * density.y;

                        //Back
                        triangles[offset + 6]  = i + 1 + (j + 1) * density.x + (k + 1) * density.x * density.y;
                        triangles[offset + 7]  = i + j * density.x + (k + 1) * density.x * density.y;
                        triangles[offset + 8]  = i + 1 + j * density.x + (k + 1) * density.x * density.y;
                        triangles[offset + 9]  = i + (j + 1) * density.x + (k + 1) * density.x * density.y;
                        triangles[offset + 10] = i + j * density.x + (k + 1) * density.x * density.y;
                        triangles[offset + 11] = i + 1 + (j + 1) * density.x + (k + 1) * density.x * density.y;

                        //Left
                        triangles[offset + 12] = i + j * density.x + k * density.x * density.y;
                        triangles[offset + 13] = i + j * density.x + (k + 1) * density.x * density.y;
                        triangles[offset + 14] = i + (j + 1) * density.x + (k + 1) * density.x * density.y;
                        triangles[offset + 15] = i + (j + 1) * density.x + k * density.x * density.y;
                        triangles[offset + 16] = i + j * density.x + k * density.x * density.y;
                        triangles[offset + 17] = i + (j + 1) * density.x + (k + 1) * density.x * density.y;

                        //Right
                        triangles[offset + 18] = (i + 1) + j * density.x + (k + 1) * density.x * density.y;
                        triangles[offset + 19] = (i + 1) + j * density.x + k * density.x * density.y;
                        triangles[offset + 20] = (i + 1) + (j + 1) * density.x + (k + 1) * density.x * density.y;
                        triangles[offset + 21] = (i + 1) + j * density.x + k * density.x * density.y;
                        triangles[offset + 22] = (i + 1) + (j + 1) * density.x + k * density.x * density.y;
                        triangles[offset + 23] = (i + 1) + (j + 1) * density.x + (k + 1) * density.x * density.y;

                        //Top
                        triangles[offset + 24] = (i + 1) + (j + 1) * density.x + k * density.x * density.y;
                        triangles[offset + 25] = i + (j + 1) * density.x + k * density.x * density.y;
                        triangles[offset + 26] = i + (j + 1) * density.x + (k + 1) * density.x * density.y;
                        triangles[offset + 27] = (i + 1) + (j + 1) * density.x + (k + 1) * density.x * density.y;
                        triangles[offset + 28] = (i + 1) + (j + 1) * density.x + k * density.x * density.y;
                        triangles[offset + 29] = i + (j + 1) * density.x + (k + 1) * density.x * density.y;

                        //Bottom
                        triangles[offset + 30] = (i + 1) + j * density.x + k * density.x * density.y;
                        triangles[offset + 31] = i + j * density.x + (k + 1) * density.x * density.y;
                        triangles[offset + 32] = i + j * density.x + k * density.x * density.y;
                        triangles[offset + 33] = (i + 1) + j * density.x + k * density.x * density.y;
                        triangles[offset + 34] = (i + 1) + j * density.x + (k + 1) * density.x * density.y;
                        triangles[offset + 35] = i + j * density.x + (k + 1) * density.x * density.y;

                        //End the the triangle loop
endTriangleLoop:
                        continue;
                    }
                }
            }

            //Create the mesh
            m_mesh             = new Mesh();
            m_mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
            m_mesh.vertices    = pts;
            m_mesh.triangles   = triangles;
            m_mesh.UploadMeshData(false);

            //Small multiples array
            m_smallMultiples = new List <VTKUnitySmallMultiple>();
            m_availableUVIDs = new List <Int32>();

            for (Int32 i = 0; i < 8; i++)
            {
                m_availableUVIDs.Add(i);
            }

            return(true);
        }
Пример #5
0
        /// <summary>
        /// Initialize the small multiple from point field data
        /// </summary>
        /// <param name="parser">The VTK Parser</param>
        /// <param name="mesh">The mesh to display</param>
        /// <param name="uvID">The ID where to put the color data</param>
        /// <param name="valueID">The ID of the VTKFieldPointValue</param>
        /// <param name="offset">The offset along each axis to apply : pos = x*offset.x + y*offset.y + z*offset.z</param>
        /// <param name="density">The density in use</param>
        /// <param name="mask">The mask to apply along each point</param>
        /// <returns></returns>
        public unsafe bool InitFromPointField(VTKParser parser, Mesh mesh, Int32 uvID, Int32 valueID, Vector3Int offset, Vector3Int density, byte *mask)
        {
            m_material = new Material(ColorMaterial);
            m_values   = new float[density.x * density.y * density.z];

            //Check the ID
            if (uvID > 7)
            {
                Debug.Log("The uvID must be between 0 to 7. This is a limitation of Unity for working within a common mesh...");
                return(false);
            }
            m_mesh = mesh;

            VTKStructuredPoints descPts = parser.GetStructuredPointsDescriptor();

            //Determine the maximum and minimum positions
            Vector3 minModelPos = new Vector3((float)(-descPts.Size[0] / 2.0 * descPts.Spacing[0]),
                                              (float)(-descPts.Size[1] / 2.0 * descPts.Spacing[1]),
                                              (float)(-descPts.Size[2] / 2.0 * descPts.Spacing[2]));
            Vector3 maxModelPos = -minModelPos;

            //The value buffer
            List <VTKFieldValue> fieldDesc = parser.GetPointFieldValueDescriptors();

            if (fieldDesc.Count < valueID)
            {
                Debug.Log("No value to display");
                return(false);
            }
            VTKValue       val    = parser.ParseAllFieldValues(fieldDesc[valueID]);
            List <Vector4> colors = new List <Vector4>((int)(density.x * density.y * density.z));

            //Determine the minimum and maximum value and their position
            m_maxVal = float.MinValue;
            m_minVal = float.MaxValue;
            Vector3 minLoc = new Vector3();
            Vector3 maxLoc = new Vector3();

            for (UInt32 i = 0; i < val.NbValues; i++)
            {
                if (mask != null && mask[i] == 0)
                {
                    continue;
                }
                float v = (float)val.ReadAsDouble(i * fieldDesc[valueID].NbValuesPerTuple);
                if (m_maxVal < v)
                {
                    m_maxVal = v;
                    maxLoc   = new Vector3(i % descPts.Size[0], (i / descPts.Size[0]) % descPts.Size[1], i / (descPts.Size[0] * descPts.Size[1]));
                }
                if (m_minVal > v)
                {
                    m_minVal = v;
                    minLoc   = new Vector3(i % descPts.Size[0], (i / descPts.Size[0]) % descPts.Size[1], i / (descPts.Size[0] * descPts.Size[1]));
                }
            }

            //Normalize the location (between 0.0 and 1.0 for the most "long" axis)
            Vector3[] vec = new Vector3[2] {
                maxLoc, minLoc
            };
            Vector3 modelDist    = maxModelPos - minModelPos;
            float   maxModelDist = Math.Max(modelDist.x, Math.Max(modelDist.y, modelDist.z));

            for (int i = 0; i < vec.Length; i++)
            {
                Vector3 l = vec[i];
                l = (new Vector3((float)(l.x * descPts.Spacing[0]),
                                 (float)(l.y * descPts.Spacing[1]),
                                 (float)(l.z * descPts.Spacing[2])) + minModelPos) / maxModelDist;
                vec[i] = l;
            }

            Debug.Log($"Min : {m_minVal} Max : {m_maxVal}");

            //Fill the color array
            maxLoc = vec[0];
            minLoc = vec[1];
            UInt64 colorValueOff = 0;

            for (UInt32 k = 0; k < density.z; k++)
            {
                for (UInt32 j = 0; j < density.y; j++)
                {
                    for (UInt32 i = 0; i < density.x; i++, colorValueOff++)
                    {
                        UInt64 fieldOff = (UInt64)(i * offset.x + j * offset.y + k * offset.z);
                        //Check the mask
                        if (mask != null && *(mask + fieldOff) == 0)
                        {
                            colors.Add(new Vector4(0.0f, 0.0f, 0.0f, 0.0f));
                            m_values[colorValueOff] = m_minVal;
                            continue;
                        }
                        float c = val.ReadAsFloat(fieldOff * fieldDesc[valueID].NbValuesPerTuple);
                        m_values[colorValueOff] = c;
                        c = (float)((c - m_minVal) / (m_maxVal - m_minVal));

                        //LAB color space (warm - cold)
                        Color?col = null;
                        if (c < 0.5)
                        {
                            col = LABColor.Lerp(coldColor, whiteColor, 2.0f * c).ToXYZ().ToRGB();
                        }
                        else
                        {
                            col = LABColor.Lerp(whiteColor, warmColor, 2.0f * (c - 0.5f)).ToXYZ().ToRGB();
                        }
                        colors.Add(new Vector4(col.Value.r, col.Value.g, col.Value.b, 1.0f));
                    }
                }
            }

            //Update the mesh / material
            m_mesh.SetUVs(uvID, colors);
            m_mesh.UploadMeshData(false);
            m_colorID = uvID;

            for (int i = 0; i < 8; i++)
            {
                if (i != m_colorID)
                {
                    m_material.DisableKeyword($"TEXCOORD{i}_ON");
                }
            }
            m_material.EnableKeyword($"TEXCOORD{m_colorID}_ON");
            PlaneEnabled  = false;
            SphereEnabled = false;

            CreateGameObjects(vec);

            return(true);
        }