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 UpdateDisplayObject() { if (Scene == null) { return; } var import = ObjectOfPreview as Component_Import3D; if (import != null) { if (displayObject == null || displayObjectVersion != import.VersionForPreviewDisplay || materialPreviewMeshUsed != ProjectSettings.Get.MaterialPreviewMesh.Value) { Scene.Enabled = false; if (displayObject != null) { displayObject.RemoveFromParent(false); displayObject.Dispose(); } displayObject = import.CreateForPreviewDisplay(Scene, out onlyOneMaterial, out _); displayObjectVersion = import.VersionForPreviewDisplay; Scene.Enabled = true; materialPreviewMeshUsed = ProjectSettings.Get.MaterialPreviewMesh.Value; } } }
static bool CheckValidMeshWithMessageBox(Component_Mesh mesh) { if (!CommonFunctions.CheckValidMesh(mesh, out string error)) { EditorMessageBox.ShowWarning(error); return(false); } return(true); }
///////////////////////////////////////// //Component_Skeleton.SkinningModeEnum GetSkinningMode( Component_Skeleton skeleton ) //{ // var _override = OverrideSkinningMode.Value; // if( _override != Component_Skeleton.SkinningModeEnum.Auto ) // return _override; // var selected = skeleton.SkinningMode.Value; // if( selected != Component_Skeleton.SkinningModeEnum.Auto ) // return selected; // if( !hasScale ) // return Component_Skeleton.SkinningModeEnum.DualQuaternion; // else // return Component_Skeleton.SkinningModeEnum.Linear; //} protected virtual void CalculateCPU(Component_Skeleton skeleton, Component_Mesh originalMesh, Component_Mesh modifiableMesh) { bool dualQuaternion = false; // GetSkinningMode( skeleton ) == Component_Skeleton.SkinningModeEnum.DualQuaternion; for (int nOper = 0; nOper < modifiableMesh.Result.MeshData.RenderOperations.Count; nOper++) { var sourceOper = originalMesh.Result.MeshData.RenderOperations[nOper]; var destOper = modifiableMesh.Result.MeshData.RenderOperations[nOper]; var position = new ChannelFloat3(sourceOper, destOper, VertexElementSemantic.Position); if (position.Exists) { var normal = new ChannelFloat3(sourceOper, destOper, VertexElementSemantic.Normal); var tangent = new ChannelFloat4(sourceOper, destOper, VertexElementSemantic.Tangent); var blendIndices = new SourceChannel <Vector4I>(sourceOper, VertexElementSemantic.BlendIndices, VertexElementType.Integer4); var blendWeights = new SourceChannel <Vector4F>(sourceOper, VertexElementSemantic.BlendWeights, VertexElementType.Float4); if (!blendIndices.Exists || !blendWeights.Exists) { continue; } if (normal.Exists) { if (tangent.Exists) { TransformVertices( dualQuaternion, position.SourceData, normal.SourceData, tangent.SourceData, blendIndices.SourceData, blendWeights.SourceData, position.DestData, normal.DestData, tangent.DestData ); } else { TransformVertices( dualQuaternion, position.SourceData, normal.SourceData, blendIndices.SourceData, blendWeights.SourceData, position.DestData, normal.DestData ); } } else { TransformVertices( dualQuaternion, position.SourceData, blendIndices.SourceData, blendWeights.SourceData, position.DestData ); } position.WriteChannel(); normal.WriteChannel(); tangent.WriteChannel(); } } }
protected override void OnDisabled() { mesh?.Dispose(); mesh = null; //CreatedCubemapDispose(); base.OnDisabled(); }
protected override void OnEnabled() { base.OnEnabled(); mesh = ComponentUtility.CreateComponent <Component_Mesh>(null, true, false); mesh.CreateComponent <Component_MeshGeometry_Box>(); mesh.Enabled = true; processedCubemapNeedUpdate = true; }
///////////////////////////////////////// //detect what LOD is need. can be -1 when skip by visibility distance static int DetectDemandedLOD(ViewportRenderingContext context, Component_Mesh mesh, double objectVisibilityDistance, ref Vector3 objectPosition) { int demandLOD; var cameraSettings = context.Owner.CameraSettings; double maxDistance; if (mesh != null) { maxDistance = Math.Min(objectVisibilityDistance, mesh.VisibilityDistance); } else { maxDistance = objectVisibilityDistance; } if (maxDistance < cameraSettings.FarClipDistance && (cameraSettings.Position - objectPosition).LengthSquared() > maxDistance * maxDistance) { demandLOD = -1; } else { demandLOD = 0; if (mesh != null) { var lods = mesh.Result.MeshData.LODs; if (lods != null) { //!!!!что про дребежжание когда быстро туда сюда переключаться нужно? var distanceSquared = (float)(objectPosition - cameraSettings.Position).LengthSquared() * context.renderingPipeline.LODScale.Value; var range = context.renderingPipeline.LODRange.Value.ToVector2I() - new Vector2I(1, 1); for (int n = Math.Min(lods.Length - 1, range.Y); n >= 0; n--) { ref var lod = ref lods[n]; var lodDistanceSquared = lod.DistanceSquared; if (distanceSquared > lodDistanceSquared || n <= range.X) { var lodMeshData = lod.Mesh?.Result?.MeshData; if (lodMeshData != null) { demandLOD = n + 1; break; } } } } } }
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()); }
public static Component_Mesh GetBillboardMesh() { if (billboardMesh == null || billboardMesh.Disposed) { billboardMesh = null; } if (billboardMesh == null) { var mesh = ComponentUtility.CreateComponent <Component_Mesh>(null, true, false); var geometry = mesh.CreateComponent <Component_MeshGeometry_Plane>(); geometry.Axis = 1; mesh.Billboard = true; mesh.Enabled = true; billboardMesh = mesh; } return(billboardMesh); }
public void Generate(Component_Mesh mesh, string writeRealFileName) { this.mesh = mesh; Init(); //create scene var scene = CreateScene(false); if (mesh != null) { var objInSpace = scene.CreateComponent <Component_MeshInSpace>(); objInSpace.Mesh = mesh; } scene.Enabled = true; //generate an image { viewport.Update(true); //clear temp data viewport.RenderingContext.MultiRenderTarget_DestroyAll(); viewport.RenderingContext.DynamicTexture_DestroyAll(); texture.Result.GetRealObject(true).BlitTo(viewport.RenderingContext.CurrentViewNumber, textureRead.Result.GetRealObject(true), 0, 0); var demandedFrame = textureRead.Result.GetRealObject(true).Read(imageData, 0); while (RenderingSystem.CallBgfxFrame() < demandedFrame) { } } //write png if (!ImageUtility.Save(writeRealFileName, imageData, imageSizeRender, 1, imageFormat, 1, 0, out var error)) { throw new Exception(error); } DetachAndOrDestroyScene(); Shutdown(); }
// public Item(RectangleF uv) { UV = uv; EngineTime = Time.Current; var vertexStructure = StandardVertex.MakeStructure(StandardVertex.Components.StaticOneTexCoord, true, out int vertexSize); var positions = new Vector3F[] { new Vector3F(-0.5f, -0.5f, 0), new Vector3F(0.5f, -0.5f, 0), new Vector3F(0.5f, 0.5f, 0), new Vector3F(-0.5f, 0.5f, 0) }; var texCoords = new Vector2F[] { uv.LeftTop, uv.RightTop, uv.RightBottom, uv.LeftBottom }; var vertices = new byte[vertexSize * positions.Length]; unsafe { fixed(byte *pVertices = vertices) { StandardVertex.StaticOneTexCoord *pVertex = (StandardVertex.StaticOneTexCoord *)pVertices; for (int n = 0; n < positions.Length; n++) { pVertex->Position = positions[n]; pVertex->Normal = new Vector3F(0, 0, 1); pVertex->Tangent = new Vector4F(1, 0, 0, -1); pVertex->Color = new ColorValue(1, 1, 1, 1); pVertex->TexCoord0 = texCoords[n]; pVertex++; } } } var mesh = ComponentUtility.CreateComponent <Component_Mesh>(null, true, false); var geometry = mesh.CreateComponent <Component_MeshGeometry>(); geometry.VertexStructure = vertexStructure; geometry.Vertices = vertices; geometry.Indices = new int[] { 0, 1, 2, 2, 3, 0 }; mesh.Enabled = true; Mesh = mesh; }
static void ResetToOriginalMesh(Component_Mesh originalMesh, Component_Mesh modifiableMesh) { for (int nOper = 0; nOper < modifiableMesh.Result.MeshData.RenderOperations.Count; nOper++) { var sourceOper = originalMesh.Result.MeshData.RenderOperations[nOper]; var destOper = modifiableMesh.Result.MeshData.RenderOperations[nOper]; var channelsSemantic = new[] { VertexElementSemantic.Position, VertexElementSemantic.Normal, VertexElementSemantic.Tangent, VertexElementSemantic.Bitangent }; foreach (var semantic in channelsSemantic) { var channel = new ChannelFloat3(sourceOper, destOper, semantic); if (channel.Exists) { for (int n = 0; n < channel.DestData.Length; n++) { channel.DestData[n] = channel.SourceData[n]; } channel.WriteChannel(); } } } }
void UpdatePreviewMesh() { var mesh = ProjectSettings.Get.MaterialPreviewMesh.Value; previewMeshUsed = mesh; if (mesh == null) { if (defaultMesh == null) { //sphere if null defaultMesh = Scene.CreateComponent <Component_Mesh>(enabled: false); var sphere = defaultMesh.CreateComponent <Component_MeshGeometry_Sphere>(); sphere.SegmentsHorizontal = 64; sphere.SegmentsVertical = 64; defaultMesh.Enabled = true; } mesh = defaultMesh; } var meshInSpace = (Component_MeshInSpace)Scene.GetComponent("Mesh In Space"); meshInSpace.Mesh = mesh; }
unsafe static void MeshGetIsBillboard(ImportContext context, Component_Mesh destinationMesh) { bool isBillboard = false; var geometries = destinationMesh.GetComponents <Component_MeshGeometry>(); if (geometries.Length == 1) { var geometry = geometries[0]; try { var vertexStructure = geometry.VertexStructure.Value; var vertices = geometry.Vertices.Value; var indices = geometry.Indices.Value; if (vertexStructure?.Length != 0 && vertices?.Length != 0 && indices?.Length != 0) { vertexStructure.GetInfo(out var vertexSize, out _); int vertexCount = vertices.Length / vertexSize; if (indices.Length >= 3) { if (vertexStructure.GetElementBySemantic(VertexElementSemantic.Position, out var positionElement)) { if (positionElement.Type == VertexElementType.Float3 && positionElement.Source == 0) { int offset = positionElement.Offset; var p = new Vector3[vertexCount]; for (int nVertex = 0; nVertex < vertexCount; nVertex++) { fixed(byte *pVertices = vertices) p[nVertex] = *(Vector3F *)(pVertices + nVertex * vertexSize + offset); } var normal1 = Plane.FromPoints(p[indices[0]], p[indices[1]], p[indices[2]]).Normal; if (Math.Abs(normal1.X) > 0.95f || Math.Abs(normal1.Y) > 0.95f) { bool canBeBillboard = true; for (int nTriangle = 0; nTriangle < indices.Length / 3; nTriangle++) { var index0 = indices[nTriangle * 3 + 0]; var index1 = indices[nTriangle * 3 + 1]; var index2 = indices[nTriangle * 3 + 2]; var normal2 = Plane.FromPoints(p[index0], p[index1], p[index2]).Normal; if (!normal1.Equals(normal2, 0.01)) { canBeBillboard = false; break; } } if (canBeBillboard) { isBillboard = true; } } } } } } } catch (Exception e) { Log.Warning(e.Message); } } if (isBillboard) { destinationMesh.Billboard = true; foreach (var geometry in geometries) { if (context.materialByIndex.TryGetValue(-1, out var material)) { geometry.Material = ReferenceUtility.MakeRootReference(material); } } } }
//Component_MeshInSpace contains only one Component_Mesh. static void MergeGeometries(Component_Mesh mesh, DocumentInstance document, UndoMultiAction undo) { Component_MeshGeometry[] geometries = mesh.GetComponents <Component_MeshGeometry>(); if (geometries == null || geometries.Length < 2) { return; } Reference <Component_Material> material = geometries[0].Material; //for( int i = 1; i < geometries.Length; i++ ) //{ // if( !( material.Value == null && geometries[ i ].Material.Value == null || material.Equals( geometries[ i ].Material ) ) ) // { // //??? Если разные Material какой вариант лучше: 1) Брать из первого geometry с вопросом в MessageBox; 2) Disable в меню для Action. 3) Соединять те, которые с одинаковым материалом. // if( EditorMessageBox.ShowQuestion( "Mesh geometries have different materials. Merge them using a material from the first geometry?", MessageBoxButtons.OKCancel ) == DialogResult.Cancel ) // { // return; // } // } //} var extracted = mesh.ExtractStructure(); var newIndices = new List <int>(); var newVertices = new List <byte>(); var newVertexStructure = extracted.MeshGeometries[0].VertexStructure; var newVertexFormat = new MeshData.MeshGeometryFormat(newVertexStructure); for (int geomIndex = 0; geomIndex < extracted.MeshGeometries.Length; geomIndex++) { var g = extracted.MeshGeometries[geomIndex]; if (g.Vertices == null || g.Indices == null) { continue; } int indexOffset = newVertices.Count / newVertexFormat.vertexSize; for (int i = 0; i < g.Indices.Length; i++) { newIndices.Add(g.Indices[i] + indexOffset); } if (!CommonFunctions.IsSameVertexStructure(newVertexStructure, g.VertexStructure)) { g.Vertices = MeshData.ConvertToFormat(new MeshData.MeshGeometryFormat(g.VertexStructure), g.Vertices, newVertexFormat); } newVertices.AddRange(g.Vertices); foreach (var face in extracted.Structure.Faces) { for (int i = 0; i < face.Triangles.Length; i++) { if (face.Triangles[i].RawGeometry == geomIndex) { face.Triangles[i].RawGeometry = 0; face.Triangles[i].RawVertex += indexOffset; } } } } // changes in the mesh if (undo != null) { //add structure update to undo var property = (Metadata.Property)mesh.MetadataGetMemberBySignature("property:" + nameof(Component_Mesh.Structure)); undo.AddAction(new UndoActionPropertiesChange(new UndoActionPropertiesChange.Item(mesh, property, mesh.Structure?.Clone()))); } bool meshWasEnabled = mesh.Enabled; mesh.Enabled = false; try { var newGeometry = mesh.CreateComponent <Component_MeshGeometry>(); newGeometry.Material = material; newGeometry.Vertices = newVertices.ToArray(); newGeometry.Indices = newIndices.ToArray(); newGeometry.VertexStructure = newVertexStructure; //add created geometry to undo undo?.AddAction(new UndoActionComponentCreateDelete(document, new Component[] { newGeometry }, create: true)); mesh.Structure = extracted.Structure; //delete old mesh geometry undo?.AddAction(new UndoActionComponentCreateDelete(document, geometries, create: false)); newGeometry.Name = CommonFunctions.GetUniqueFriendlyName(newGeometry); } finally { mesh.Enabled = meshWasEnabled; } }
public unsafe static void GetDemandedLODs(ViewportRenderingContext context, Component_Mesh mesh, float cameraDistanceMinSquared, float cameraDistanceMaxSquared, out LodState lodState) { //var cameraDistanceMinSquared2 = cameraDistanceMinSquared; //var cameraDistanceMaxSquared2 = cameraDistanceMaxSquared; ////!!!!fix for shadows. в случае простых билбордов тень рисуется дальше объекта другого лода, резко пропадает //cameraDistanceRangeSquared2.Maximum *= 1.1f; lodState = new LodState(); var lods = mesh.Result.MeshData.LODs; if (lods != null) { RangeF GetLodRange(int lodIndex) { if (lodIndex == 0) { return(new RangeF(0, lods[0].Distance)); } else { var arrayIndex = lodIndex - 1; var lod = lods[arrayIndex]; float far; if (arrayIndex + 1 < lods.Length) { far = lods[arrayIndex + 1].Distance; } else { far = 1000000.0f; } return(new RangeF(lod.Distance, far)); } } var lodCount = lods.Length + 1; var pipeline = context.renderingPipeline; var contextLodRange = pipeline.LODRange.Value; var contextLodScale = (float)pipeline.LODScale.Value; var lodStart = contextLodRange.Minimum; var lodEnd = Math.Min(lodCount - 1, contextLodRange.Maximum); if (lodStart > lodEnd) { lodStart = lodEnd; } for (int lodIndex = lodStart; lodIndex <= lodEnd; lodIndex++) { var lodRange = GetLodRange(lodIndex) * contextLodScale; if (lodIndex == lodStart) { lodRange.Minimum = 0; } if (lodIndex == lodEnd) { lodRange.Maximum = 1000000; } var min = lodRange.Minimum * 0.9f; var minSquared = min * min; var max = lodRange.Maximum; var maxSquared = max * max; //early exit if (minSquared > cameraDistanceMaxSquared) { break; } if (cameraDistanceMaxSquared >= minSquared && cameraDistanceMinSquared < maxSquared) { lodState.Add(lodIndex, lodRange); } } if (lodState.Count == 0) { lodState.Add(lodEnd, new RangeF(0, 1000000)); } lodState.FixMinMax(); } else { lodState.Add(0, new RangeF(0, 1000000)); } }
public static bool ExportToFBX(Component_Mesh sourceMesh, string realFileName, out string error) { //!!!!как для Vegetation. оверрайдить в Component_Mesh? //get mesh data var operations = new List <Component_RenderingPipeline.RenderSceneData.MeshDataRenderOperation>(); foreach (var geometry in sourceMesh.GetComponents <Component_MeshGeometry>()) { if (geometry.Enabled) { geometry.CompileDataOfThisObject(out var operation); if (operation != null) { operations.Add(operation); } } } //foreach( var geometry in mesh.Result.MeshData.RenderOperations ) //{ //} FbxManager manager = null; FbxIOSettings setting = null; FbxExporter exporter = null; FbxScene scene = null; try { //init FBX manager manager = FbxManager.Create(); setting = FbxIOSettings.Create(manager, "IOSRoot"); manager.SetIOSettings(setting); scene = FbxScene.Create(manager, "scene"); scene.GetGlobalSettings().SetAxisSystem(new FbxAxisSystem(FbxAxisSystem.EPreDefinedAxisSystem.eMax)); scene.GetGlobalSettings().SetSystemUnit(new FbxSystemUnit(100)); //init FBX scene for (int nOper = 0; nOper < operations.Count; nOper++) { var oper = operations[nOper]; //get data Vector3F[] positions = null; Vector3F[] normals = null; var texCoords = new List <Vector2F[]>(); ColorValue[] colors = null; Vector3F[] tangents = null; Vector3F[] binormals = null; //Position { if (oper.VertexStructure.GetElementBySemantic(VertexElementSemantic.Position, out VertexElement element) && element.Type == VertexElementType.Float3) { var buffer = oper.VertexBuffers[element.Source]; positions = buffer.ExtractChannel <Vector3F>(element.Offset); } } //Normal { if (oper.VertexStructure.GetElementBySemantic(VertexElementSemantic.Normal, out VertexElement element) && element.Type == VertexElementType.Float3) { var buffer = oper.VertexBuffers[element.Source]; normals = buffer.ExtractChannel <Vector3F>(element.Offset); } } //TexCoord for (var channel = VertexElementSemantic.TextureCoordinate0; channel <= VertexElementSemantic.TextureCoordinate3; channel++) { if (oper.VertexStructure.GetElementBySemantic(channel, out VertexElement element) && element.Type == VertexElementType.Float2) { var buffer = oper.VertexBuffers[element.Source]; texCoords.Add(buffer.ExtractChannel <Vector2F>(element.Offset)); } } //Color { if (oper.VertexStructure.GetElementBySemantic(VertexElementSemantic.Color0, out VertexElement element)) { if (element.Type == VertexElementType.Float4) { var buffer = oper.VertexBuffers[element.Source]; var values = buffer.ExtractChannel <Vector4F>(element.Offset); colors = new ColorValue[positions.Length]; int destIndex = 0; foreach (var p in values) { colors[destIndex++] = p.ToColorValue(); } } else if (element.Type == VertexElementType.ColorABGR) { //!!!!check var buffer = oper.VertexBuffers[element.Source]; var values = buffer.ExtractChannel <uint>(element.Offset); colors = new ColorValue[positions.Length]; int destIndex = 0; foreach (var p in values) { colors[destIndex++] = new ColorValue(ColorByte.FromABGR(p)); } } else if (element.Type == VertexElementType.ColorARGB) { //!!!!check var buffer = oper.VertexBuffers[element.Source]; var values = buffer.ExtractChannel <uint>(element.Offset); colors = new ColorValue[positions.Length]; int destIndex = 0; foreach (var p in values) { colors[destIndex++] = new ColorValue(ColorByte.FromARGB(p)); } } } } //Tangent, Binormal if (normals != null) { if (oper.VertexStructure.GetElementBySemantic(VertexElementSemantic.Tangent, out VertexElement element) && element.Type == VertexElementType.Float4) { var buffer = oper.VertexBuffers[element.Source]; var tangents4 = buffer.ExtractChannel <Vector4F>(element.Offset); tangents = new Vector3F[tangents4.Length]; binormals = new Vector3F[tangents4.Length]; int destIndex = 0; foreach (var p in tangents4) { tangents[destIndex] = p.ToVector3F(); binormals[destIndex] = Vector3F.Cross(p.ToVector3F(), normals[destIndex]) * p.W; destIndex++; } } } //indices int[] indices = null; if (oper.IndexBuffer != null) { indices = oper.IndexBuffer.Indices; } //create geometry var geometryName = "Geometry " + nOper.ToString(); var mesh = FbxMesh.Create(scene, geometryName); mesh.InitControlPoints(positions.Length); FbxLayerElementNormal elementNormals = null; if (normals != null) { elementNormals = mesh.CreateElementNormal(); elementNormals.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); elementNormals.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); } FbxLayerElementVertexColor elementColors = null; if (colors != null) { elementColors = mesh.CreateElementVertexColor(); elementColors.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); elementColors.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); } FbxLayerElementTangent elementTangents = null; if (tangents != null) { elementTangents = mesh.CreateElementTangent(); elementTangents.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); elementTangents.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); } FbxLayerElementBinormal elementBinormals = null; if (binormals != null) { elementBinormals = mesh.CreateElementBinormal(); elementBinormals.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); elementBinormals.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); } var uvElements = new List <FbxLayerElementUV>(); for (int uvIndex = 0; uvIndex < texCoords.Count; uvIndex++) { var pUVElement = mesh.CreateElementUV("texcoord" + uvIndex.ToString()); pUVElement.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint); pUVElement.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect); uvElements.Add(pUVElement); } for (int n = 0; n < positions.Length; n++) { mesh.SetControlPointAt(ToFbxVector4(positions[n]), n); if (normals != null) { elementNormals.GetDirectArray().Add(ToFbxVector4(normals[n])); } for (int uvIndex = 0; uvIndex < texCoords.Count; uvIndex++) { var texCoord = texCoords[uvIndex][n]; texCoord.Y = 1.0f - texCoord.Y; uvElements[uvIndex].GetDirectArray().Add(ToFbxVector2(texCoord)); } if (colors != null) { elementColors.GetDirectArray().Add(ToFbxColor(colors[n])); } if (tangents != null) { elementTangents.GetDirectArray().Add(ToFbxVector4(tangents[n])); } if (binormals != null) { elementBinormals.GetDirectArray().Add(ToFbxVector4(binormals[n])); } } if (normals != null) { mesh.GetLayer(0).SetNormals(elementNormals); } if (colors != null) { mesh.GetLayer(0).SetVertexColors(elementColors); } if (tangents != null) { mesh.GetLayer(0).SetTangents(elementTangents); } if (binormals != null) { mesh.GetLayer(0).SetBinormals(elementBinormals); } int polygonCount = indices.Length / 3; for (int i = 0; i < polygonCount; i++) { mesh.BeginPolygon(-1, -1, -1, false); for (int j = 0; j < 3; j++) { int currentIndex = i * 3 + j; int vertexIndex = indices[currentIndex]; mesh.AddPolygon(vertexIndex); } mesh.EndPolygon(); } var node = FbxNode.Create(scene, geometryName); node.SetNodeAttribute(mesh); scene.GetRootNode().AddChild(mesh.GetNode()); } //save exporter = FbxExporter.Create(manager, ""); if (!exporter.Initialize(realFileName, -1, manager.GetIOSettings())) { error = "Can't initialize FBX exporter."; return(false); } if (!exporter.Export(scene)) { error = "Export to FBX failed."; return(false); } } finally { try { scene?.Destroy(); } catch { } try { exporter?.Destroy(); } catch { } try { setting?.Destroy(); } catch { } try { manager?.Destroy(); } catch { } } foreach (var op in operations) { op.DisposeBuffers(); } error = ""; return(true); }
static void ConvertProceduralMeshGeometries(DocumentInstance document, Component_Mesh mesh, UndoMultiAction undoMultiAction, ref bool needUndoForNextActions) { //needUndoForNextActions = true; var meshGeometries = mesh.GetComponents <Component_MeshGeometry>(); if (meshGeometries.Any(g => g is Component_MeshGeometry_Procedural)) { //!!!!? bool hasOrdinary = meshGeometries.Any(g => !(g is Component_MeshGeometry_Procedural)); if (!hasOrdinary) { needUndoForNextActions = false; //??? Если были и обычные geometry и procedural? Как правильно needUndoForNextActions? Пока так: undo не нужен только если все procedural } //!!!!right? !needUndoForNextActions if (undoMultiAction != null && !needUndoForNextActions) { //add structure update to undo var property = (Metadata.Property)mesh.MetadataGetMemberBySignature("property:" + nameof(Component_Mesh.Structure)); undoMultiAction.AddAction(new UndoActionPropertiesChange(new UndoActionPropertiesChange.Item(mesh, property, mesh.Structure?.Clone()))); } for (int i = 0; i < meshGeometries.Length; i++) { var meshGeometry = meshGeometries[i]; //convert to usual Component_MeshGeometry if (meshGeometry 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 insertIndex = meshGeometryProcedural.Parent.Components.IndexOf(meshGeometryProcedural); var meshGeometryNew = mesh.CreateComponent <Component_MeshGeometry>(insertIndex); meshGeometryNew.Name = meshGeometry.Name; meshGeometryNew.VertexStructure = vertexStructure; meshGeometryNew.Vertices = vertices; meshGeometryNew.Indices = indices; meshGeometryNew.Material = meshGeometryProcedural.Material; //concut structures. If the geometry is procedural it is not in a structure yet. mesh.Structure = Component_Mesh.StructureClass.Concat(mesh.Structure, structure, i); //delete old mesh geometry if (undoMultiAction != null) { undoMultiAction.AddAction(new UndoActionComponentCreateDelete(document, new Component[] { meshGeometry }, create: false)); } else { meshGeometry.Dispose(); } //add created geometry to undo if (undoMultiAction != null) { undoMultiAction.AddAction(new UndoActionComponentCreateDelete(document, new Component[] { meshGeometryNew }, create: true)); } } } } }