From ff1e14bf44200cfd3dd15f240a480e46baa3b968 Mon Sep 17 00:00:00 2001 From: Bengt Gustafsson Date: Thu, 29 Dec 2016 18:29:22 +0100 Subject: [PATCH 1/3] Changed handling of collada meshes with multiple instances so that the prim.Asset values are the same in all Prims, while the difference in rotation, position and scale deduced from the Collada instance transform matrix are stored in the Position, Scale and Rotation members of each prim, properly adjusted for the rescaling and offseting done to the mesh vertices to fit into the unit cube of SL meshes. This fixes bugs related to the case that several instances of the same mesh but with different rotation in their transformation matrix was present in the Collada file, which previously caused distorted objects except for those having the same rotation as the first instance. A caveat is that now, as the incoming transform matrix is not used when creating the vertices and as the ModelPrim only stores rotation, scale and translation files which have transforms containing shear etc. not encodable by these three vectors will produce erroneous output even if there is only one instance of each mesh. At the same time save some time and space during conversion by sharing the Positions and Faces members of all prims and not redoing the AddPositions and AddFacesFromPolyList calls for each instace (as results are identical). Applications that change the vertices or faces in situ in individual prim instances may suffer. --- OpenMetaverse/ImportExport/ColladalLoader.cs | 90 +++++++++++--------- 1 file changed, 51 insertions(+), 39 deletions(-) diff --git a/OpenMetaverse/ImportExport/ColladalLoader.cs b/OpenMetaverse/ImportExport/ColladalLoader.cs index 601ea10f..d9b5abb6 100644 --- a/OpenMetaverse/ImportExport/ColladalLoader.cs +++ b/OpenMetaverse/ImportExport/ColladalLoader.cs @@ -439,49 +439,62 @@ namespace OpenMetaverse.ImportExport ParseVisualScene(); ParseMaterials(); - foreach (var item in Model.Items) - { - if (item is library_geometries) - { + foreach (var item in Model.Items) { + if (item is library_geometries) { var geometries = (library_geometries)item; - foreach (var geo in geometries.geometry) - { + foreach (var geo in geometries.geometry) { var mesh = geo.Item as mesh; - if (mesh == null) continue; + if (mesh == null) + continue; - var nodes = Nodes.FindAll(n => n.MeshID == geo.id); - if (nodes != null) - { - byte[] mesh_asset = null; - foreach (var node in nodes) - { + var nodes = Nodes.FindAll(n => n.MeshID == geo.id); // Find all instances of this geometry + if (nodes != null) { + ModelPrim firstPrim = null; // The first prim is actually calculated, the others are just copied from it. + + Vector3 asset_scale = new Vector3(1,1,1); + Vector3 asset_offset = new Vector3(0, 0, 0); // Scale and offset between Collada and OS asset (Which is always in a unit cube) + + foreach (var node in nodes) { var prim = new ModelPrim(); prim.ID = node.ID; Prims.Add(prim); - Matrix4 primTransform = transform; - primTransform = primTransform * node.Transform; - AddPositions(mesh, prim, primTransform); + // First node is used to create the asset. This is as the code to crate the byte array is somewhat + // erroneously placed in the ModelPrim class. + if (firstPrim == null) { + firstPrim = prim; + AddPositions(out asset_scale, out asset_offset, mesh, prim, transform); // transform is used only for inch -> meter and up axis transform. - foreach (var mitem in mesh.Items) - { - if (mitem is triangles) - { - AddFacesFromPolyList(Triangles2Polylist((triangles)mitem), mesh, prim, primTransform); - } - if (mitem is polylist) - { - AddFacesFromPolyList((polylist)mitem, mesh, prim, primTransform); - } - } + foreach (var mitem in mesh.Items) { + if (mitem is triangles) + AddFacesFromPolyList(Triangles2Polylist((triangles)mitem), mesh, prim, transform); // Transform is used to turn normals according to up axis + if (mitem is polylist) + AddFacesFromPolyList((polylist)mitem, mesh, prim, transform); + } - if (mesh_asset == null) - { prim.CreateAsset(UUID.Zero); - mesh_asset = prim.Asset; } - else - prim.Asset = mesh_asset; + else { + // Copy the values set by Addpositions and AddFacesFromPolyList as these are the same as long as the mesh is the same + prim.Asset = firstPrim.Asset; + prim.BoundMin = firstPrim.BoundMin; + prim.BoundMax = firstPrim.BoundMax; + prim.Positions = firstPrim.Positions; + prim.Faces = firstPrim.Faces; + } + + // Note: This ignores any shear or similar non-linear effects. This can cause some problems but it + // is unlikely that authoring software can generate such matrices. + node.Transform.Decompose(out prim.Scale, out prim.Rotation, out prim.Position); + float roll, pitch, yaw; + node.Transform.GetEulerAngles(out roll, out pitch, out yaw); + + // The offset created when normalizing the mesh vertices into the OS unit cube must be rotated + // before being added to the position part of the Collada transform. + Matrix4 rot = Matrix4.CreateFromQuaternion(prim.Rotation); // Convert rotation to matrix for for Transform + Vector3 offset = Vector3.Transform(asset_offset * prim.Scale, rot); // The offset must be rotated and mutiplied by the Collada file's scale as the offset is added during rendering with the unit cube mesh already multiplied by the compound scale. + prim.Position += offset; + prim.Scale *= asset_scale; // Modify scale from Collada instance by the rescaling done in AddPositions() } } } @@ -503,7 +516,7 @@ namespace OpenMetaverse.ImportExport return null; } - void AddPositions(mesh mesh, ModelPrim prim, Matrix4 transform) + void AddPositions(out Vector3 scale, out Vector3 offset, mesh mesh, ModelPrim prim, Matrix4 transform) { prim.Positions = new List(); source posSrc = FindSource(mesh.source, mesh.vertices.input[0].source); @@ -530,21 +543,20 @@ namespace OpenMetaverse.ImportExport if (pos.Z < prim.BoundMin.Z) prim.BoundMin.Z = pos.Z; } - prim.Scale = prim.BoundMax - prim.BoundMin; - prim.Position = prim.BoundMin + (prim.Scale / 2); + scale = prim.BoundMax - prim.BoundMin; + offset = prim.BoundMin + (scale / 2); // Fit vertex positions into identity cube -0.5 .. 0.5 for (int i = 0; i < prim.Positions.Count; i++) { Vector3 pos = prim.Positions[i]; pos = new Vector3( - prim.Scale.X == 0 ? 0 : ((pos.X - prim.BoundMin.X) / prim.Scale.X) - 0.5f, - prim.Scale.Y == 0 ? 0 : ((pos.Y - prim.BoundMin.Y) / prim.Scale.Y) - 0.5f, - prim.Scale.Z == 0 ? 0 : ((pos.Z - prim.BoundMin.Z) / prim.Scale.Z) - 0.5f + scale.X == 0 ? 0 : ((pos.X - prim.BoundMin.X) / scale.X) - 0.5f, + scale.Y == 0 ? 0 : ((pos.Y - prim.BoundMin.Y) / scale.Y) - 0.5f, + scale.Z == 0 ? 0 : ((pos.Z - prim.BoundMin.Z) / scale.Z) - 0.5f ); prim.Positions[i] = pos; } - } int[] StrToArray(string s) From 4c6e11a146336928fe21ba8442fef8df98b54828 Mon Sep 17 00:00:00 2001 From: Bengt Gustafsson Date: Thu, 29 Dec 2016 18:38:13 +0100 Subject: [PATCH 2/3] untabified --- OpenMetaverse/ImportExport/ColladalLoader.cs | 60 ++++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/OpenMetaverse/ImportExport/ColladalLoader.cs b/OpenMetaverse/ImportExport/ColladalLoader.cs index d9b5abb6..1d5256e1 100644 --- a/OpenMetaverse/ImportExport/ColladalLoader.cs +++ b/OpenMetaverse/ImportExport/ColladalLoader.cs @@ -445,56 +445,56 @@ namespace OpenMetaverse.ImportExport foreach (var geo in geometries.geometry) { var mesh = geo.Item as mesh; if (mesh == null) - continue; + continue; - var nodes = Nodes.FindAll(n => n.MeshID == geo.id); // Find all instances of this geometry + var nodes = Nodes.FindAll(n => n.MeshID == geo.id); // Find all instances of this geometry if (nodes != null) { - ModelPrim firstPrim = null; // The first prim is actually calculated, the others are just copied from it. + ModelPrim firstPrim = null; // The first prim is actually calculated, the others are just copied from it. - Vector3 asset_scale = new Vector3(1,1,1); - Vector3 asset_offset = new Vector3(0, 0, 0); // Scale and offset between Collada and OS asset (Which is always in a unit cube) + Vector3 asset_scale = new Vector3(1,1,1); + Vector3 asset_offset = new Vector3(0, 0, 0); // Scale and offset between Collada and OS asset (Which is always in a unit cube) foreach (var node in nodes) { var prim = new ModelPrim(); prim.ID = node.ID; Prims.Add(prim); - // First node is used to create the asset. This is as the code to crate the byte array is somewhat - // erroneously placed in the ModelPrim class. + // First node is used to create the asset. This is as the code to crate the byte array is somewhat + // erroneously placed in the ModelPrim class. if (firstPrim == null) { - firstPrim = prim; - AddPositions(out asset_scale, out asset_offset, mesh, prim, transform); // transform is used only for inch -> meter and up axis transform. + firstPrim = prim; + AddPositions(out asset_scale, out asset_offset, mesh, prim, transform); // transform is used only for inch -> meter and up axis transform. - foreach (var mitem in mesh.Items) { - if (mitem is triangles) - AddFacesFromPolyList(Triangles2Polylist((triangles)mitem), mesh, prim, transform); // Transform is used to turn normals according to up axis - if (mitem is polylist) - AddFacesFromPolyList((polylist)mitem, mesh, prim, transform); - } + foreach (var mitem in mesh.Items) { + if (mitem is triangles) + AddFacesFromPolyList(Triangles2Polylist((triangles)mitem), mesh, prim, transform); // Transform is used to turn normals according to up axis + if (mitem is polylist) + AddFacesFromPolyList((polylist)mitem, mesh, prim, transform); + } prim.CreateAsset(UUID.Zero); } - else { - // Copy the values set by Addpositions and AddFacesFromPolyList as these are the same as long as the mesh is the same - prim.Asset = firstPrim.Asset; - prim.BoundMin = firstPrim.BoundMin; - prim.BoundMax = firstPrim.BoundMax; - prim.Positions = firstPrim.Positions; - prim.Faces = firstPrim.Faces; - } + else { + // Copy the values set by Addpositions and AddFacesFromPolyList as these are the same as long as the mesh is the same + prim.Asset = firstPrim.Asset; + prim.BoundMin = firstPrim.BoundMin; + prim.BoundMax = firstPrim.BoundMax; + prim.Positions = firstPrim.Positions; + prim.Faces = firstPrim.Faces; + } - // Note: This ignores any shear or similar non-linear effects. This can cause some problems but it - // is unlikely that authoring software can generate such matrices. - node.Transform.Decompose(out prim.Scale, out prim.Rotation, out prim.Position); + // Note: This ignores any shear or similar non-linear effects. This can cause some problems but it + // is unlikely that authoring software can generate such matrices. + node.Transform.Decompose(out prim.Scale, out prim.Rotation, out prim.Position); float roll, pitch, yaw; node.Transform.GetEulerAngles(out roll, out pitch, out yaw); - // The offset created when normalizing the mesh vertices into the OS unit cube must be rotated - // before being added to the position part of the Collada transform. - Matrix4 rot = Matrix4.CreateFromQuaternion(prim.Rotation); // Convert rotation to matrix for for Transform + // The offset created when normalizing the mesh vertices into the OS unit cube must be rotated + // before being added to the position part of the Collada transform. + Matrix4 rot = Matrix4.CreateFromQuaternion(prim.Rotation); // Convert rotation to matrix for for Transform Vector3 offset = Vector3.Transform(asset_offset * prim.Scale, rot); // The offset must be rotated and mutiplied by the Collada file's scale as the offset is added during rendering with the unit cube mesh already multiplied by the compound scale. prim.Position += offset; - prim.Scale *= asset_scale; // Modify scale from Collada instance by the rescaling done in AddPositions() + prim.Scale *= asset_scale; // Modify scale from Collada instance by the rescaling done in AddPositions() } } } From a54dc6f3238bc36d5ebd7061d719ebd509bdcaa8 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 30 Dec 2016 13:04:55 +0000 Subject: [PATCH 3/3] Fix sliding expiration in ExpiringCache --- OpenMetaverseTypes/ExpiringCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenMetaverseTypes/ExpiringCache.cs b/OpenMetaverseTypes/ExpiringCache.cs index 1d4aa25b..5588b598 100644 --- a/OpenMetaverseTypes/ExpiringCache.cs +++ b/OpenMetaverseTypes/ExpiringCache.cs @@ -62,7 +62,7 @@ namespace OpenMetaverse public void Accessed() { if (slidingExpiration) - expirationDate = DateTime.Now.Add(slidingExpirationWindowSize); + expirationDate = DateTime.UtcNow.Add(slidingExpirationWindowSize); } public int CompareTo(TKey other)