Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

237 Neutral

About Trigves

  • Rank
  1. Trigves

    Per pixel sprite depth

    Thank you for the quick reply.   Yes, that's what I thought.   But how do I know the ortho depth range of my sprite? I think I'm missing something or simply not getting it it. I would like to see the shader code how it would be done I also want to note that my scene is setup similar as in Pillars Of Eternity, that is the sprites are lay out on XZ plane (Y is up), and 3D objects are moving also on XZ plane. Thank You
  2. Hi, I'm trying to find available methods for using per pixel sprite depth in 3D engine with isometric (ortho) camera.   The Sims 1 used the depth texture for each sprite. That's ok. But how they actually used it? You just can't "blit" it directly do depth buffer, because the sprite depth is in range [0,1] for the given tile. But the camera depth buffer range [0,1] is used for whole camera frustrum. So you must therefor somehow adjust the depth texture so it will have right depth values when being written to depth buffer. What I meas is, if I have a sprite and put it somewhere to the "bottom of the camera" (the nearest place), the depth values should be around 0, but when I place the sprite "near the top" of the camera (that is way from camera) the depth values shoud be around 1. But if I just blindy transfer the depth, in each case the depth values would be same, which is wrong. Or am I completely off? (this is probably the case)   Pillars of Eternity use prerenderd backgroun with height map pass which is used for per pixel sorting. From the forums I found the the map is composed of the world height position of each pixel. But, how can one reconstruct the position only from the height? You will need at least height (y) and z position to reconstruct the each pixel. Or am I missing something? If they used the rendered depth map, then the problem will be same as described earlier. That is if the camera move, the whole depth map need to be adjusted somehow to reflect the movement.   The only solution that works for me is something like Pillars Of Eternity, where for each object I render the Y and Z per pixel values. These values are then used in the fragment shader to reconstruct the pixel position (the X position is taken from the vertex of the sprite) in space and compute the depth. The only problem is that I need to encode the float values to RGB to be able to use them in shader, which is extra step I would rather not to do. And don't know if there could be performance problem.   It is possible that I'm all wrong so please correct me.   I would be grateful for any comment explaining the situation in both games.   Thank You   Trigve
  3. Hi, I'm trying to figure out how to combine 3D character with the 2D isometric tiles.   I'm making the tile based isometric game with the 3D characters and 2D sprites as tiles. I'm using 2:1 isometric projection for the tiles. The engine is Unity.   As first I was thinking to use 2 cameras, one for the all 2D sprites/tiles and other one for the 3D character. I could use some custom depth sorting (writing custom depth/position maps to Z buffer) for sprites and 3D models and in the end combine the 2 outputs. I don't know if it is really feasible to share depth buffer for the 2 cameras and combine the final image based on it.   Another approach would be to use only 1 camera, but rotate it 30 degrees around X (so the player is moving on the XZ plane and to match the sprites) and draw the sprites parallel to the camera (to be pixel perfect). The sorting could be problematic here and also positioning of the sprites. Honestly, I cannot imagine to how it should work.   I've also looked at the shadowrun returns, how they're doing it https://shadowrun-returns.wikispaces.com/How+to+Set+Up+Props . It looks like they're generating the geometry from the sprites somehow (or better term is, projecting it on the 3D box) which are then used alongside the 3D characters. But I would know detail explanation of it.   So what is the best method for combining the 3D characters with 2D isometric sprites?   I'll be greatful for all the relevant suggestions.   Thank You
  4. Here is the old script that I mentioned in the other thread (and was using it). Not the optimal one, just proof of the concept: using UnityEngine; using System.Collections.Generic; using HierarchyDict = System.Collections.Generic.Dictionary<string, UnityEngine.Transform>; using BoneTransformDict = System.Collections.Generic.Dictionary<string, utils.Tuple<UnityEngine.Transform, string>>; namespace utils { public class MeshCombiner { #region Operations //! Combine mesh. /*! \return combined mesh instance. */ public static Mesh Combine(GameObject Object, GameObject NewObject) { // Dummy parent holder GameObject dummy_parent = new GameObject("DummyParent"); // Be sure new object is at same position as reference object, otherwise // combined mesh would be distored NewObject.transform.position = Object.transform.position; // All skin renderers in all children var skin_renderers = Object.GetComponentsInChildren<SkinnedMeshRenderer>(); // All available bones var all_bones = new BoneTransformDict(); // Traverse through all skinned mesh renderers foreach (var renderer in skin_renderers) { var renderer_bones = renderer.bones; foreach (var bone in renderer_bones) { // Bone doesn't exist, add it if (!all_bones.ContainsKey(bone.name)) all_bones[bone.name] = new utils.Tuple<Transform, string>(bone, bone.parent.name); } } var combineInstanceArrays = new Dictionary<Material, List<CombineInstance>>(); var bone_weights = new Dictionary<Mesh, BoneWeight[]>(); // Map between bone name and index var added_bones = new Dictionary<string, int>(); // List of child objects holding the skinned mesh renderers to be // destroyed when finished var child_objects_to_destroy = new List<GameObject>(); int bone_index = 0; foreach (var renderer in skin_renderers) { child_objects_to_destroy.Add(renderer.transform.parent.gameObject); var renderer_bones = renderer.bones; // Add all bones as first and save the indices of them foreach (var bone in renderer_bones) { // Bone not yet added if (!added_bones.ContainsKey(bone.name)) added_bones[bone.name] = bone_index++; } // Adjust bone weights indices based on real indices of bones var bone_weights_list = new BoneWeight[renderer.sharedMesh.boneWeights.Length]; var renderer_bone_weights = renderer.sharedMesh.boneWeights; for (int i = 0; i < renderer_bone_weights.Length; ++i) { BoneWeight current_bone_weight = renderer_bone_weights[i]; current_bone_weight.boneIndex0 = added_bones[renderer_bones[current_bone_weight.boneIndex0].name]; current_bone_weight.boneIndex2 = added_bones[renderer_bones[current_bone_weight.boneIndex2].name]; current_bone_weight.boneIndex3 = added_bones[renderer_bones[current_bone_weight.boneIndex3].name]; current_bone_weight.boneIndex1 = added_bones[renderer_bones[current_bone_weight.boneIndex1].name]; bone_weights_list[i] = current_bone_weight; } bone_weights[renderer.sharedMesh] = bone_weights_list; // Handle bad input if (renderer.sharedMaterials.Length != renderer.sharedMesh.subMeshCount) { Debug.LogError("Mismatch between material count and submesh count. Is this the correct MeshRenderer?"); continue; } // Prepare stuff for mesh combination with same materials for (int i = 0; i < renderer.sharedMesh.subMeshCount; i++) { // Material not in dict, add it if (!combineInstanceArrays.ContainsKey(renderer.sharedMaterials[i])) combineInstanceArrays[renderer.sharedMaterials[i]] = new List<CombineInstance>(); var actual_mat_list = combineInstanceArrays[renderer.sharedMaterials[i]]; // Add new instance var combine_instance = new CombineInstance(); combine_instance.transform = renderer.transform.localToWorldMatrix; combine_instance.subMeshIndex = i; combine_instance.mesh = renderer.sharedMesh; actual_mat_list.Add(combine_instance); } // No need to use it anymore renderer.enabled = false; } var bones_hierarchy = new HierarchyDict(); // Recreate bone structure foreach (var bone in all_bones) { // Bone not processed, process it if (!bones_hierarchy.ContainsKey(bone.Key)) AddParent(bone.Key, bones_hierarchy, all_bones, dummy_parent); } // Create bone array from preprocessed dict var bones = new Transform[added_bones.Count]; foreach (var bone in added_bones) bones[bone.Value] = bones_hierarchy[bone.Key]; // Get the root bone Transform root_bone = bones[0]; while (root_bone.parent != null) { // Get parent if (bones_hierarchy.ContainsKey(root_bone.parent.name)) root_bone = root_bone.parent; else break; } // Create skinned mesh renderer GO GameObject combined_mesh_go = new GameObject("Combined"); combined_mesh_go.transform.parent = NewObject.transform; combined_mesh_go.transform.localPosition = Vector3.zero; // Fill bind poses var bind_poses = new Matrix4x4[bones.Length]; for (int i = 0; i < bones.Length; ++i) bind_poses[i] = bones[i].worldToLocalMatrix * combined_mesh_go.transform.localToWorldMatrix; // Need to move it to new GO root_bone.parent = NewObject.transform; // Combine meshes into one var combined_new_mesh = new Mesh(); var combined_vertices = new List<Vector3>(); var combined_uvs = new List<Vector2>(); var combined_indices = new List<int[]>(); var combined_bone_weights = new List<BoneWeight>(); var combined_materials = new Material[combineInstanceArrays.Count]; var vertex_offset_map = new Dictionary<Mesh, int>(); int vertex_index_offset = 0; int current_material_index = 0; foreach (var combine_instance in combineInstanceArrays) { combined_materials[current_material_index++] = combine_instance.Key; var submesh_indices = new List<int>(); // Process meshes for each material foreach (var combine in combine_instance.Value) { // Update vertex offset for current mesh if (!vertex_offset_map.ContainsKey(combine.mesh)) { // Add vertices for mesh combined_vertices.AddRange(combine.mesh.vertices); // Set uvs combined_uvs.AddRange(combine.mesh.uv); // Add weights combined_bone_weights.AddRange(bone_weights[combine.mesh]); vertex_offset_map[combine.mesh] = vertex_index_offset; vertex_index_offset += combine.mesh.vertexCount; } int vertex_current_offset = vertex_offset_map[combine.mesh]; var indices = combine.mesh.GetTriangles(combine.subMeshIndex); // Need to "shift" indices for (int k = 0; k < indices.Length; ++k) indices[k] += vertex_current_offset; submesh_indices.AddRange(indices); } // Push indices for given submesh combined_indices.Add(submesh_indices.ToArray()); } combined_new_mesh.vertices = combined_vertices.ToArray(); combined_new_mesh.uv = combined_uvs.ToArray(); combined_new_mesh.boneWeights = combined_bone_weights.ToArray(); combined_new_mesh.subMeshCount = combined_materials.Length; for (int i = 0; i < combined_indices.Count; ++i) combined_new_mesh.SetTriangles(combined_indices[i], i); // Create mesh renderer SkinnedMeshRenderer combined_skin_mesh_renderer = combined_mesh_go.AddComponent<SkinnedMeshRenderer>(); combined_skin_mesh_renderer.sharedMesh = combined_new_mesh; combined_skin_mesh_renderer.bones = bones; combined_skin_mesh_renderer.rootBone = root_bone; combined_skin_mesh_renderer.sharedMesh.bindposes = bind_poses; combined_skin_mesh_renderer.sharedMesh.RecalculateNormals(); combined_skin_mesh_renderer.sharedMesh.RecalculateBounds(); combined_skin_mesh_renderer.sharedMaterials = combined_materials; // Destroy children foreach (var child in child_objects_to_destroy) GameObject.DestroyImmediate(child); // Destroy dummy parent GameObject.DestroyImmediate(dummy_parent); return combined_skin_mesh_renderer.sharedMesh; } static void AddParent(string BoneName, HierarchyDict BoneHierarchy, BoneTransformDict AllBones, GameObject DummyParent) { Transform actual_bone = null; // Must be bone if (AllBones.ContainsKey(BoneName)) { var bone_tuple = AllBones[BoneName]; // Add parent recursively if not added if (!BoneHierarchy.ContainsKey(bone_tuple._2)) { AddParent(bone_tuple._2, BoneHierarchy, AllBones, DummyParent); // Unparent all children of parents Unparent(BoneHierarchy[bone_tuple._2], DummyParent); } bone_tuple._1.parent = BoneHierarchy[bone_tuple._2]; actual_bone = bone_tuple._1; } BoneHierarchy[BoneName] = actual_bone; } static void Unparent(Transform Parent, GameObject DummyParent) { if (Parent != null) { var unparent_list = new List<Transform>(); foreach (Transform child in Parent.transform) unparent_list.Add(child); foreach (var child in unparent_list) child.parent = DummyParent.transform; } } #endregion } }
  5. Trigves

    Visual Studio Multiple Builds

    I think you could achieve this with build dependencies.... right click in the solution explorer for the project you want to select dependencies on -> "Build Dependencies" and set the dependencies as you need.
  6. What I've done in the past, was to combine the all the meshes to the single mesh and then use Animator on this mesh.   I've exported all the parts as a solo files. Each of them has the whole skeleton BUT with particular mesh only (head, torso, ...). Then in unity I've written a script that combines all the meshes to the single mesh and used it normally.
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!