protected override void OnCreate() { base.OnCreate(); var scene = CreateScene(false); Component_Mesh mesh = ObjectOfPreview as Component_Mesh; if (mesh != null) { Component_MeshInSpace objInSpace = scene.CreateComponent <Component_MeshInSpace>(); objInSpace.Mesh = mesh; } scene.Enabled = true; SetCameraByBounds(scene.CalculateTotalBoundsOfObjectsInSpace()); if (mesh.EditorCameraTransform != null) { var tr = mesh.EditorCameraTransform; CameraInitialDistance = (tr.Position - CameraLookTo).Length(); CameraDirection = SphericalDirection.FromVector(CameraLookTo - tr.Position); } }
//void ParentSprite_GetRenderSceneDataBefore( Component_ObjectInSpace sender, ViewportRenderingContext context, GetRenderSceneDataMode mode ) //{ //} private void ParentSprite_GetRenderSceneDataAddToFrameData(Component_MeshInSpace sender, ViewportRenderingContext context, GetRenderSceneDataMode mode, ref Component_RenderingPipeline.RenderSceneData.MeshItem item) { Component_Material material = null; var animation = PlayAnimation.Value as Component_SpriteAnimation; if (animation != null) { UpdateAnimationTime(); material = animation.Material; var frame = animation.GetFrameByTime(currentAnimationTime); if (frame != null) { var m = frame.Material.Value; if (m != null) { material = m; } } } item.ReplaceMaterial = material; item.ReplaceMaterialSelectively = null; }
protected override void OnEnabledInSimulation() { //create a mesh mesh = CreateComponent <Component_Mesh>(enabled: false); mesh.Name = "Mesh 1"; //generate vertices. use StandardVertex to make it easier StandardVertex.StaticOneTexCoord[] vertices = new StandardVertex.StaticOneTexCoord[4]; var v = new StandardVertex.StaticOneTexCoord(); v.Position = new Vector3F(-0.4f, -0.4f, 0f); v.Normal = new Vector3F(0, 0, 1); v.Tangent = new Vector4F(1, 0, 0, 0); v.Color = new ColorValue(1, 1, 1); //v.TexCoord0 = new Vector2F(-1, -1); vertices[0] = v; v.Position = new Vector3F(0.4f, -0.4f, 0); vertices[1] = v; v.Position = new Vector3F(0.4f, 0.4f, 0); vertices[2] = v; v.Position = new Vector3F(-0.4f, 0.4f, 0); vertices[3] = v; //generate indices var indices = new int[] { 0, 1, 2, 2, 3, 0 }; //create geometry of the mesh geometry = mesh.CreateComponent <Component_MeshGeometry>(); geometry.VertexStructure = StandardVertex.MakeStructure(StandardVertex.Components.StaticOneTexCoord, true, out int vertexSize); geometry.Vertices = ConvertVertices(vertices); geometry.Indices = indices; //mesh has been created, now we can enable it mesh.Enabled = true; meshInSpace = CreateComponent <Component_MeshInSpace>(enabled: false); meshInSpace.Transform = new Transform(new Vector3(1, 1, 1)); //make reference to the mesh. 'Root' reference - global path from scene root. meshInSpace.Mesh = ReferenceUtility.MakeRootReference(mesh); meshInSpace.Color = new ColorValue(1, 0, 0); meshInSpace.Enabled = true; }
private void ParentSprite_MeshOutputOverride(Component_MeshInSpace sender, ref Component_Mesh result) { var animation = PlayAnimation.Value as Component_SpriteAnimation; if (animation != null) { UpdateAnimationTime(); var frame = animation.GetFrameByTime(currentAnimationTime); if (frame != null) { result = SpriteMeshManager.GetMesh(frame.UV.Value.ToRectangleF()); } } }
protected override void CalculateCPU(Component_Skeleton skeleton, Component_Mesh originalMesh, Component_Mesh modifiableMesh) { if (EngineApp.ApplicationType == EngineApp.ApplicationTypeEnum.Simulation) { if (Component_Scene.All != null && Component_Scene.All.Length > 0) { // Component_MeshInSpace[] sphs = new Component_MeshInSpace[2]; // Component_MeshInSpace sph = Component_Scene.All[0]?.GetComponent<Component_MeshInSpace>("chest"); // sphs[0] = sph?.GetComponent<Component_MeshInSpace>("upper_arm.R"); // sphs[1] = sphs[0]?.GetComponent<Component_MeshInSpace>("forearm.R"); // var bones = skeleton?.GetBones(false); // if (bones != null) // { // var sR = Array.Find(bones, item => item.Name == "upper_arm.R"); // sR.Transform = new Transform(sphs[0].TransformV.Position, sphs[0].TransformV.Rotation, sR.Transform.Value.Scale); // var sR1 = Array.Find(bones, item => item.Name == "forearm.R"); // sR1.Transform = new Transform(sphs[1].TransformV.Position, sphs[1].TransformV.Rotation, sR1.Transform.Value.Scale); // } Component_MeshInSpace sph = Component_Scene.All[0]?.GetComponent <Component_MeshInSpace>("chest"); var sphch = sph.GetComponents <Component_MeshInSpace>(false, true, false); var bones = skeleton?.GetBones(false); if (bones != null) { var sR = Array.Find(bones, item => item.Name == "chest"); sR.Transform = new Transform(sph.TransformV.Position, sph.TransformV.Rotation, sR.Transform.Value.Scale); var chB = sR.GetComponents <Component_SkeletonBone>(false, true, false); for (int i = 0; i < chB.Length; i = i + 1) { var cursph = Array.Find(sphch, item => item.Name == chB[i].Name); if (cursph != null) { chB[i].Transform = new Transform(cursph.TransformV.Position, cursph.TransformV.Rotation, chB[i].Transform.Value.Scale); } } } } MainViewport_UpdateBeforeOutput(Project.SimulationApp.MainViewport, skeleton); base.CalculateCPU(skeleton, originalMesh, modifiableMesh); } }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); var scene = CreateScene(false); Component_Mesh mesh = ObjectForPreview as Component_Mesh; if (mesh != null) { Component_MeshInSpace objInSpace = scene.CreateComponent <Component_MeshInSpace>(); objInSpace.Mesh = mesh; } scene.Enabled = true; SetCameraByBounds(scene.CalculateTotalBoundsOfObjectsInSpace()); }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); var scene = CreateScene(false); if (Mesh != null) { Component_MeshInSpace objInSpace = scene.CreateComponent <Component_MeshInSpace>(); objInSpace.Mesh = Mesh; skeletonAnimationController = objInSpace.CreateComponent <Component_MeshInSpaceAnimationController>(); } scene.Enabled = true; if (Document != null) { Document.UndoSystem.ListOfActionsChanged += UndoSystem_ListOfActionsChanged; } if (ObjectOfWindow != null) { SelectObjects(new object[] { ObjectOfWindow }); } }
//static byte[] ToVertices( Net3dBool.Vector3[] vertices, MeshData.MeshGeometryFormat vs ) //{ // byte[] ret = new byte[ vertices.Length * vs.vertexSize ]; // unsafe // { // fixed ( byte* ptr = ret ) // { // for( int i = 0; i < vertices.Length; i++ ) // { // var v = vertices[ i ]; // var pos = (Vector3F*)( ptr + i * vs.vertexSize + vs.positionOffset ); // ( *pos ) = new Vector3F( (float)v.x, (float)v.y, (float)v.z ); // } // } // } // return ret; //} //The data are extracted from Component_Mesh.ExtractedStructure. //Хотя можно взять из MeshGeometry.Vertices,Indices, но там проиндексировано вместе с другими элементами(normals,...). static List <(Vector3F[] positions, int[] indices)> GetData(Component_MeshInSpace ms) { Component_Mesh.ExtractedStructure structure = ms.Mesh.Value.ExtractStructure(); var ret = new List <(Vector3F[] positions, int[] indices)>(); //extract old positions var oldPositions = new Vector3F[structure.MeshGeometries.Length][]; for (int geomIndex = 0; geomIndex < structure.MeshGeometries.Length; geomIndex++) { var vs = new MeshData.MeshGeometryFormat(structure.MeshGeometries[geomIndex].VertexStructure); oldPositions[geomIndex] = new Vector3F[structure.MeshGeometries[geomIndex].Vertices.Length / vs.vertexSize]; unsafe { fixed(byte *ptr = structure.MeshGeometries[geomIndex].Vertices) { for (int i = 0; i < oldPositions[geomIndex].Length; i++) { oldPositions[geomIndex][i] = *(Vector3F *)(ptr + i * vs.vertexSize + vs.positionOffset); } } } } //------------ var geomTriangles = new List <Component_Mesh.StructureClass.FaceVertex> [structure.MeshGeometries.Length]; for (int i = 0; i < structure.MeshGeometries.Length; i++) { geomTriangles[i] = new List <Component_Mesh.StructureClass.FaceVertex>(); } for (int faceIndex = 0; faceIndex < structure.Structure.Faces.Length; faceIndex++) { var face = structure.Structure.Faces[faceIndex]; for (int i = 0; i < face.Triangles.Length; i++) { geomTriangles[face.Triangles[i].RawGeometry].Add(face.Triangles[i]); } } for (int i = 0; i < geomTriangles.Length; i++) { var g = geomTriangles[i]; int[] oldVertexToNewMapping = new int[structure.Structure.Vertices.Length]; for (int j = 0; j < oldVertexToNewMapping.Length; j++) { oldVertexToNewMapping[j] = -1; } int nextIndex = 0; var newPositions = new List <Vector3F>(); var newIndices = new int[g.Count]; for (int j = 0; j < g.Count; j++) { var tv = g[j]; int newIndex = oldVertexToNewMapping[tv.Vertex]; if (newIndex == -1) { newIndex = nextIndex++; oldVertexToNewMapping[tv.Vertex] = newIndex; newPositions.Add(oldPositions[tv.RawGeometry][tv.RawVertex]); } newIndices[j] = newIndex; } ret.Add((newPositions.ToArray(), newIndices)); } return(ret); }
public static void BoolActionExecute(Component_MeshInSpace firstMeshInSpace, Component_MeshInSpace secondMeshInSpace, UndoMultiAction undo, DocumentInstance document, BoolActionEnum boolAction) { //the first operand of the union operation must be a single geometry, otherwise duplicate parts will be made. if (boolAction == BoolActionEnum.Union && 1 < firstMeshInSpace.Mesh.Value.GetComponents <Component_MeshGeometry>().Length) { MergeGeometries(firstMeshInSpace.Mesh, document, undo); } bool needUndoForNextActions = true; CommonFunctions.ConvertProceduralMeshGeometries(document, firstMeshInSpace.Mesh, undo, ref needUndoForNextActions); List <(Vector3F[] positions, int[] indices)> data1List = GetData(firstMeshInSpace); (Vector3F[] positions, int[] indices)data2 = MergeData(GetData(secondMeshInSpace)); //convert the second mesh in space, to the transform of first mesh in space var matrix = firstMeshInSpace.Transform.Value.ToMatrix4().GetInverse() * secondMeshInSpace.Transform.Value.ToMatrix4(); Net3dBool.Vector3[] vertices2 = new Net3dBool.Vector3[data2.positions.Length]; for (int i = 0; i < data2.positions.Length; i++) { vertices2[i] = ToNet3DBoolVector3((matrix * data2.positions[i]).ToVector3F()); } var operand2 = new Net3dBool.Solid(vertices2, data2.indices); var geometries = firstMeshInSpace.Mesh.Value.GetComponents <Component_MeshGeometry>(); var resultGeometries = new List <(Vector3F[] positions, int[] indices, MeshData.MeshGeometryFormat format)>(); var geometriesToDelete = new List <Component_MeshGeometry>(); for (int geomIndex = 0; geomIndex < data1List.Count; geomIndex++) { var data1 = data1List[geomIndex]; Net3dBool.Vector3[] vertices1 = data1.positions.Select(ToNet3DBoolVector3).ToArray(); var modeller = new Net3dBool.BooleanModeller(new Net3dBool.Solid(vertices1, data1.indices), operand2); //Большую часть времени на вычисления занимает эта сторка Net3dBool.Solid result = null; switch (boolAction) { case BoolActionEnum.Union: result = modeller.GetUnion(); break; case BoolActionEnum.Intersect: result = modeller.GetIntersection(); break; case BoolActionEnum.Subtract: result = modeller.GetDifference(); break; default: return; } var newVertices = result.getVertices().Select(ToVector3F).ToArray(); if (0 < newVertices.Length) { resultGeometries.Add((newVertices, result.getIndices(), new MeshData.MeshGeometryFormat(geometries[geomIndex].VertexStructure))); } else { geometriesToDelete.Add(geometries[geomIndex]); } } foreach (var g in resultGeometries) { if (!CheckValid(g.positions, g.indices)) { throw new Exception(); } } //delete empty mesh geometry // if (0 < geometriesToDelete.Count) { undo?.AddAction(new UndoActionComponentCreateDelete(document, geometriesToDelete.ToArray(), create: false)); } var meshData = MeshData.BuildFromRaw(resultGeometries); meshData?.Save(firstMeshInSpace.Mesh.Value, needUndoForNextActions ? undo : null, null); //??? No selection? firstMeshInSpace.Mesh.Value?.RebuildStructure(); }
//??? Для объединенного MeshInSpace transform выбирать как у первого MeshInSpace или лучше считать средний transform? //??? MeshInSpace.ReplaceMeterial,ReplaceMeterialSelectively ? отбрасывать или выбирать первый. Как с geometry? static Component_MeshInSpace MergeMeshInSpaces(Component_MeshInSpace[] meshInSpaces, DocumentInstance document, UndoMultiAction undo) { if (meshInSpaces.Length < 2) { return(null); } var newTransform = meshInSpaces[0].Transform.Value; var newMatrixInverse = newTransform.ToMatrix4().GetInverse(); var newRotationInverse = newTransform.Rotation.GetInverse(); Component_Mesh.StructureClass newStructure = null; var newGeometries = new List <Component_MeshGeometry>(); for (int i = 0; i < meshInSpaces.Length; i++) { var m = meshInSpaces[i].Mesh.Value; if (m == null) { continue; } var oldTransform = meshInSpaces[i].Transform.Value; var transformMatrix = newMatrixInverse * oldTransform.ToMatrix4(); var rotation = newRotationInverse * oldTransform.Rotation; var geometries = m.GetComponents <Component_MeshGeometry>(); newStructure = Component_Mesh.StructureClass.Concat(newStructure, m.ExtractStructure().Structure, newGeometries.Count); foreach (var g in geometries) { if (g is Component_MeshGeometry_Procedural meshGeometryProcedural) { VertexElement[] vertexStructure = null; byte[] vertices = null; int[] indices = null; Component_Material material = null; Component_Mesh.StructureClass structure = null; meshGeometryProcedural.GetProceduralGeneratedData(ref vertexStructure, ref vertices, ref indices, ref material, ref structure); var newMeshGeometry = new Component_MeshGeometry(); newMeshGeometry.Name = meshGeometryProcedural.Name; newMeshGeometry.VertexStructure = vertexStructure; newMeshGeometry.Vertices = vertices; newMeshGeometry.Indices = indices; newMeshGeometry.Material = meshGeometryProcedural.Material; //newMeshGeometry.Material = material; TransformVertices(newMeshGeometry.Vertices.Value, new MeshData.MeshGeometryFormat(newMeshGeometry.VertexStructure), transformMatrix, rotation); newGeometries.Add(newMeshGeometry); } else { //??? Проверять CloneSupport? var newMeshGeometry = (Component_MeshGeometry)g.Clone(); if (newMeshGeometry.Vertices.Value != null) { newMeshGeometry.Vertices = (byte[])newMeshGeometry.Vertices.Value.Clone(); TransformVertices(newMeshGeometry.Vertices.Value, new MeshData.MeshGeometryFormat(newMeshGeometry.VertexStructure), transformMatrix, rotation); } newGeometries.Add(newMeshGeometry); } } } //changes var parent = meshInSpaces[0].Parent; undo.AddAction(new UndoActionComponentCreateDelete(document, meshInSpaces, create: false)); Component_MeshInSpace newMeshInSpace = parent.CreateComponent <Component_MeshInSpace>(); bool wasEnabled = newMeshInSpace.Enabled; try { newMeshInSpace.Enabled = false; newMeshInSpace.Name = CommonFunctions.GetUniqueFriendlyName(newMeshInSpace); newMeshInSpace.Transform = newTransform; var newMesh = newMeshInSpace.CreateComponent <Component_Mesh>(); newMesh.Name = CommonFunctions.GetUniqueFriendlyName(newMesh); newMesh.Structure = newStructure; newMeshInSpace.Mesh = ReferenceUtility.MakeReference <Component_Mesh>(null, ReferenceUtility.CalculateRootReference(newMesh)); foreach (var g in newGeometries) { newMesh.AddComponent(g); CommonFunctions.EnsureNameIsUnique(g); } } finally { newMeshInSpace.Enabled = wasEnabled; } undo.AddAction(new UndoActionComponentCreateDelete(document, new[] { newMeshInSpace }, create: true)); return(newMeshInSpace); }
private void ParentMeshInSpace_GetRenderSceneDataAddToFrameData(Component_MeshInSpace sender, ViewportRenderingContext context, GetRenderSceneDataMode mode, ref Component_RenderingPipeline.RenderSceneData.MeshItem item) { if (!CalculateOnCPU) { Component_Skeleton skeleton = ReplaceSkeleton; if (skeleton == null) { skeleton = ParentMeshInSpace?.Mesh.Value?.Skeleton; } if (skeleton != null) { var animation = PlayAnimation.Value; if (animation != null) { UpdateAnimationTime(); //settings.animationStates = new AnimationStateItem[ 1 ]; //settings.animationStates[ 0 ] = new AnimationStateItem( animation, currentLocalTime, 1 ); var skeletonAnimation = animation as Component_SkeletonAnimation; var track = skeletonAnimation?.Track.Value; if (track != null || CalculateBoneTransforms != null) { Update(skeleton, track, currentAnimationTime); if (transformMatrixRelativeToSkin != null && transformMatrixRelativeToSkin.Length != 0) { item.AnimationData = new Component_RenderingPipeline.RenderSceneData.MeshItem.AnimationDataClass(); bool dualQuaternion = false; // GetSkinningMode( skeleton ) == Component_Skeleton.SkinningModeEnum.DualQuaternion; if (dualQuaternion) { item.AnimationData.Mode = 2; } else { item.AnimationData.Mode = 1; } //create dynamic texture var size = new Vector2I(4, MathEx.NextPowerOfTwo(transformMatrixRelativeToSkin.Length)); var bonesTexture = context.DynamicTexture_Alloc(ViewportRenderingContext.DynamicTextureType.DynamicTexture, Component_Image.TypeEnum._2D, size, PixelFormat.Float32RGBA, 0, false); //try get array from texture to minimize memory allocations var surfaces = bonesTexture.Result.GetData(); if (surfaces == null) { surfaces = new GpuTexture.SurfaceData[] { new GpuTexture.SurfaceData(0, 0, new byte[size.X * size.Y * 16]) } } ; var data = surfaces[0].data; //copy data to the texture unsafe { fixed(byte *pData2 = data) { Matrix4F *pData = (Matrix4F *)pData2; for (int n = 0; n < transformMatrixRelativeToSkin.Length; n++) { pData[n] = transformMatrixRelativeToSkin[n]; } } } bonesTexture.Result.SetData(new GpuTexture.SurfaceData[] { new GpuTexture.SurfaceData(0, 0, data) }); item.AnimationData.BonesTexture = bonesTexture; } } } } } } void RenderSkeleton(Viewport viewport) { // ParentMeshInSpace.Transform is automaticaly applyed to ParentMeshInSpace.Mesh, skeleton must be transformed manually var transformMatrix = ParentMeshInSpace?.Transform.Value?.ToMatrix4() ?? Matrix4.Identity; var skeletonArrows = GetCurrentAnimatedSkeletonArrows(); if (skeletonArrows != null) { var color = new ColorValue(0, 0.5, 1, 0.7); //ToDo : Вынести в другое место. viewport.Simple3DRenderer.SetColor(color, color * ProjectSettings.Get.HiddenByOtherObjectsColorMultiplier); foreach (var arrow in skeletonArrows) { viewport.Simple3DRenderer.AddArrow(transformMatrix * arrow.Start, transformMatrix * arrow.End); } } } bool CheckNeedModifiableMesh() { if (CalculateOnCPU) { if (ReplaceSkeleton.ReferenceSpecified) { return(true); } var mesh = ParentMeshInSpace?.Mesh.Value; if (mesh != null && mesh.Skeleton.ReferenceSpecified) { return(true); } if (PlayAnimation.ReferenceSpecified) { return(true); } } return(false); } void UpdateModifiableMesh(ViewportRenderingContext context) { var originalMesh = ParentMeshInSpace.Mesh.Value; var modifiableMesh = ParentMeshInSpace.ModifiableMesh; Component_Skeleton skeleton = ReplaceSkeleton; if (skeleton == null) { skeleton = originalMesh.Skeleton; } if (skeleton != null) { //!!!!сериализовывать var animation = PlayAnimation.Value; if (animation != null) { UpdateAnimationTime(); //settings.animationStates = new AnimationStateItem[ 1 ]; //settings.animationStates[ 0 ] = new AnimationStateItem( animation, currentLocalTime, 1 ); var skeletonAnimation = animation as Component_SkeletonAnimation; var track = skeletonAnimation?.Track.Value; if (track != null || CalculateBoneTransforms != null) { Update(skeleton, track, currentAnimationTime); CalculateCPU(skeleton, originalMesh, modifiableMesh); } } if (needResetToOriginalMesh) { needResetToOriginalMesh = false; if (CalculateOnCPU) { ResetToOriginalMesh(originalMesh, modifiableMesh); } } } } ///////////////////////////////////////// void ResetTime(bool needResetToOriginalMesh) { if (needResetToOriginalMesh) { this.needResetToOriginalMesh = true; } currentEngineTime = EngineApp.EngineTime; currentAnimationTime = (PlayAnimation.Value as Component_SkeletonAnimation)?.TrackStartTime ?? 0; } void UpdateAnimationTime() { double t = EngineApp.EngineTime; double increment = t - currentEngineTime; currentEngineTime = t; currentAnimationTime += increment * Speed; var animation = PlayAnimation.Value as Component_SkeletonAnimation; if (animation != null) { double animationStartTime = animation.TrackStartTime; double animationLength = animation.Length; if (animationLength > 0) { if (AutoRewind) { while (currentAnimationTime > animationStartTime + animationLength) { currentAnimationTime -= animationLength; } while (currentAnimationTime < animationStartTime) { currentAnimationTime += animationLength; } } else { MathEx.Clamp(ref currentAnimationTime, animationStartTime, animationStartTime + animationLength); } } else { currentAnimationTime = animationStartTime; } } else { currentAnimationTime = 0; } }