private void ConvertUnityEmptyObjectToBabylon(GameObject gameObject) { BabylonMesh babylonMesh = new BabylonMesh { name = gameObject.name, id = GetID(gameObject) }; var transform = gameObject.transform; babylonMesh.parentId = GetParentID(transform); babylonMesh.position = transform.localPosition.ToFloat(); babylonMesh.rotation = new float[3]; babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180; babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180; babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180; babylonMesh.scaling = transform.localScale.ToFloat(); babylonScene.MeshesList.Add(babylonMesh); // Animations ExportAnimations(transform, babylonMesh); if (IsRotationQuaternionAnimated(babylonMesh)) { babylonMesh.rotationQuaternion = transform.localRotation.ToFloat(); } }
public static BabylonMesh Clone(this BabylonMesh mesh, BabylonScene scene) { string gid = mesh.geometryId; if (gid == null) { // we may create the geometry into the scene gid = mesh.id; // ensure geometries object exist scene.geometries = scene.geometries ?? new BabylonGeometries(); // add new geometry object to the scene if (!scene.geometries.Contains(gid)) { scene.geometries.Add(new BabylonVertexData(gid, mesh)); } // and update the mesh to ref this geometry. mesh.geometryId = gid; mesh.ClearLocalGeometry(); } BabylonMesh newMesh = new BabylonMesh() { materialId = mesh.materialId, geometryId = mesh.geometryId, subMeshes = mesh.subMeshes }; return(newMesh); }
private static void ExportSkeletonAnimationClips(Animator animator, bool autoPlay, BabylonSkeleton skeleton, Transform[] bones, BabylonMesh babylonMesh) { AnimationClip clip = null; AnimatorController ac = animator.runtimeAnimatorController as AnimatorController; if (ac == null) { return; } var layer = ac.layers[0]; if (layer == null) { return; } AnimatorStateMachine sm = layer.stateMachine; if (sm.states.Length > 0) { // Only the first state is supported so far. var state = sm.states[0].state; clip = state.motion as AnimationClip; } if (clip == null) { return; } ExportSkeletonAnimationClipData(animator, autoPlay, skeleton, bones, babylonMesh, clip); }
private BabylonMesh ConvertUnityEmptyObjectToBabylon(GameObject gameObject, ref UnityMetaData metaData, ref List<BabylonExport.Entities.BabylonParticleSystem> particleSystems, ref List<UnityFlareSystem> lensFlares, ref string componentTags, BabylonMesh collisionMesh = null, Collider collider = null) { BabylonMesh babylonMesh = new BabylonMesh { name = gameObject.name, id = GetID(gameObject) }; metaData.type = "Game"; if (!String.IsNullOrEmpty(componentTags)) { babylonMesh.tags = componentTags; } var transform = gameObject.transform; babylonMesh.parentId = GetParentID(transform); babylonMesh.position = transform.localPosition.ToFloat(); babylonMesh.rotation = new float[3]; babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180; babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180; babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180; babylonMesh.scaling = transform.localScale.ToFloat(); babylonMesh.isVisible = false; babylonMesh.visibility = 0; babylonMesh.checkCollisions = false; // Collision mesh (No detail mesh fallback) string collisionMeshId = null; if (collider != null && collisionMesh != null) { collisionMeshId = collisionMesh.id; collisionMesh.parentId = babylonMesh.id; collisionMesh.visibility = collider.isTrigger ? 0.25f : 0.5f; collisionMesh.checkCollisions = (exportationOptions.ExportCollisions && collider.isTrigger == false); } metaData.properties["collisionMeshId"] = collisionMeshId; babylonMesh.metadata = metaData; babylonScene.MeshesList.Add(babylonMesh); // Animations ExportAnimations(transform, babylonMesh); if (IsRotationQuaternionAnimated(babylonMesh)) { babylonMesh.rotationQuaternion = transform.localRotation.ToFloat(); } // Lens Flares ParseLensFlares(gameObject, babylonMesh.id, ref lensFlares); // Particles Systems ParseParticleSystems(gameObject, babylonMesh.id, ref particleSystems); return babylonMesh; }
internal static bool MeshesShareSkin(BabylonMesh matchingSkinnedMesh, BabylonMesh babylonMesh) { // check if the skinning matrix indices are equivalent if (!babylonMesh.matricesIndices.SequenceEqual(matchingSkinnedMesh.matricesIndices)) { return(false); } // finally, compare the skinning matrix weights within a tolerance threshold. var skinDifference = babylonMesh.matricesWeights.Zip(matchingSkinnedMesh.matricesWeights, (first, second) => first - second).ToArray(); return(skinDifference.All(value => Math.Abs(value) < BabylonMesh.SkinningWeightToleranceThreshold)); }
private void ConvertUnitySkyboxToBabylon(Camera camera, float progress) { // Skybox if ((camera.clearFlags & CameraClearFlags.Skybox) == CameraClearFlags.Skybox) { if (RenderSettings.skybox != null) { if (RenderSettings.skybox.shader.name == "Skybox/Cubemap") { var cubeMap = RenderSettings.skybox.GetTexture("_Tex") as Cubemap; if (cubeMap != null) { var skytex = new BabylonTexture(); CopyTextureCube("sceneSkybox.hdr", cubeMap, skytex); skytex.coordinatesMode = 5; skytex.level = RenderSettings.reflectionIntensity; BabylonMesh skybox = new BabylonMesh(); skybox.indices = new[] { 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23 }; skybox.positions = new[] { 50.0f, -50.0f, 50.0f, -50.0f, -50.0f, 50.0f, -50.0f, 50.0f, 50.0f, 50.0f, 50.0f, 50.0f, 50.0f, 50.0f, -50.0f, -50.0f, 50.0f, -50.0f, -50.0f, -50.0f, -50.0f, 50.0f, -50.0f, -50.0f, 50.0f, 50.0f, -50.0f, 50.0f, -50.0f, -50.0f, 50.0f, -50.0f, 50.0f, 50.0f, 50.0f, 50.0f, -50.0f, 50.0f, 50.0f, -50.0f, -50.0f, 50.0f, -50.0f, -50.0f, -50.0f, -50.0f, 50.0f, -50.0f, -50.0f, 50.0f, 50.0f, -50.0f, 50.0f, -50.0f, 50.0f, 50.0f, -50.0f, 50.0f, 50.0f, 50.0f, 50.0f, -50.0f, 50.0f, 50.0f, -50.0f, -50.0f, -50.0f, -50.0f, -50.0f, -50.0f, -50.0f, 50.0f }; skybox.uvs = new[] { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f }; skybox.normals = new[] { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0,0f }; var skyboxMaterial = new BabylonPBRMaterial() { name = "sceneSkyboxMaterial", id = Guid.NewGuid().ToString(), albedo = new[] { 1.0f, 1.0f, 1.0f, 1.0f }, reflectivity = new[] { 0.0f, 0.0f, 0.0f }, microSurface = 1.0f, directIntensity = 0.0f, specularIntensity = 0.0f, environmentIntensity = 1.0f }; skyboxMaterial.backFaceCulling = false; skybox.materialId = skyboxMaterial.id; skybox.infiniteDistance = true; skyboxMaterial.reflectionTexture = skytex; babylonScene.MeshesList.Add(skybox); babylonScene.MaterialsList.Add(skyboxMaterial); babylonScene.AddTextureCube("sceneSkyboxMaterial"); } } } } }
private static void ExportSkeletonAnimation(SkinnedMeshRenderer skinnedMesh, BabylonMesh babylonMesh, BabylonSkeleton skeleton) { var animator = skinnedMesh.rootBone.gameObject.GetComponent<Animator>(); if (animator != null) { ExportSkeletonAnimationClips(animator, true, skeleton, skinnedMesh.bones, babylonMesh); } else { var parent = skinnedMesh.rootBone.parent; while (parent != null) { animator = parent.gameObject.GetComponent<Animator>(); if (animator != null) { ExportSkeletonAnimationClips(animator, true, skeleton, skinnedMesh.bones, babylonMesh); break; } parent = parent.parent; } } }
public BabylonMorphTargetManager(BabylonMesh sourceMesh) { id = NB_BABYLON_MORPH_TARGET_MANAGER++; this.sourceMesh = sourceMesh; }
private void ExportMesh(IIGameScene scene, IIGameNode meshNode, BabylonScene babylonScene) { if (meshNode.MaxNode.IsInstance()) { return; } if (meshNode.MaxNode.GetBoolProperty("babylonjs_noexport")) { return; } if (!ExportHiddenObjects && meshNode.MaxNode.IsHidden(NodeHideFlags.None, false)) { return; } var gameMesh = meshNode.IGameObject.AsGameMesh(); bool initialized = gameMesh.InitializeData; //needed, the property is in fact a method initializing the exporter that has wrongly been auto // translated into a property because it has no parameters var babylonMesh = new BabylonMesh { name = meshNode.Name, id = meshNode.MaxNode.GetGuid().ToString() }; if (meshNode.NodeParent != null) { babylonMesh.parentId = GetParentID(meshNode.NodeParent, babylonScene, scene); } // Sounds var soundName = meshNode.MaxNode.GetStringProperty("babylonjs_sound_filename", ""); if (!string.IsNullOrEmpty(soundName)) { var filename = Path.GetFileName(soundName); var meshSound = new BabylonSound { name = filename, autoplay = meshNode.MaxNode.GetBoolProperty("babylonjs_sound_autoplay", 1), loop = meshNode.MaxNode.GetBoolProperty("babylonjs_sound_loop", 1), volume = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_volume", 1.0f), playbackRate = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_playbackrate", 1.0f), connectedMeshId = babylonMesh.id, isDirectional = false, spatialSound = false, distanceModel = meshNode.MaxNode.GetStringProperty("babylonjs_sound_distancemodel", "linear"), maxDistance = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_maxdistance", 100f), rolloffFactor = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_rolloff", 1.0f), refDistance = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_refdistance", 1.0f), }; var isDirectional = meshNode.MaxNode.GetBoolProperty("babylonjs_sound_directional", 0); if (isDirectional) { meshSound.isDirectional = true; meshSound.coneInnerAngle = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_coneinnerangle", 360f); meshSound.coneOuterAngle = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_coneouterangle", 360f); meshSound.coneOuterGain = meshNode.MaxNode.GetFloatProperty("babylonjs_sound_coneoutergain", 1.0f); } babylonScene.SoundsList.Add(meshSound); try { File.Copy(soundName, Path.Combine(babylonScene.OutputPath, filename), true); } catch { } } // Misc. babylonMesh.isVisible = meshNode.MaxNode.Renderable == 1; babylonMesh.pickable = meshNode.MaxNode.GetBoolProperty("babylonjs_checkpickable"); babylonMesh.receiveShadows = meshNode.MaxNode.RcvShadows == 1; babylonMesh.showBoundingBox = meshNode.MaxNode.GetBoolProperty("babylonjs_showboundingbox"); babylonMesh.showSubMeshesBoundingBox = meshNode.MaxNode.GetBoolProperty("babylonjs_showsubmeshesboundingbox"); babylonMesh.applyFog = meshNode.MaxNode.ApplyAtmospherics == 1; babylonMesh.alphaIndex = (int)meshNode.MaxNode.GetFloatProperty("babylonjs_alphaindex", 1000); // Actions babylonMesh.actions = ExportNodeAction(meshNode); // Collisions babylonMesh.checkCollisions = meshNode.MaxNode.GetBoolProperty("babylonjs_checkcollisions"); var isSkinned = gameMesh.IsObjectSkinned; var skin = gameMesh.IGameSkin; var unskinnedMesh = gameMesh; IGMatrix skinInitPoseMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true)); List<int> boneIds = null; if (isSkinned) { bonesCount = skin.TotalSkinBoneCount; skins.Add(skin); skinnedNodes.Add(meshNode); babylonMesh.skeletonId = skins.IndexOf(skin); skin.GetInitSkinTM(skinInitPoseMatrix); boneIds = SortBones(skin); skinSortedBones[skin] = boneIds; } // Position / rotation / scaling var localTM = meshNode.GetObjectTM(0); if (meshNode.NodeParent != null) { var parentWorld = meshNode.NodeParent.GetObjectTM(0); localTM.MultiplyBy(parentWorld.Inverse); } var meshTrans = localTM.Translation; var meshRotation = localTM.Rotation; var meshScale = localTM.Scaling; var exportQuaternions = Loader.Core.RootNode.GetBoolProperty("babylonjs_exportquaternions"); babylonMesh.position = new[] { meshTrans.X, meshTrans.Y, meshTrans.Z }; if (exportQuaternions) { babylonMesh.rotationQuaternion = new[] { meshRotation.X, meshRotation.Y, meshRotation.Z, -meshRotation.W }; } else { RotationToEulerAngles(babylonMesh, meshRotation); } babylonMesh.scaling = new[] { meshScale.X, meshScale.Y, meshScale.Z }; // Mesh RaiseMessage(meshNode.Name, 1); if (unskinnedMesh.IGameType == Autodesk.Max.IGameObject.ObjectTypes.Mesh && unskinnedMesh.MaxMesh != null) { if (unskinnedMesh.NumberOfFaces < 1) { RaiseError(string.Format("Mesh {0} has no face", babylonMesh.name), 2); } if (unskinnedMesh.NumberOfVerts < 3) { RaiseError(string.Format("Mesh {0} has not enough vertices", babylonMesh.name), 2); } if (unskinnedMesh.NumberOfVerts >= 65536) { RaiseWarning(string.Format("Mesh {0} has tmore than 65536 vertices which means that it will require specific WebGL extension to be rendered. This may impact portability of your scene on low end devices.", babylonMesh.name), 2); } // Physics var impostorText = meshNode.MaxNode.GetStringProperty("babylonjs_impostor", "None"); if (impostorText != "None") { switch (impostorText) { case "Sphere": babylonMesh.physicsImpostor = 1; break; case "Box": babylonMesh.physicsImpostor = 2; break; case "Plane": babylonMesh.physicsImpostor = 3; break; default: babylonMesh.physicsImpostor = 0; break; } babylonMesh.physicsMass = meshNode.MaxNode.GetFloatProperty("babylonjs_mass"); babylonMesh.physicsFriction = meshNode.MaxNode.GetFloatProperty("babylonjs_friction", 0.2f); babylonMesh.physicsRestitution = meshNode.MaxNode.GetFloatProperty("babylonjs_restitution", 0.2f); } // Material var mtl = meshNode.NodeMaterial; var multiMatsCount = 1; if (mtl != null) { babylonMesh.materialId = mtl.MaxMaterial.GetGuid().ToString(); if (!referencedMaterials.Contains(mtl)) { referencedMaterials.Add(mtl); } multiMatsCount = Math.Max(mtl.SubMaterialCount, 1); } babylonMesh.visibility = meshNode.MaxNode.GetVisibility(0, Tools.Forever); var vertices = new List<GlobalVertex>(); var indices = new List<int>(); var mappingChannels = unskinnedMesh.ActiveMapChannelNum; bool hasUV = false; bool hasUV2 = false; for (int i = 0; i < mappingChannels.Count; ++i) { var indexer = new IntPtr(i); var channelNum = mappingChannels[indexer]; if (channelNum == 1) { hasUV = true; } else if (channelNum == 2) { hasUV2 = true; } } var hasColor = unskinnedMesh.NumberOfColorVerts > 0; var hasAlpha = unskinnedMesh.GetNumberOfMapVerts(-2) > 0; var optimizeVertices = meshNode.MaxNode.GetBoolProperty("babylonjs_optimizevertices"); // Compute normals List<GlobalVertex>[] verticesAlreadyExported = null; if (optimizeVertices) { verticesAlreadyExported = new List<GlobalVertex>[unskinnedMesh.NumberOfVerts]; } var subMeshes = new List<BabylonSubMesh>(); var indexStart = 0; for (int i = 0; i < multiMatsCount; ++i) { int materialId = meshNode.NodeMaterial == null ? 0 : meshNode.NodeMaterial.GetMaterialID(i); var indexCount = 0; var minVertexIndex = int.MaxValue; var maxVertexIndex = int.MinValue; var subMesh = new BabylonSubMesh { indexStart = indexStart, materialIndex = i }; if (multiMatsCount == 1) { for (int j = 0; j < unskinnedMesh.NumberOfFaces; ++j) { var face = unskinnedMesh.GetFace(j); ExtractFace(skin, unskinnedMesh, vertices, indices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, ref indexCount, ref minVertexIndex, ref maxVertexIndex, face, boneIds); } } else { ITab<IFaceEx> materialFaces = unskinnedMesh.GetFacesFromMatID(materialId); for (int j = 0; j < materialFaces.Count; ++j) { var faceIndexer = new IntPtr(j); var face = materialFaces[faceIndexer]; Marshal.FreeHGlobal(faceIndexer); ExtractFace(skin, unskinnedMesh, vertices, indices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, ref indexCount, ref minVertexIndex, ref maxVertexIndex, face, boneIds); } } if (indexCount != 0) { subMesh.indexCount = indexCount; subMesh.verticesStart = minVertexIndex; subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1; indexStart += indexCount; subMeshes.Add(subMesh); } } if (vertices.Count >= 65536) { RaiseWarning(string.Format("Mesh {0} has {1} vertices. This may prevent your scene to work on low end devices where 32 bits indice are not supported", babylonMesh.name, vertices.Count), 2); if (!optimizeVertices) { RaiseError("You can try to optimize your object using [Try to optimize vertices] option", 2); } } RaiseMessage(string.Format("{0} vertices, {1} faces", vertices.Count, indices.Count / 3), 2); // Buffers babylonMesh.positions = vertices.SelectMany(v => new[] { v.Position.X, v.Position.Y, v.Position.Z }).ToArray(); babylonMesh.normals = vertices.SelectMany(v => new[] { v.Normal.X, v.Normal.Y, v.Normal.Z }).ToArray(); if (hasUV) { babylonMesh.uvs = vertices.SelectMany(v => new[] { v.UV.X, 1 - v.UV.Y }).ToArray(); } if (hasUV2) { babylonMesh.uvs2 = vertices.SelectMany(v => new[] { v.UV2.X, 1 - v.UV2.Y }).ToArray(); } if (skin != null) { babylonMesh.matricesWeights = vertices.SelectMany(v => v.Weights.ToArray()).ToArray(); babylonMesh.matricesIndices = vertices.Select(v => v.BonesIndices).ToArray(); } if (hasColor) { babylonMesh.colors = vertices.SelectMany(v => v.Color.ToArray()).ToArray(); babylonMesh.hasVertexAlpha = hasAlpha; } babylonMesh.subMeshes = subMeshes.ToArray(); // Buffers - Indices babylonMesh.indices = indices.ToArray(); } // Instances var tabs = Loader.Global.NodeTab.Create(); Loader.Global.IInstanceMgr.InstanceMgr.GetInstances(meshNode.MaxNode, tabs); var instances = new List<BabylonAbstractMesh>(); for (var index = 0; index < tabs.Count; index++) { var indexer = new IntPtr(index); var tab = tabs[indexer]; Marshal.FreeHGlobal(indexer); if (meshNode.MaxNode.GetGuid() == tab.GetGuid()) { continue; } var instanceGameNode = scene.GetIGameNode(tab); if (instanceGameNode == null) { continue; } tab.MarkAsInstance(); var instance = new BabylonAbstractMesh { name = tab.Name }; { var instanceLocalTM = instanceGameNode.GetObjectTM(0); var instanceTrans = instanceLocalTM.Translation; var instanceRotation = instanceLocalTM.Rotation; var instanceScale = instanceLocalTM.Scaling; instance.position = new[] { instanceTrans.X, instanceTrans.Y, instanceTrans.Z }; if (exportQuaternions) { instance.rotationQuaternion = new[] { instanceRotation.X, instanceRotation.Y, instanceRotation.Z, -instanceRotation.W }; } else { RotationToEulerAngles(instance, instanceRotation); } instance.scaling = new[] { instanceScale.X, instanceScale.Y, instanceScale.Z }; } var instanceAnimations = new List<BabylonAnimation>(); GenerateCoordinatesAnimations(meshNode, instanceAnimations); instance.animations = instanceAnimations.ToArray(); instances.Add(instance); } babylonMesh.instances = instances.ToArray(); // Animations var animations = new List<BabylonAnimation>(); GenerateCoordinatesAnimations(meshNode, animations); if (!ExportFloatController(meshNode.MaxNode.VisController, "visibility", animations)) { ExportFloatAnimation("visibility", animations, key => new[] { meshNode.MaxNode.GetVisibility(key, Tools.Forever) }); } babylonMesh.animations = animations.ToArray(); if (meshNode.MaxNode.GetBoolProperty("babylonjs_autoanimate", 1)) { babylonMesh.autoAnimate = true; babylonMesh.autoAnimateFrom = (int)meshNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_from"); babylonMesh.autoAnimateTo = (int)meshNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_to", 100); babylonMesh.autoAnimateLoop = meshNode.MaxNode.GetBoolProperty("babylonjs_autoanimateloop", 1); } babylonScene.MeshesList.Add(babylonMesh); }
private BabylonMesh ConvertUnityTerrainToBabylon(Terrain terrain, GameObject gameObject, float progress, ref UnityMetaData metaData, ref List<BabylonExport.Entities.BabylonParticleSystem> particleSystems, ref List<UnityFlareSystem> lensFlares, ref string componentTags) { ExporterWindow.ReportProgress(progress, "Exporting terrain: " + gameObject.name); var transform = gameObject.transform; float[] position = transform.localPosition.ToFloat(); float[] rotation = new float[3]; rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180; rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180; rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180; float[] scaling = transform.localScale.ToFloat(); BabylonMesh babylonMesh = new BabylonMesh { name = gameObject.name, id = GetID(gameObject) }; metaData.type = "Terrain"; if (!String.IsNullOrEmpty(componentTags)) { babylonMesh.tags = componentTags; } babylonMesh.tags += " [TERRAIN]"; if (!String.IsNullOrEmpty(babylonMesh.tags)) { babylonMesh.tags = babylonMesh.tags.Trim(); } babylonMesh.parentId = GetParentID(transform); babylonMesh.position = Vector3.zero.ToFloat(); babylonMesh.rotation = rotation; babylonMesh.scaling = scaling; babylonMesh.isVisible = true; babylonMesh.visibility = 1; babylonMesh.checkCollisions = false; metaData.properties["collisionMeshId"] = null; var generator = gameObject.GetComponent<BabylonTerrainGenerator>(); if (generator != null && terrain != null) { // TODO: Terrain tree information object treeInstances = null; object treePrototypes = null; // Terrain metadata infomation Vector3 terrainSize = terrain.terrainData.size; metaData.properties.Add("width", terrainSize.x); metaData.properties.Add("length", terrainSize.z); metaData.properties.Add("height", terrainSize.y); metaData.properties.Add("position", position); metaData.properties.Add("rotation", rotation); metaData.properties.Add("scaling", scaling); metaData.properties.Add("thickness", terrain.terrainData.thickness); metaData.properties.Add("detailWidth", terrain.terrainData.detailWidth); metaData.properties.Add("detailHeight", terrain.terrainData.detailHeight); metaData.properties.Add("heightmapWidth", terrain.terrainData.heightmapWidth); metaData.properties.Add("heightmapHeight", terrain.terrainData.heightmapHeight); metaData.properties.Add("wavingGrassAmount", terrain.terrainData.wavingGrassAmount); metaData.properties.Add("wavingGrassSpeed", terrain.terrainData.wavingGrassSpeed); metaData.properties.Add("wavingGrassStrength", terrain.terrainData.wavingGrassStrength); metaData.properties.Add("wavingGrassTint", terrain.terrainData.wavingGrassTint.ToFloat()); metaData.properties.Add("treeInstanceCount", terrain.terrainData.treeInstanceCount); metaData.properties.Add("treeInstances", treeInstances); metaData.properties.Add("treePrototypes", treePrototypes); metaData.properties.Add("physicsState", generator.physicsActive); metaData.properties.Add("physicsMass", generator.physicsMass); metaData.properties.Add("physicsFriction", generator.physicsFriction); metaData.properties.Add("physicsRestitution", generator.physicsRestitution); metaData.properties.Add("physicsImpostor", (int)generator.physicsImpostor); metaData.properties.Add("groundTessellation", generator.groundTessellation); // Generate detailed mesh ExporterWindow.ReportProgress(progress, "Generating terrain mesh: " + gameObject.name); BabylonTerrainData terrainMeshData = Unity3D2Babylon.Tools.CreateTerrainData(terrain.terrainData, (int)generator.terrainResolution, transform.localPosition, true); Tools.GenerateBabylonMeshTerrainData(terrainMeshData, babylonMesh, false, babylonScene, transform); if (generator.surfaceMaterial != null) { babylonMesh.materialId = DumpMaterial(generator.surfaceMaterial, terrain.lightmapIndex, terrain.lightmapScaleOffset, generator.coordinatesIndex).id; } // Generate collision heightmap var terrainCollider = gameObject.GetComponent<TerrainCollider>(); if (terrainCollider != null && terrainCollider.enabled) { ExporterWindow.ReportProgress(progress, "Generating terrain heightmap: " + gameObject.name); float minheight = float.MaxValue; float maxheight = float.MinValue; int hwidth = terrain.terrainData.heightmapWidth; int hheight = terrain.terrainData.heightmapHeight; float[,] rawHeights = terrain.terrainData.GetHeights(0, 0, hwidth, hheight); Texture2D heightMap = new Texture2D(hwidth, hheight, TextureFormat.ARGB32, false); for (int y = 0; y < hheight; y++) { for (int x = 0; x < hwidth; x++) { float inverted = rawHeights[y, x]; minheight = Mathf.Min(minheight, inverted); maxheight = Mathf.Max(maxheight, inverted); } } List<Color32> pixels = new List<Color32>(); for (int y = 0; y < hheight; y++) { for (int x = 0; x < hwidth; x++) { float inverted = rawHeights[y, x]; if (generator.heightmapStrength > 0) { float threadhold = minheight + generator.floorThreashold; if (inverted > threadhold) { inverted += (generator.heightmapStrength / 10.0f); } } byte[] packed = BitConverter.GetBytes(inverted); if (packed != null && packed.Length >= 4) { pixels.Add(new Color32(packed[0], packed[1], packed[2], packed[3])); } } } heightMap.SetPixels32(pixels.ToArray()); heightMap.Apply(); byte[] heightmapBytes = heightMap.EncodeToPNG(); metaData.properties.Add("heightmapBase64", ("data:image/png;base64," + Convert.ToBase64String(heightmapBytes))); } } else { UnityEngine.Debug.LogWarning("No valid terrain or generator found for: " + gameObject.name); } babylonMesh.metadata = metaData; babylonScene.MeshesList.Add(babylonMesh); SceneBuilder.Metadata.properties["hasTerrainMeshes"] = true; // Animations ExportAnimations(transform, babylonMesh); if (IsRotationQuaternionAnimated(babylonMesh)) { babylonMesh.rotationQuaternion = transform.localRotation.ToFloat(); } // Lens Flares ParseLensFlares(gameObject, babylonMesh.id, ref lensFlares); // Particles Systems ParseParticleSystems(gameObject, babylonMesh.id, ref particleSystems); return babylonMesh; }
private BabylonMesh ConvertUnityMeshToBabylon(Mesh mesh, Transform transform, GameObject gameObject, float progress, ref UnityMetaData metaData, ref List<BabylonExport.Entities.BabylonParticleSystem> particleSystems, ref List<UnityFlareSystem> lensFlares, ref string componentTags, BabylonMesh collisionMesh = null, Collider collider = null) { BabylonMesh babylonMesh = new BabylonMesh(); metaData.type = "Mesh"; if (!String.IsNullOrEmpty(componentTags)) { babylonMesh.tags = componentTags; } ExporterWindow.ReportProgress(progress, "Exporting mesh: " + gameObject.name); babylonMesh.name = gameObject.name; babylonMesh.id = GetID(transform.gameObject); var renderer = gameObject.GetComponent<Renderer>(); if (renderer != null) { babylonMesh.receiveShadows = renderer.receiveShadows; } babylonMesh.parentId = GetParentID(transform); babylonMesh.position = transform.localPosition.ToFloat(); babylonMesh.rotation = new float[3]; babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180; babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180; babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180; babylonMesh.scaling = transform.localScale.ToFloat(); babylonMesh.checkCollisions = false; // Collision mesh (With detail mesh fallback) string collisionMeshId = null; if (collider != null) { if (collisionMesh != null) { collisionMeshId = collisionMesh.id; collisionMesh.parentId = babylonMesh.id; collisionMesh.visibility = collider.isTrigger ? 0.25f : 0.5f; collisionMesh.checkCollisions = (exportationOptions.ExportCollisions && collider.isTrigger == false); } else { babylonMesh.checkCollisions = exportationOptions.ExportCollisions; } } metaData.properties["collisionMeshId"] = collisionMeshId; if (mesh != null) { Tools.GenerateBabylonMeshData(mesh, babylonMesh, babylonScene, transform); int index = 0; if (mesh.boneWeights.Length == mesh.vertexCount) { babylonMesh.matricesIndices = new int[mesh.vertexCount]; babylonMesh.matricesWeights = new float[mesh.vertexCount * 4]; index = 0; foreach (BoneWeight bw in mesh.boneWeights) { babylonMesh.matricesIndices[index] = (bw.boneIndex3 << 24) | (bw.boneIndex2 << 16) | (bw.boneIndex1 << 8) | bw.boneIndex0; babylonMesh.matricesWeights[index * 4 + 0] = bw.weight0; babylonMesh.matricesWeights[index * 4 + 1] = bw.weight1; babylonMesh.matricesWeights[index * 4 + 2] = bw.weight2; babylonMesh.matricesWeights[index * 4 + 3] = bw.weight3; var totalWeight = bw.weight0 + bw.weight1 + bw.weight2 + bw.weight3; if (Mathf.Abs(totalWeight - 1.0f) > 0.01f) { throw new Exception("Total bone weights is not normalized for: " + mesh); } index++; } } index = 0; if (renderer != null && renderer.sharedMaterial != null) { // Validate Multi Materials if (mesh.subMeshCount > 1) { BabylonMultiMaterial bMultiMat; string multiMatName = ""; for (int i = 0; i < renderer.sharedMaterials.Length; i++) { multiMatName += renderer.sharedMaterials[i].name; } if (!multiMatDictionary.ContainsKey(multiMatName)) { bMultiMat = new BabylonMultiMaterial { materials = new string[mesh.subMeshCount], id = Guid.NewGuid().ToString(), name = multiMatName }; for (int i = 0; i < renderer.sharedMaterials.Length; i++) { var sharedMaterial = renderer.sharedMaterials[i]; BabylonMaterial babylonMaterial; babylonMaterial = DumpMaterial(sharedMaterial, renderer.lightmapIndex, renderer.lightmapScaleOffset); bMultiMat.materials[i] = babylonMaterial.id; } if (mesh.subMeshCount > 1) { multiMatDictionary.Add(bMultiMat.name, bMultiMat); } } else { bMultiMat = multiMatDictionary[multiMatName]; } babylonMesh.materialId = bMultiMat.id; babylonMesh.subMeshes = new BabylonSubMesh[mesh.subMeshCount]; var offset = 0; for (int materialIndex = 0; materialIndex < mesh.subMeshCount; materialIndex++) { var unityTriangles = mesh.GetTriangles(materialIndex); babylonMesh.subMeshes[materialIndex] = new BabylonSubMesh { verticesStart = 0, verticesCount = mesh.vertexCount, materialIndex = materialIndex, indexStart = offset, indexCount = unityTriangles.Length }; offset += unityTriangles.Length; } } else { babylonMesh.materialId = DumpMaterial(renderer.sharedMaterial, renderer.lightmapIndex, renderer.lightmapScaleOffset).id; } } babylonMesh.metadata = metaData; babylonScene.MeshesList.Add(babylonMesh); // Animations ExportAnimations(transform, babylonMesh); if (IsRotationQuaternionAnimated(babylonMesh)) { babylonMesh.rotationQuaternion = transform.localRotation.ToFloat(); } // Lens Flares ParseLensFlares(gameObject, babylonMesh.id, ref lensFlares); // Particles Systems ParseParticleSystems(gameObject, babylonMesh.id, ref particleSystems); // Babylon Physics if (exportationOptions.ExportPhysics) { var physics = gameObject.GetComponent<BabylonPhysicsState>(); if (physics != null) { babylonMesh.physicsMass = physics.mass; babylonMesh.physicsFriction = physics.friction; babylonMesh.physicsRestitution = physics.restitution; babylonMesh.physicsImpostor = (int)physics.imposter; } } } return babylonMesh; }
private void ConvertUnityEmptyObjectToBabylon(GameObject gameObject, BabylonAbstractMesh[] instances = null) { BabylonMesh babylonMesh = new BabylonMesh { name = gameObject.name, id = GetID(gameObject) }; var transform = gameObject.transform; babylonMesh.parentId = GetParentID(transform); ConvertTransform(babylonMesh, transform, gameObject, instances); babylonScene.MeshesList.Add(babylonMesh); // Animations ExportAnimations(transform, babylonMesh); if (IsRotationQuaternionAnimated(babylonMesh)) { babylonMesh.rotationQuaternion = transform.localRotation.ToFloat(); } }
private void ConvertTransform(BabylonMesh babylonMesh, Transform transform, GameObject gameObject, BabylonAbstractMesh[] instances = null) { Action SetTransformFromGameobject = () => { babylonMesh.position = transform.localPosition.ToFloat(); babylonMesh.rotation = new float[3]; babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180; babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180; babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180; babylonMesh.scaling = transform.localScale.ToFloat(); }; Action SetTransformFromFirstInstance = () => { BabylonAbstractMesh first = instances[0]; babylonMesh.position = new float[3]; babylonMesh.position[0] = first.position[0]; babylonMesh.position[1] = first.position[1]; babylonMesh.position[2] = first.position[2]; babylonMesh.rotation = new float[3]; babylonMesh.rotation[0] = first.rotation[0]; babylonMesh.rotation[1] = first.rotation[1]; babylonMesh.rotation[2] = first.rotation[2]; babylonMesh.scaling = new float[3]; babylonMesh.scaling[0] = first.scaling[0]; babylonMesh.scaling[1] = first.scaling[1]; babylonMesh.scaling[2] = first.scaling[2]; }; //Check if this is a prefab if (instances != null) { /* Unity3D prefabs don't have transforms (position, rotation, scale) because they are just a template and are not drawn on screen but Babylon.js meshes must have a transform because they are drawn on the screen so what we do is take the first instance copy its transform (position, rotation, scale) into the prefab mesh then remove that first instance */ babylonMesh.instances = new BabylonAbstractMesh[instances.Length - 1]; //Effectively remove first instance from list of all instances for (int i = 0; i < instances.Length - 1; i++) { babylonMesh.instances[i] = instances[i + 1]; } //If this is the root object then copy values directly from first instance if (GetParentID(transform) == null) { SetTransformFromFirstInstance(); } else { GameObject parent = gameObject.transform.parent.gameObject; if ((parent.GetComponent<Light>() == null) && (parent.GetComponent<Camera>() == null)) { SetTransformFromGameobject(); } else { SetTransformFromFirstInstance(); } } } else { SetTransformFromGameobject(); } }
private void ConvertUnityMeshToBabylon(Mesh mesh, Transform transform, GameObject gameObject, float progress) { BabylonMesh babylonMesh = new BabylonMesh(); var renderer = gameObject.GetComponent<Renderer>(); ExporterWindow.ReportProgress(progress, "Exporting mesh: " + gameObject.name); babylonMesh.name = gameObject.name; babylonMesh.id = GetID(transform.gameObject); babylonMesh.receiveShadows = renderer.receiveShadows; babylonMesh.parentId = GetParentID(transform); babylonMesh.position = transform.localPosition.ToFloat(); babylonMesh.rotation = new float[3]; babylonMesh.rotation[0] = transform.localRotation.eulerAngles.x * (float)Math.PI / 180; babylonMesh.rotation[1] = transform.localRotation.eulerAngles.y * (float)Math.PI / 180; babylonMesh.rotation[2] = transform.localRotation.eulerAngles.z * (float)Math.PI / 180; babylonMesh.scaling = transform.localScale.ToFloat(); babylonMesh.positions = new float[mesh.vertexCount * 3]; for (int i = 0; i < mesh.vertices.Length; i++) { babylonMesh.positions[i * 3] = mesh.vertices[i].x; babylonMesh.positions[(i * 3) + 1] = mesh.vertices[i].y; babylonMesh.positions[(i * 3) + 2] = mesh.vertices[i].z; // Computing world extends var worldPosition = transform.TransformPoint(mesh.vertices[i]); if (worldPosition.x > babylonScene.MaxVector.X) { babylonScene.MaxVector.X = worldPosition.x; } if (worldPosition.y > babylonScene.MaxVector.Y) { babylonScene.MaxVector.Y = worldPosition.y; } if (worldPosition.z > babylonScene.MaxVector.Z) { babylonScene.MaxVector.Z = worldPosition.z; } if (worldPosition.x < babylonScene.MinVector.X) { babylonScene.MinVector.X = worldPosition.x; } if (worldPosition.y < babylonScene.MinVector.Y) { babylonScene.MinVector.Y = worldPosition.y; } if (worldPosition.z < babylonScene.MinVector.Z) { babylonScene.MinVector.Z = worldPosition.z; } } babylonMesh.normals = new float[mesh.vertexCount * 3]; for (int i = 0; i < mesh.normals.Length; i++) { babylonMesh.normals[i * 3] = mesh.normals[i].x; babylonMesh.normals[(i * 3) + 1] = mesh.normals[i].y; babylonMesh.normals[(i * 3) + 2] = mesh.normals[i].z; } babylonMesh.uvs = new float[mesh.vertexCount * 2]; for (int i = 0; i < mesh.uv.Length; i++) { babylonMesh.uvs[i * 2] = mesh.uv[i].x; babylonMesh.uvs[(i * 2) + 1] = mesh.uv[i].y; } if (mesh.uv2 != null) { babylonMesh.uvs2 = new float[mesh.vertexCount * 2]; for (int i = 0; i < mesh.uv2.Length; i++) { babylonMesh.uvs2[i * 2] = mesh.uv2[i].x; babylonMesh.uvs2[(i * 2) + 1] = mesh.uv2[i].y; } } babylonMesh.indices = new int[mesh.triangles.Length]; for (int i = 0; i < mesh.triangles.Length; i += 3) { babylonMesh.indices[i] = mesh.triangles[i + 2]; babylonMesh.indices[i + 1] = mesh.triangles[i + 1]; babylonMesh.indices[i + 2] = mesh.triangles[i]; } if (mesh.subMeshCount > 1) // Multimaterials { BabylonMultiMaterial bMultiMat; if (!multiMatDictionary.ContainsKey(renderer.sharedMaterial.name)) { bMultiMat = new BabylonMultiMaterial { materials = new string[mesh.subMeshCount], id = Guid.NewGuid().ToString(), name = renderer.sharedMaterial.name }; for (int i = 0; i < renderer.sharedMaterials.Length; i++) { var bMat = DumpMaterial(renderer.sharedMaterials[i], renderer); bMultiMat.materials[i] = bMat.id; } if (mesh.subMeshCount > 1) { multiMatDictionary.Add(bMultiMat.name, bMultiMat); } } else { bMultiMat = multiMatDictionary[renderer.sharedMaterial.name]; } babylonMesh.materialId = bMultiMat.id; babylonMesh.subMeshes = new BabylonSubMesh[mesh.subMeshCount]; var offset = 0; for (int materialIndex = 0; materialIndex < mesh.subMeshCount; materialIndex++) { var unityTriangles = mesh.GetTriangles(materialIndex); babylonMesh.subMeshes[materialIndex] = new BabylonSubMesh { verticesStart = 0, verticesCount = mesh.vertexCount, materialIndex = materialIndex, indexStart = offset, indexCount = unityTriangles.Length }; offset += unityTriangles.Length; } } else { babylonMesh.materialId = DumpMaterial(renderer.sharedMaterial, renderer).id; } babylonScene.MeshesList.Add(babylonMesh); // Animations ExportAnimations(transform, babylonMesh); if (IsRotationQuaternionAnimated(babylonMesh)) { babylonMesh.rotationQuaternion = transform.localRotation.ToFloat(); } // Collisions if (exportationOptions.ExportCollisions) { var collider = gameObject.GetComponent<Collider>(); if (collider != null) { babylonMesh.checkCollisions = true; } } }
private void ExportMesh(IINode meshNode, BabylonScene babylonScene) { if (meshNode.GetBoolProperty("babylonjs_noexport")) { return; } if (!ExportHiddenObjects && meshNode.IsHidden(NodeHideFlags.None, false)) { return; } var babylonMesh = new BabylonMesh(); int vx1, vx2, vx3; babylonMesh.name = meshNode.Name; babylonMesh.id = meshNode.GetGuid().ToString(); if (meshNode.HasParent()) { babylonMesh.parentId = meshNode.ParentNode.GetGuid().ToString(); } // Misc. babylonMesh.isVisible = meshNode.Renderable == 1; babylonMesh.pickable = meshNode.GetBoolProperty("babylonjs_checkpickable"); babylonMesh.receiveShadows = meshNode.RcvShadows == 1; babylonMesh.showBoundingBox = meshNode.GetBoolProperty("babylonjs_showboundingbox"); babylonMesh.showSubMeshesBoundingBox = meshNode.GetBoolProperty("babylonjs_showsubmeshesboundingbox"); // Collisions babylonMesh.checkCollisions = meshNode.GetBoolProperty("babylonjs_checkcollisions"); // Skin var skin = GetSkinModifier(meshNode); if (skin != null) { babylonMesh.skeletonId = skins.IndexOf(skin); bonesCount = skin.NumBones; } // Position / rotation / scaling var wm = meshNode.GetWorldMatrix(0, meshNode.HasParent()); babylonMesh.position = wm.Trans.ToArraySwitched(); var parts = Loader.Global.AffineParts.Create(); Loader.Global.DecompAffine(wm, parts); if (exportQuaternionsInsteadOfEulers) { babylonMesh.rotationQuaternion = parts.Q.ToArray(); } else { var rotate = new float[3]; IntPtr xPtr = Marshal.AllocHGlobal(sizeof(float)); IntPtr yPtr = Marshal.AllocHGlobal(sizeof(float)); IntPtr zPtr = Marshal.AllocHGlobal(sizeof(float)); parts.Q.GetEuler(xPtr, yPtr, zPtr); Marshal.Copy(xPtr, rotate, 0, 1); Marshal.Copy(yPtr, rotate, 1, 1); Marshal.Copy(zPtr, rotate, 2, 1); var temp = rotate[1]; rotate[0] = -rotate[0] * parts.F; rotate[1] = -rotate[2] * parts.F; rotate[2] = -temp * parts.F; babylonMesh.rotation = rotate; } babylonMesh.scaling = parts.K.ToArraySwitched(); if (wm.Parity) { vx1 = 2; vx2 = 1; vx3 = 0; } else { vx1 = 0; vx2 = 1; vx3 = 2; } // Pivot var pivotMatrix = Tools.Identity; pivotMatrix.PreTranslate(meshNode.ObjOffsetPos); Loader.Global.PreRotateMatrix(pivotMatrix, meshNode.ObjOffsetRot); Loader.Global.ApplyScaling(pivotMatrix, meshNode.ObjOffsetScale); babylonMesh.pivotMatrix = pivotMatrix.ToArray(); // Mesh var objectState = meshNode.EvalWorldState(0, false); var triObject = objectState.Obj.GetMesh(); var mesh = triObject != null ? triObject.Mesh : null; RaiseMessage(meshNode.Name, 1); if (mesh != null) { mesh.BuildNormals(); if (mesh.NumFaces < 1) { RaiseError(string.Format("Mesh {0} has no face", babylonMesh.name), 2); } if (mesh.NumVerts < 3) { RaiseError(string.Format("Mesh {0} has not enough vertices", babylonMesh.name), 2); } if (mesh.NumVerts >= 65536) { RaiseError(string.Format("Mesh {0} has too many vertices (more than 65535)", babylonMesh.name), 2); } // Material var mtl = meshNode.Mtl; var multiMatsCount = 1; if (mtl != null) { babylonMesh.materialId = mtl.GetGuid().ToString(); if (!referencedMaterials.Contains(mtl)) { referencedMaterials.Add(mtl); } multiMatsCount = Math.Max(mtl.NumSubMtls, 1); } babylonMesh.visibility = meshNode.GetVisibility(0, Tools.Forever); var vertices = new List<GlobalVertex>(); var indices = new List<int>(); var matIDs = new List<int>(); var hasUV = mesh.NumTVerts > 0; var hasUV2 = mesh.GetNumMapVerts(2) > 0; var optimizeVertices = meshNode.GetBoolProperty("babylonjs_optimizevertices"); // Skin IISkinContextData skinContext = null; if (skin != null) { skinContext = skin.GetContextInterface(meshNode); } // Compute normals VNormal[] vnorms = Tools.ComputeNormals(mesh, optimizeVertices); List<GlobalVertex>[] verticesAlreadyExported = null; if (optimizeVertices) { verticesAlreadyExported = new List<GlobalVertex>[mesh.NumVerts]; } for (var face = 0; face < mesh.NumFaces; face++) { indices.Add(CreateGlobalVertex(mesh, face, vx1, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext)); indices.Add(CreateGlobalVertex(mesh, face, vx2, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext)); indices.Add(CreateGlobalVertex(mesh, face, vx3, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext)); matIDs.Add(mesh.Faces[face].MatID % multiMatsCount); CheckCancelled(); } if (vertices.Count >= 65536) { RaiseError(string.Format("Mesh {0} has too many vertices: {1} (limit is 65535)", babylonMesh.name, vertices.Count), 2); if (!optimizeVertices) { RaiseError("You can try to optimize your object using [Try to optimize vertices] option", 2); } } RaiseMessage(string.Format("{0} vertices, {1} faces", vertices.Count, indices.Count / 3), 2); // Buffers babylonMesh.positions = vertices.SelectMany(v => v.Position.ToArraySwitched()).ToArray(); babylonMesh.normals = vertices.SelectMany(v => v.Normal.ToArraySwitched()).ToArray(); if (hasUV) { babylonMesh.uvs = vertices.SelectMany(v => v.UV.ToArray()).ToArray(); } if (hasUV2) { babylonMesh.uvs2 = vertices.SelectMany(v => v.UV2.ToArray()).ToArray(); } if (skin != null) { babylonMesh.matricesWeights = vertices.SelectMany(v => v.Weights.ToArray()).ToArray(); babylonMesh.matricesIndices = vertices.Select(v => v.BonesIndices).ToArray(); } // Submeshes var sortedIndices = new List<int>(); var subMeshes = new List<BabylonSubMesh>(); var indexStart = 0; for (var index = 0; index < multiMatsCount; index++) { var subMesh = new BabylonSubMesh(); var indexCount = 0; var minVertexIndex = int.MaxValue; var maxVertexIndex = int.MinValue; subMesh.indexStart = indexStart; subMesh.materialIndex = index; for (var face = 0; face < matIDs.Count; face++) { if (matIDs[face] == index) { var a = indices[3 * face]; var b = indices[3 * face + 1]; var c = indices[3 * face + 2]; sortedIndices.Add(a); sortedIndices.Add(b); sortedIndices.Add(c); indexCount += 3; if (a < minVertexIndex) { minVertexIndex = a; } if (b < minVertexIndex) { minVertexIndex = b; } if (c < minVertexIndex) { minVertexIndex = c; } if (a > maxVertexIndex) { maxVertexIndex = a; } if (b > maxVertexIndex) { maxVertexIndex = b; } if (c > maxVertexIndex) { maxVertexIndex = c; } } } if (indexCount != 0) { subMesh.indexCount = indexCount; subMesh.verticesStart = minVertexIndex; subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1; indexStart += indexCount; subMeshes.Add(subMesh); } CheckCancelled(); } babylonMesh.subMeshes = subMeshes.ToArray(); // Buffers - Indices babylonMesh.indices = sortedIndices.ToArray(); triObject.Dispose(); } // Animations var animations = new List<BabylonAnimation>(); if (!ExportVector3Controller(meshNode.TMController.PositionController, "position", animations)) { ExportVector3Animation("position", animations, key => { var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent()); return worldMatrix.Trans.ToArraySwitched(); }); } if (!ExportQuaternionController(meshNode.TMController.RotationController, "rotationQuaternion", animations)) { ExportQuaternionAnimation("rotationQuaternion", animations, key => { var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent()); var affineParts = Loader.Global.AffineParts.Create(); Loader.Global.DecompAffine(worldMatrix, affineParts); return affineParts.Q.ToArray(); }); } if (!ExportVector3Controller(meshNode.TMController.ScaleController, "scaling", animations)) { ExportVector3Animation("scaling", animations, key => { var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent()); var affineParts = Loader.Global.AffineParts.Create(); Loader.Global.DecompAffine(worldMatrix, affineParts); return affineParts.K.ToArraySwitched(); }); } if (!ExportFloatController(meshNode.VisController, "visibility", animations)) { ExportFloatAnimation("visibility", animations, key => new[] { meshNode.GetVisibility(key, Tools.Forever) }); } babylonMesh.animations = animations.ToArray(); if (meshNode.GetBoolProperty("babylonjs_autoanimate", 1)) { babylonMesh.autoAnimate = true; babylonMesh.autoAnimateFrom = (int)meshNode.GetFloatProperty("babylonjs_autoanimate_from"); babylonMesh.autoAnimateTo = (int)meshNode.GetFloatProperty("babylonjs_autoanimate_to", 100); babylonMesh.autoAnimateLoop = meshNode.GetBoolProperty("babylonjs_autoanimateloop", 1); } babylonScene.MeshesList.Add(babylonMesh); }
private static void ExportSkeletonAnimationClipData(Animator animator, bool autoPlay, BabylonSkeleton skeleton, Transform[] bones, BabylonMesh babylonMesh, AnimationClip clip) { var frameTime = 1.0f / clip.frameRate; int animationFrameCount = (int)(clip.length * clip.frameRate); if (autoPlay) { babylonMesh.autoAnimate = true; babylonMesh.autoAnimateFrom = 0; babylonMesh.autoAnimateTo = animationFrameCount; babylonMesh.autoAnimateLoop = true; } foreach (var bone in skeleton.bones) { var keys = new List<BabylonAnimationKey>(); var transform = bones.Single(b => b.name == bone.name); AnimationMode.BeginSampling(); for (var i = 0; i < animationFrameCount; i++) { clip.SampleAnimation(animator.gameObject, i * frameTime); var local = (transform.parent.localToWorldMatrix.inverse * transform.localToWorldMatrix); float[] matrix = new[] { local[0, 0], local[1, 0], local[2, 0], local[3, 0], local[0, 1], local[1, 1], local[2, 1], local[3, 1], local[0, 2], local[1, 2], local[2, 2], local[3, 2], local[0, 3], local[1, 3], local[2, 3], local[3, 3] }; var key = new BabylonAnimationKey { frame = i, values = matrix, }; keys.Add(key); } AnimationMode.EndSampling(); var babylonAnimation = new BabylonAnimation { name = bone.name + "Animation", property = "_matrix", dataType = (int)BabylonAnimation.DataType.Matrix, loopBehavior = (int)BabylonAnimation.LoopBehavior.Cycle, framePerSecond = (int)clip.frameRate, keys = keys.ToArray() }; bone.animation = babylonAnimation; } }
public void ConvertFromUnity() { ExporterWindow.ReportProgress(0, "Starting exportation process..."); gameObjects = Object.FindObjectsOfType(typeof(GameObject)) as GameObject[]; if (gameObjects.Length == 0) { ExporterWindow.ShowMessage("No gameobject! - Please add at least a gameobject to export"); return; } // Create scene metadata SceneBuilder.Metadata = new SceneMetaData(); // Parse all scene game objects var index = 0; var itemsCount = gameObjects.Length; var particleSystems = new List<BabylonExport.Entities.BabylonParticleSystem>(); var lensFlareSystems = new List<UnityFlareSystem>(); ExporterWindow.ReportProgress(0, "Exporting game objects from scene..."); babylonScene.physicsEngine = (exportationOptions.DefaultPhysicsEngine == 1) ? "oimo" : "cannon"; try { bool foundController = false; foreach (var gameObject in gameObjects) { var progress = ((float)index / itemsCount); index++; // Unity metadata var metaData = new UnityMetaData(); metaData.objectId = GetID(gameObject); metaData.objectName = gameObject.name; metaData.tagName = gameObject.tag; metaData.layerIndex = gameObject.layer; metaData.layerName = LayerMask.LayerToName(gameObject.layer); // Export hooking var exportObject = gameObject; var exportOptions = exportationOptions; BabylonScene sceneBuilder = babylonScene; if (SceneController != null) { SceneController.OnExportGameObject(ref exportOptions, ref exportObject, ref metaData, ref sceneBuilder, OutputPath); } // Components tags string componentTags = String.Empty; if (!String.IsNullOrEmpty(gameObject.tag) && !gameObject.tag.Equals("Untagged", StringComparison.OrdinalIgnoreCase)) { componentTags = gameObject.tag; } // Navigation area metaData.areaIndex = -1; bool navigationStatic = GameObjectUtility.AreStaticEditorFlagsSet(gameObject, StaticEditorFlags.NavigationStatic); if (navigationStatic) { metaData.areaIndex = GameObjectUtility.GetNavMeshArea(gameObject); } // Navigation agent metaData.navAgent = null; var navigationAgent = gameObject.GetComponent<NavMeshAgent>(); if (navigationAgent != null) { componentTags += " [NAVAGENT]"; Dictionary<string, object> agentInfo = new Dictionary<string, object>(); agentInfo.Add("name", navigationAgent.name); agentInfo.Add("radius", navigationAgent.radius); agentInfo.Add("height", navigationAgent.height); agentInfo.Add("speed", navigationAgent.speed); agentInfo.Add("acceleration", navigationAgent.acceleration); agentInfo.Add("angularSpeed", navigationAgent.angularSpeed); agentInfo.Add("areaMask", navigationAgent.areaMask); agentInfo.Add("autoBraking", navigationAgent.autoBraking); agentInfo.Add("autoTraverseOffMeshLink", navigationAgent.autoTraverseOffMeshLink); agentInfo.Add("avoidancePriority", navigationAgent.avoidancePriority); agentInfo.Add("baseOffset", navigationAgent.baseOffset); agentInfo.Add("obstacleAvoidanceType", navigationAgent.obstacleAvoidanceType.ToString()); agentInfo.Add("stoppingDistance", navigationAgent.stoppingDistance); metaData.navAgent = agentInfo; } // Navigation link metaData.meshLink = null; var navigationLink = gameObject.GetComponent<OffMeshLink>(); if (navigationLink != null) { componentTags += " [MESHLINK]"; Dictionary<string, object> linkInfo = new Dictionary<string, object>(); linkInfo.Add("name", navigationLink.name); linkInfo.Add("activated", navigationLink.activated); linkInfo.Add("area", navigationLink.area); linkInfo.Add("autoUpdatePositions", navigationLink.autoUpdatePositions); linkInfo.Add("biDirectional", navigationLink.biDirectional); linkInfo.Add("costOverride", navigationLink.costOverride); linkInfo.Add("occupied", navigationLink.occupied); linkInfo.Add("start", GetTransformPropertyValue(navigationLink.startTransform)); linkInfo.Add("end", GetTransformPropertyValue(navigationLink.endTransform)); metaData.meshLink = linkInfo; } // Navigation obstacle metaData.meshObstacle = null; var navigationObstacle = gameObject.GetComponent<NavMeshObstacle>(); if (navigationObstacle != null) { componentTags += " [MESHOBSTACLE]"; Dictionary<string, object> obstacleInfo = new Dictionary<string, object>(); obstacleInfo.Add("name", navigationObstacle.name); obstacleInfo.Add("carving", navigationObstacle.carving); obstacleInfo.Add("carveOnlyStationary", navigationObstacle.carveOnlyStationary); obstacleInfo.Add("carvingMoveThreshold", navigationObstacle.carvingMoveThreshold); obstacleInfo.Add("carvingTimeToStationary", navigationObstacle.carvingTimeToStationary); obstacleInfo.Add("shape", navigationObstacle.shape.ToString()); obstacleInfo.Add("radius", navigationObstacle.radius); obstacleInfo.Add("center", navigationObstacle.center.ToFloat()); obstacleInfo.Add("size", navigationObstacle.size.ToFloat()); metaData.meshObstacle = obstacleInfo; } // Tags component var tagsComponent = gameObject.GetComponent<BabylonTagsComponent>(); if (tagsComponent != null) { if (!String.IsNullOrEmpty(tagsComponent.babylonTags)) { componentTags += (" " + tagsComponent.babylonTags); } } // Script components var gameComponents = gameObject.GetComponents<BabylonScriptComponent>(); if (gameComponents != null) { var components = new List<object>(); foreach (var gameComponent in gameComponents) { Type componentType = gameComponent.GetType(); string componentName = componentType.FullName; var component = new UnityScriptComponent(); MonoScript componentScript = MonoScript.FromMonoBehaviour(gameComponent); component.order = MonoImporter.GetExecutionOrder(componentScript); component.name = componentName; component.klass = gameComponent.babylonClass; component.update = (gameComponent.updateOption == BabylonTickOptions.EnableTick); component.controller = (gameComponent is BabylonSceneController); if (component.controller == true) { component.order = -1; if (foundController == false) { foundController = true; componentTags += " [CONTROLLER]"; object userInterface = null; BabylonSceneController scx = (gameComponent as BabylonSceneController); EmbeddedAsset guiAsset = scx.sceneOptions.graphicUserInterface; if (guiAsset != null && scx.sceneOptions.userInterfaceMode != BabylonGuiMode.None) { userInterface = GetEmbeddedAssetPropertyValue(guiAsset); } SceneBuilder.Metadata.properties.Add("autoDraw", scx.sceneOptions.autoDrawInterface); SceneBuilder.Metadata.properties.Add("interfaceMode", scx.sceneOptions.userInterfaceMode.ToString()); SceneBuilder.Metadata.properties.Add("userInterface", userInterface); SceneBuilder.Metadata.properties.Add("controllerPresent", true); SceneBuilder.Metadata.properties.Add("controllerObjectId", metaData.objectId); } else { Debug.LogError("Duplicate scene controller detected: " + component.name); } } FieldInfo[] componentFields = componentType.GetFields(); if (componentFields != null) { foreach (var componentField in componentFields) { var componentAttribute = (BabylonPropertyAttribute)Attribute.GetCustomAttribute(componentField, typeof(BabylonPropertyAttribute)); if (componentAttribute != null && componentField.Name != "babylonClass") { component.properties.Add(componentField.Name, GetComponentPropertyValue(componentField, gameComponent)); } } } gameComponent.OnExportProperties(ref exportOptions, ref exportObject, ref component.properties, OutputPath); components.Add(component); } if (components.Count > 0) { metaData.components = components; } } // Format tags if (!String.IsNullOrEmpty(componentTags)) { componentTags = componentTags.Trim(); } // Audio sources var audioComponents = gameObject.GetComponents<BabylonAudioSource>(); if (audioComponents != null) { foreach (var item in audioComponents) { if (item != null && item.exportAudio && item.sound != null) { string soundPath = AssetDatabase.GetAssetPath(item.sound); if (!String.IsNullOrEmpty(soundPath)) { string soundName = Path.GetFileName(soundPath).Replace(" ", ""); string outputFile = Path.Combine(OutputPath, soundName); if (File.Exists(soundPath)) { File.Copy(soundPath, outputFile, true); var sound = new BabylonSound(); sound.name = soundName; sound.volume = item.options.volume; sound.playbackRate = item.options.playbackRate; sound.autoplay = item.options.autoplay; sound.loop = item.options.loop; sound.soundTrackId = item.options.soundTrackId; sound.spatialSound = item.options.spatialSound; sound.position = item.options.position.ToFloat(); sound.refDistance = item.options.refDistance; sound.rolloffFactor = item.options.rolloffFactor; sound.maxDistance = item.options.maxDistance; sound.distanceModel = item.options.distanceModel; sound.panningModel = item.options.panningModel; sound.isDirectional = item.options.isDirectional; sound.coneInnerAngle = item.options.coneInnerAngle; sound.coneOuterAngle = item.options.coneOuterAngle; sound.coneOuterGain = item.options.coneOuterGain; sound.localDirectionToMesh = item.options.directionToMesh.ToFloat(); babylonScene.SoundsList.Add(sound); } else { Debug.LogError("Fail to locate audio file: " + soundPath); } } else { Debug.LogError("Null audio clip path for: " + item.sound.name); } } } } // Terrain meshes var terrainMesh = gameObject.GetComponent<Terrain>(); if (terrainMesh != null) { ConvertUnityTerrainToBabylon(terrainMesh, gameObject, progress, ref metaData, ref particleSystems, ref lensFlareSystems, ref componentTags); continue; } // Collision meshes BabylonMesh collisionMesh = null; var collider = gameObject.GetComponent<Collider>(); if (collider != null) { if (collider.enabled) { int segments = 12; BabylonColliderDetail detail = (BabylonColliderDetail)exportationOptions.DefaultColliderDetail; var collisionData = new UnityMetaData(); collisionData.objectId = Guid.NewGuid().ToString(); collisionData.objectName = gameObject.name + "_Metadata"; if (collider is MeshCollider) { var meshCollider = collider as MeshCollider; collisionMesh = new BabylonMesh(); collisionMesh.tags = "[MESHCOLLIDER]"; // Generate Mesh Collider Geometry if(!meshCollider.sharedMesh) { UnityEngine.Debug.LogWarning(meshCollider.gameObject+" has a Mesh Collider component without a mesh"); } else { Tools.GenerateBabylonMeshData(meshCollider.sharedMesh, collisionMesh); } collisionMesh.position = Vector3.zero.ToFloat(); collisionMesh.rotation = Vector3.zero.ToFloat(); float factorX = 1f, factorY = 1f, factorZ = 1f; if (meshCollider.inflateMesh && meshCollider.skinWidth > 0f) { Vector3 localScale = gameObject.transform.localScale; factorX += (meshCollider.skinWidth / localScale.x); factorY += (meshCollider.skinWidth / localScale.y); factorZ += (meshCollider.skinWidth / localScale.z); } collisionMesh.scaling = new Vector3(factorX, factorY, factorZ).ToFloat(); // Export Mesh Collider Metadata collisionData.tagName = "MeshCollider"; collisionData.properties.Add("type", "Mesh"); collisionData.properties.Add("convex", meshCollider.convex); collisionData.properties.Add("inflateMesh", meshCollider.inflateMesh); collisionData.properties.Add("skinWidth", meshCollider.skinWidth); } else if (collider is CapsuleCollider) { var capsuleCollider = collider as CapsuleCollider; collisionMesh = new BabylonMesh(); collisionMesh.tags = "[CAPSULECOLLIDER]"; switch (detail) { case BabylonColliderDetail.FullResolution: segments = 48; break; case BabylonColliderDetail.HighResolution: segments = 32; break; case BabylonColliderDetail.MediumResolution: segments = 24; break; case BabylonColliderDetail.LowResolution: segments = 12; break; case BabylonColliderDetail.VeryLowResolution: segments = 8; break; case BabylonColliderDetail.MinimumResolution: segments = 6; break; default: segments = 12; break; } // Generate Capsule Collider Geometry Mesh capsuleMesh = Tools.CreateCapsuleMesh(capsuleCollider.height, capsuleCollider.radius, segments); Tools.GenerateBabylonMeshData(capsuleMesh, collisionMesh); collisionMesh.position = new float[3]; collisionMesh.position[0] = capsuleCollider.center.x; collisionMesh.position[1] = capsuleCollider.center.y; collisionMesh.position[2] = capsuleCollider.center.z; collisionMesh.rotation = new float[3]; collisionMesh.rotation[0] = (capsuleCollider.direction == 2) ? 90f * (float)Math.PI / 180f : 0f; collisionMesh.rotation[1] = 0f; collisionMesh.rotation[2] = (capsuleCollider.direction == 0) ? 90f * (float)Math.PI / 180f : 0f; collisionMesh.scaling = new Vector3(1, 1, 1).ToFloat(); // Export Capsule Collider Metadata collisionData.tagName = "CapsuleCollider"; collisionData.properties.Add("type", "Capsule"); collisionData.properties.Add("center", capsuleCollider.center.ToFloat()); collisionData.properties.Add("radius", capsuleCollider.radius); collisionData.properties.Add("height", capsuleCollider.height); collisionData.properties.Add("direction", capsuleCollider.direction); } else if (collider is SphereCollider) { var sphereCollider = collider as SphereCollider; collisionMesh = new BabylonMesh(); collisionMesh.tags = "[SPHERECOLLIDER]"; switch (detail) { case BabylonColliderDetail.FullResolution: segments = 48; break; case BabylonColliderDetail.HighResolution: segments = 32; break; case BabylonColliderDetail.MediumResolution: segments = 24; break; case BabylonColliderDetail.LowResolution: segments = 12; break; case BabylonColliderDetail.VeryLowResolution: segments = 8; break; case BabylonColliderDetail.MinimumResolution: segments = 6; break; default: segments = 12; break; } // Generate Sphere Collider Geometry Mesh sphereMesh = Tools.CreateSphereMesh(sphereCollider.radius, segments); Tools.GenerateBabylonMeshData(sphereMesh, collisionMesh); collisionMesh.position = new float[3]; collisionMesh.position[0] = sphereCollider.center.x; collisionMesh.position[1] = sphereCollider.center.y; collisionMesh.position[2] = sphereCollider.center.z; collisionMesh.rotation = Vector3.zero.ToFloat(); collisionMesh.scaling = new Vector3(1f, 1f, 1f).ToFloat(); // Export Sphere Collider Metadata collisionData.tagName = "SphereCollider"; collisionData.properties.Add("type", "Sphere"); collisionData.properties.Add("center", sphereCollider.center.ToFloat()); collisionData.properties.Add("radius", sphereCollider.radius); } else if (collider is WheelCollider) { var wheelCollider = collider as WheelCollider; collisionMesh = new BabylonMesh(); collisionMesh.tags = "[WHEELCOLLIDER]"; switch (detail) { case BabylonColliderDetail.FullResolution: segments = 128; break; case BabylonColliderDetail.HighResolution: segments = 64; break; case BabylonColliderDetail.MediumResolution: segments = 48; break; case BabylonColliderDetail.LowResolution: segments = 32; break; case BabylonColliderDetail.VeryLowResolution: segments = 24; break; case BabylonColliderDetail.MinimumResolution: segments = 16; break; default: segments = 32; break; } // Generate Wheel Collider Geometry Mesh wheelMesh = Tools.CreateWheelMesh(wheelCollider.suspensionDistance, wheelCollider.radius, segments); Tools.GenerateBabylonMeshData(wheelMesh, collisionMesh); collisionMesh.position = new float[3]; collisionMesh.position[0] = wheelCollider.center.x; collisionMesh.position[1] = wheelCollider.center.y; collisionMesh.position[2] = wheelCollider.center.z; collisionMesh.rotation = new float[3]; collisionMesh.rotation[0] = 0f; collisionMesh.rotation[1] = 0f; collisionMesh.rotation[2] = 90f * (float)Math.PI / 180; collisionMesh.scaling = new Vector3(1f, 1f, 1f).ToFloat(); // Export Wheel Collider Metadata collisionData.tagName = "WheelCollider"; collisionData.properties.Add("type", "Wheel"); collisionData.properties.Add("center", wheelCollider.center.ToFloat()); collisionData.properties.Add("radius", wheelCollider.radius); } else if (collider is BoxCollider) { var boxCollider = collider as BoxCollider; collisionMesh = new BabylonMesh(); collisionMesh.tags = "[BOXCOLLIDER]"; // Generate Box Collider Geometry Mesh boxMesh = Tools.CreateBoxMesh(boxCollider.size.x, boxCollider.size.y, boxCollider.size.z); Tools.GenerateBabylonMeshData(boxMesh, collisionMesh); collisionMesh.position = new float[3]; collisionMesh.position[0] = boxCollider.center.x; collisionMesh.position[1] = boxCollider.center.y; collisionMesh.position[2] = boxCollider.center.z; collisionMesh.rotation = Vector3.zero.ToFloat(); collisionMesh.scaling = new Vector3(1f, 1f, 1f).ToFloat(); // Export Box Collider Metadata collisionData.tagName = "BoxCollider"; collisionData.properties.Add("type", "Box"); collisionData.properties.Add("center", boxCollider.center.ToFloat()); collisionData.properties.Add("size", boxCollider.size.ToFloat()); } if (collisionMesh != null) { collisionMesh.id = Guid.NewGuid().ToString(); collisionMesh.name = gameObject.name + "_Collider"; // Default Check Collisions False collisionMesh.checkCollisions = false; collisionMesh.isVisible = false; collisionData.properties.Add("parrentId", metaData.objectId); collisionData.properties.Add("transform", GetTransformPropertyValue(gameObject.transform)); collisionMesh.metadata = collisionData; babylonScene.MeshesList.Add(collisionMesh); SceneBuilder.Metadata.properties["hasCollisionMeshes"] = true; } } } // Static meshes var meshFilter = gameObject.GetComponent<MeshFilter>(); if (meshFilter != null) { ConvertUnityMeshToBabylon(meshFilter.sharedMesh, meshFilter.transform, gameObject, progress, ref metaData, ref particleSystems, ref lensFlareSystems, ref componentTags, collisionMesh, collider); continue; } // Skinned meshes var skinnedMesh = gameObject.GetComponent<SkinnedMeshRenderer>(); if (skinnedMesh != null) { var babylonMesh = ConvertUnityMeshToBabylon(skinnedMesh.sharedMesh, skinnedMesh.transform, gameObject, progress, ref metaData, ref particleSystems, ref lensFlareSystems, ref componentTags, collisionMesh, collider); var skeleton = ConvertUnitySkeletonToBabylon(skinnedMesh.bones, skinnedMesh.sharedMesh.bindposes, skinnedMesh.transform, gameObject, progress); babylonMesh.skeletonId = skeleton.id; ExportSkeletonAnimation(skinnedMesh, babylonMesh, skeleton); continue; } // Scene lights var light = gameObject.GetComponent<Light>(); if (light != null) { ConvertUnityLightToBabylon(light, gameObject, progress, ref metaData, ref particleSystems, ref lensFlareSystems, ref componentTags); continue; } // Scene cameras var camera = gameObject.GetComponent<Camera>(); if (camera != null) { ConvertUnityCameraToBabylon(camera, gameObject, progress, ref metaData, ref particleSystems, ref lensFlareSystems, ref componentTags); if (SceneController != null && SceneController.skyboxOptions.exportSkybox) { ConvertUnitySkyboxToBabylon(camera, progress); } continue; } // Empty objects ConvertUnityEmptyObjectToBabylon(gameObject, ref metaData, ref particleSystems, ref lensFlareSystems, ref componentTags, collisionMesh, collider); } // Materials foreach (var mat in materialsDictionary) { babylonScene.MaterialsList.Add(mat.Value); } foreach (var multiMat in multiMatDictionary) { babylonScene.MultiMaterialsList.Add(multiMat.Value); } // Collisions if (exportationOptions.ExportCollisions) { babylonScene.workerCollisions = exportationOptions.WorkerCollisions; if (SceneController != null) { babylonScene.gravity = SceneController.sceneOptions.defaultGravity.ToFloat(); } } // Babylon Physics if (exportationOptions.ExportPhysics) { babylonScene.physicsEnabled = true; if (SceneController != null) { babylonScene.physicsGravity = SceneController.sceneOptions.defaultGravity.ToFloat(); } } // Scene Controller if (SceneController != null) { Color ambientColor = SceneController.sceneOptions.ambientColor; float ambientLevel = SceneController.lightingOptions.lightLevel; Color ambientSpecular = SceneController.lightingOptions.specularColor; babylonScene.autoClear = SceneController.sceneOptions.autoClear; int fogmode = 0; if (RenderSettings.fog) { switch (RenderSettings.fogMode) { case FogMode.Exponential: fogmode = 1; break; case FogMode.ExponentialSquared: fogmode = 2; break; case FogMode.Linear: fogmode = 3; break; } } babylonScene.fogMode = fogmode; babylonScene.fogDensity = RenderSettings.fogDensity; babylonScene.fogColor = RenderSettings.fogColor.ToFloat(); babylonScene.fogStart = RenderSettings.fogStartDistance; babylonScene.fogEnd = RenderSettings.fogEndDistance; if (exportationOptions.DefaultLightmapMode != (int)BabylonLightmapMode.FullLightBaking && SceneController.lightingOptions.lightMode == BabylonAmbientLighting.UnityAmbientLighting) { var ambientLight = new BabylonLight { name = "Ambient Light", id = Guid.NewGuid().ToString(), parentId = null, metadata = null, position = null, exponent = 1.0f, angle = 0.0f, type = 3 }; var ambientDirection = new Vector3(0.0f, 1.0f, 0.0f); Color ambientDiffuse = (RenderSettings.ambientMode == UnityEngine.Rendering.AmbientMode.Skybox) ? RenderSettings.ambientSkyColor : RenderSettings.ambientLight; ambientLight.intensity = RenderSettings.ambientIntensity * ambientLevel; ambientLight.direction = ambientDirection.ToFloat(); ; ambientLight.diffuse = ambientDiffuse.ToFloat(); ambientLight.specular = ambientSpecular.ToFloat(); ambientLight.groundColor = RenderSettings.ambientGroundColor.ToFloat(); babylonScene.ambientColor = ambientColor.ToFloat(); babylonScene.LightsList.Add(ambientLight); ExporterWindow.ReportProgress(0, "Exporting ambient light intensity at: " + ambientLight.intensity.ToString()); } if (SceneController.sceneOptions.navigationMesh == BabylonNavigationMesh.EnableNavigation) { ExporterWindow.ReportProgress(0, "Parsing scene navigation mesh..."); NavMeshTriangulation triangulatedNavMesh = NavMesh.CalculateTriangulation(); if (triangulatedNavMesh.vertices != null && triangulatedNavMesh.vertices.Length > 0 && triangulatedNavMesh.indices != null && triangulatedNavMesh.indices.Length > 0) { int vertexCount = triangulatedNavMesh.vertices.Length; if (vertexCount <= SceneBuilder.MAX_VERTEX_COUNT) { ExporterWindow.ReportProgress(0, "Generating navigation mesh vertices: " + vertexCount.ToString()); var navData = new UnityMetaData(); navData.type = "NavMesh"; navData.objectId = Guid.NewGuid().ToString(); navData.objectName = "Navigation_Mesh"; var areaTable = new List<object>(); string[] areaNavigation = GameObjectUtility.GetNavMeshAreaNames(); foreach (string areaName in areaNavigation) { var bag = new Dictionary<string, object>(); int areaIndex = NavMesh.GetAreaFromName(areaName); float areaCost = NavMesh.GetAreaCost(areaIndex); bag.Add("index", areaIndex); bag.Add("area", areaName); bag.Add("cost", areaCost); areaTable.Add(bag); } navData.properties.Add("table", areaTable); navData.properties.Add("areas", triangulatedNavMesh.areas); Mesh mesh = new Mesh(); mesh.name = "sceneNavigationMesh"; mesh.vertices = triangulatedNavMesh.vertices; mesh.triangles = triangulatedNavMesh.indices; mesh.RecalculateNormals(); BabylonMesh babylonMesh = new BabylonMesh(); babylonMesh.tags = "[NAVMESH]"; babylonMesh.metadata = navData; babylonMesh.name = mesh.name; babylonMesh.id = Guid.NewGuid().ToString(); babylonMesh.parentId = null; babylonMesh.position = Vector3.zero.ToFloat(); babylonMesh.rotation = Vector3.zero.ToFloat(); babylonMesh.scaling = new Vector3(1, 1, 1).ToFloat(); babylonMesh.isVisible = false; babylonMesh.visibility = 0.75f; babylonMesh.checkCollisions = false; Tools.GenerateBabylonMeshData(mesh, babylonMesh); babylonScene.MeshesList.Add(babylonMesh); SceneBuilder.Metadata.properties["hasNavigationMesh"] = true; } else { UnityEngine.Debug.LogError("Navigation mesh exceeds max (65000) vertex limit: " + vertexCount.ToString()); } } } if (SceneController.sceneOptions.particleSystems) { if (particleSystems != null && particleSystems.Count > 0) { babylonScene.particleSystems = particleSystems.ToArray(); } } if (SceneController.sceneOptions.lensFlareSystems) { if (lensFlareSystems != null && lensFlareSystems.Count > 0) { var lfs_buffer = new List<BabylonLensFlareSystem>(); foreach (var ulfs in lensFlareSystems) { var lfs = new BabylonLensFlareSystem(); lfs.borderLimit = ulfs.borderLimit; lfs.emitterId = ulfs.emitterId; var lfx = new List<BabylonLensFlare>(); foreach (var ulf in ulfs.lensFlares) { var lf = new BabylonLensFlare(); lf.textureName = ulf.textureName; lf.position = ulf.position; lf.color = ulf.color; lf.size = ulf.size; lfx.Add(lf); } lfs.flares = lfx.ToArray(); lfs_buffer.Add(lfs); } babylonScene.lensFlareSystems = lfs_buffer.ToArray(); } } } } catch (Exception ex) { Debug.LogException(ex); } finally { babylonScene.metadata = SceneBuilder.Metadata; } }
private void ConvertUnitySkyboxToBabylon(Camera camera, float progress) { // Skybox bool png = (exportationOptions.DefaultImageFormat == (int)BabylonImageFormat.PNG); string fext = (png == true) ? ".png" : ".jpg"; if ((camera.clearFlags & CameraClearFlags.Skybox) == CameraClearFlags.Skybox) { if (RenderSettings.skybox != null) { BabylonTexture skytex = null; if (RenderSettings.skybox.shader.name == "Skybox/Cubemap") { var cubeMap = RenderSettings.skybox.GetTexture("_Tex") as Cubemap; if (cubeMap != null) { var srcTexturePath = AssetDatabase.GetAssetPath(cubeMap); if (srcTexturePath.EndsWith(".hdr", StringComparison.OrdinalIgnoreCase)) { var hdr = new BabylonHDRCubeTexture(); hdr.size = cubeMap.width; skytex = hdr; CopyTextureCube(String.Format("{0}Skybox.hdr", SceneName), cubeMap, skytex, true); } else { skytex = new BabylonTexture(); CopyTextureCube(String.Format("{0}Skybox.hdr", SceneName), cubeMap, skytex, false); if (png) skytex.extensions = new string[] { "_px.png", "_py.png", "_pz.png", "_nx.png", "_ny.png", "_nz.png" }; } } } else if (RenderSettings.skybox.shader.name == "Skybox/6 Sided") { var frontTexture = RenderSettings.skybox.GetTexture("_FrontTex") as Texture2D; var backTexture = RenderSettings.skybox.GetTexture("_BackTex") as Texture2D; var leftTexture = RenderSettings.skybox.GetTexture("_LeftTex") as Texture2D; var rightTexture = RenderSettings.skybox.GetTexture("_RightTex") as Texture2D; var upTexture = RenderSettings.skybox.GetTexture("_UpTex") as Texture2D; var downTexture = RenderSettings.skybox.GetTexture("_DownTex") as Texture2D; if (frontTexture != null && backTexture != null && leftTexture != null && rightTexture != null && upTexture != null && downTexture != null) { skytex = new BabylonTexture(); skytex.name = String.Format("{0}Skybox", SceneName); var frontTextureName = String.Format("{0}_pz{1}", skytex.name, fext); var frontTexturePath = Path.Combine(babylonScene.OutputPath, frontTextureName); CopyTextureFace(frontTexturePath, frontTextureName, frontTexture); var backTextureName = String.Format("{0}_nz{1}", skytex.name, fext); var backTexturePath = Path.Combine(babylonScene.OutputPath, backTextureName); CopyTextureFace(backTexturePath, backTextureName, backTexture); var leftTextureName = String.Format("{0}_px{1}", skytex.name, fext); var leftTexturePath = Path.Combine(babylonScene.OutputPath, leftTextureName); CopyTextureFace(leftTexturePath, leftTextureName, leftTexture); var rightTextureName = String.Format("{0}_nx{1}", skytex.name, fext); var rightTexturePath = Path.Combine(babylonScene.OutputPath, rightTextureName); CopyTextureFace(rightTexturePath, rightTextureName, rightTexture); var upTextureName = String.Format("{0}_py{1}", skytex.name, fext); var upTexturePath = Path.Combine(babylonScene.OutputPath, upTextureName); CopyTextureFace(upTexturePath, upTextureName, upTexture); var downTextureName = String.Format("{0}_ny{1}", skytex.name, fext); var downTexturePath = Path.Combine(babylonScene.OutputPath, downTextureName); CopyTextureFace(downTexturePath, downTexturePath, downTexture); if (png) skytex.extensions = new string[] { "_px.png", "_py.png", "_pz.png", "_nx.png", "_ny.png", "_nz.png" }; } } if (skytex != null) { skytex.isCube = true; skytex.coordinatesMode = 5; skytex.level = (SceneController != null) ? SceneController.skyboxOptions.lightIntensity : 1.0f; var skybox = new BabylonMesh(); skybox.name = "sceneSkyboxMesh"; skybox.id = Guid.NewGuid().ToString(); skybox.indices = new[] { 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23 }; skybox.positions = new[] { 50.0f, -50.0f, 50.0f, -50.0f, -50.0f, 50.0f, -50.0f, 50.0f, 50.0f, 50.0f, 50.0f, 50.0f, 50.0f, 50.0f, -50.0f, -50.0f, 50.0f, -50.0f, -50.0f, -50.0f, -50.0f, 50.0f, -50.0f, -50.0f, 50.0f, 50.0f, -50.0f, 50.0f, -50.0f, -50.0f, 50.0f, -50.0f, 50.0f, 50.0f, 50.0f, 50.0f, -50.0f, 50.0f, 50.0f, -50.0f, -50.0f, 50.0f, -50.0f, -50.0f, -50.0f, -50.0f, 50.0f, -50.0f, -50.0f, 50.0f, 50.0f, -50.0f, 50.0f, -50.0f, 50.0f, 50.0f, -50.0f, 50.0f, 50.0f, 50.0f, 50.0f, -50.0f, 50.0f, 50.0f, -50.0f, -50.0f, -50.0f, -50.0f, -50.0f, -50.0f, -50.0f, 50.0f }; skybox.uvs = new[] { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f }; skybox.normals = new[] { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0, 0f }; if (SceneController != null) { Color skycolor = SceneController.skyboxOptions.albedoColor; Color skyreflect = SceneController.skyboxOptions.reflectivityColor; var skyboxMaterial = new BabylonPBRMaterial() { name = "sceneSkyboxMaterial", id = Guid.NewGuid().ToString(), albedo = skycolor.ToFloat(), reflectivity = skyreflect.ToFloat(), microSurface = SceneController.skyboxOptions.microSurface, cameraContrast = SceneController.skyboxOptions.cameraContrast, cameraExposure = SceneController.skyboxOptions.cameraExposure, directIntensity = SceneController.skyboxOptions.directIntensity, emissiveIntensity = SceneController.skyboxOptions.emissiveIntensity, specularIntensity = SceneController.skyboxOptions.specularIntensity, environmentIntensity = SceneController.skyboxOptions.environmentIntensity }; skyboxMaterial.reflectionTexture = skytex; skyboxMaterial.backFaceCulling = false; skyboxMaterial.disableLighting = true; skybox.materialId = skyboxMaterial.id; skybox.infiniteDistance = true; babylonScene.MeshesList.Add(skybox); babylonScene.MaterialsList.Add(skyboxMaterial); babylonScene.AddTextureCube("sceneSkyboxMaterial"); } } } } }
private BabylonMesh ExportMesh(Node meshNode, BabylonScene babylonScene, CancellationToken token) { var babylonMesh = new BabylonMesh(); int vx1, vx2, vx3; RaiseMessage(meshNode.Name, true); babylonMesh.name = meshNode.Name; babylonMesh.id = meshNode.GetGuid().ToString(); if (meshNode.HasParent()) { babylonMesh.parentId = meshNode.Parent.GetGuid().ToString(); } // Misc. babylonMesh.isVisible = meshNode._Node.Renderable == 1; babylonMesh.pickable = meshNode._Node.GetBoolProperty("babylonjs_checkpickable"); babylonMesh.receiveShadows = meshNode._Node.RcvShadows == 1; babylonMesh.showBoundingBox = meshNode._Node.GetBoolProperty("babylonjs_showboundingbox"); babylonMesh.showSubMeshesBoundingBox = meshNode._Node.GetBoolProperty("babylonjs_showsubmeshesboundingbox"); // Collisions babylonMesh.checkCollisions = meshNode._Node.GetBoolProperty("babylonjs_checkcollisions"); // Position / rotation / scaling var wm = meshNode.GetWorldMatrix(0, meshNode.HasParent()); babylonMesh.position = wm.Trans.ToArraySwitched(); var parts = Loader.Global.AffineParts.Create(); Loader.Global.DecompAffine(wm, parts); //var rotate = new float[3]; //IntPtr xPtr = Marshal.AllocHGlobal(sizeof(float)); //IntPtr yPtr = Marshal.AllocHGlobal(sizeof(float)); //IntPtr zPtr = Marshal.AllocHGlobal(sizeof(float)); //parts.Q.GetEuler(xPtr, yPtr, zPtr); //Marshal.Copy(xPtr, rotate, 0, 1); //Marshal.Copy(yPtr, rotate, 1, 1); //Marshal.Copy(zPtr, rotate, 2, 1); //var temp = -rotate[1]; //rotate[0] = rotate[0] * parts.F; //rotate[1] = -rotate[2] * parts.F; //rotate[2] = temp * parts.F; //babylonMesh.rotation = rotate; babylonMesh.rotationQuaternion = parts.Q.ToArray(); babylonMesh.scaling = parts.K.ToArraySwitched(); if (wm.Parity) { vx1 = 2; vx2 = 1; vx3 = 0; } else { vx1 = 0; vx2 = 1; vx3 = 2; } // Pivot var pivotMatrix = Matrix3.Identity._IMatrix3; pivotMatrix.PreTranslate(meshNode._Node.ObjOffsetPos); Loader.Global.PreRotateMatrix(pivotMatrix, meshNode._Node.ObjOffsetRot); Loader.Global.ApplyScaling(pivotMatrix, meshNode._Node.ObjOffsetScale); babylonMesh.pivotMatrix = pivotMatrix.ToArray(); // Mesh var objectState = meshNode._Node.EvalWorldState(0, false); var mesh = objectState.Obj.GetMesh(); var computedMesh = meshNode.GetMesh(); if (mesh != null) { mesh.BuildNormals(); if (mesh.NumFaces < 1) { RaiseError(string.Format("Mesh {0} has no face", babylonMesh.name)); } if (mesh.NumVerts < 3) { RaiseError(string.Format("Mesh {0} has not enough vertices", babylonMesh.name)); } if (mesh.NumVerts >= 65536) { RaiseError(string.Format("Mesh {0} has too many vertices (more than 65535)", babylonMesh.name)); } // Material var mtl = meshNode.Material; var multiMatsCount = 1; if (mtl != null) { babylonMesh.materialId = mtl.GetGuid().ToString(); if (!referencedMaterials.Contains(mtl)) { referencedMaterials.Add(mtl); } multiMatsCount = Math.Max(mtl.NumSubMaterials, 1); } babylonMesh.visibility = meshNode._Node.GetVisibility(0, Interval.Forever._IInterval); var vertices = new List<GlobalVertex>(); var indices = new List<int>(); var matIDs = new List<int>(); var hasUV = mesh.NumTVerts > 0; var hasUV2 = mesh.GetNumMapVerts(2) > 0; var noOptimize = meshNode._Node.GetBoolProperty("babylonjs_nooptimize"); for (var face = 0; face < mesh.NumFaces; face++) { indices.Add(CreateGlobalVertex(mesh, computedMesh, face, vx1, vertices, hasUV, hasUV2, noOptimize)); indices.Add(CreateGlobalVertex(mesh, computedMesh, face, vx2, vertices, hasUV, hasUV2, noOptimize)); indices.Add(CreateGlobalVertex(mesh, computedMesh, face, vx3, vertices, hasUV, hasUV2, noOptimize)); matIDs.Add(mesh.Faces[face].MatID % multiMatsCount); if (token.IsCancellationRequested) token.ThrowIfCancellationRequested(); } if (vertices.Count >= 65536) { RaiseError(string.Format("Mesh {0} has too many vertices: {1} (limit is 65535)", babylonMesh.name, vertices.Count)); } // Buffers babylonMesh.positions = vertices.SelectMany(v => v.Position.ToArraySwitched()).ToArray(); babylonMesh.normals = vertices.SelectMany(v => v.Normal.ToArraySwitched()).ToArray(); if (hasUV) { babylonMesh.uvs = vertices.SelectMany(v => v.UV.ToArray()).ToArray(); } if (hasUV2) { babylonMesh.uvs2 = vertices.SelectMany(v => v.UV2.ToArray()).ToArray(); } // Submeshes var sortedIndices = new List<int>(); var subMeshes = new List<BabylonSubMesh>(); var indexStart = 0; for (var index = 0; index < multiMatsCount; index++) { var subMesh = new BabylonSubMesh(); var indexCount = 0; var minVertexIndex = int.MaxValue; var maxVertexIndex = int.MinValue; subMesh.indexStart = indexStart; subMesh.materialIndex = index; for (var face = 0; face < matIDs.Count; face++) { if (matIDs[face] == index) { var a = indices[3 * face]; var b = indices[3 * face + 1]; var c = indices[3 * face + 2]; sortedIndices.Add(a); sortedIndices.Add(b); sortedIndices.Add(c); indexCount += 3; if (a < minVertexIndex) { minVertexIndex = a; } if (b < minVertexIndex) { minVertexIndex = b; } if (c < minVertexIndex) { minVertexIndex = c; } if (a > maxVertexIndex) { maxVertexIndex = a; } if (b > maxVertexIndex) { maxVertexIndex = b; } if (c > maxVertexIndex) { maxVertexIndex = c; } } } if (indexCount != 0) { subMesh.indexCount = indexCount; subMesh.verticesStart = minVertexIndex; subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1; indexStart += indexCount; subMeshes.Add(subMesh); } if (token.IsCancellationRequested) token.ThrowIfCancellationRequested(); } babylonMesh.subMeshes = subMeshes.ToArray(); // Buffers - Indices babylonMesh.indices = sortedIndices.ToArray(); } // Animations var animations = new List<BabylonAnimation>(); ExportVector3Animation("position", animations, key => { var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent()); return worldMatrix.Trans.ToArraySwitched(); }); ExportQuaternionAnimation("rotationQuaternion", animations, key => { var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent()); var affineParts = Loader.Global.AffineParts.Create(); Loader.Global.DecompAffine(worldMatrix, affineParts); return affineParts.Q.ToArray(); }); ExportVector3Animation("scaling", animations, key => { var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent()); var affineParts = Loader.Global.AffineParts.Create(); Loader.Global.DecompAffine(worldMatrix, affineParts); return affineParts.K.ToArraySwitched(); }); ExportFloatAnimation("visibility", animations, key => new []{meshNode._Node.GetVisibility(key, Interval.Forever._IInterval)}); babylonMesh.animations = animations.ToArray(); if (meshNode._Node.GetBoolProperty("babylonjs_autoanimate")) { babylonMesh.autoAnimate = true; babylonMesh.autoAnimateFrom = (int)meshNode._Node.GetFloatProperty("babylonjs_autoanimate_from"); babylonMesh.autoAnimateTo = (int)meshNode._Node.GetFloatProperty("babylonjs_autoanimate_to"); babylonMesh.autoAnimateLoop = meshNode._Node.GetBoolProperty("babylonjs_autoanimateloop"); } babylonScene.MeshesList.Add(babylonMesh); return babylonMesh; }