protected override void SetScreenUniforms(TerrainNode node, TerrainQuad quad, MaterialPropertyBlock matPropertyBlock) { matPropertyBlock.SetMatrix(uniforms.screenQuadCorners, (localToScreen * quad.DeformedCorners).ToMatrix4x4()); matPropertyBlock.SetMatrix(uniforms.screenQuadVerticals, (localToScreen * quad.DeformedVerticals).ToMatrix4x4()); matPropertyBlock.SetVector(uniforms.screenQuadCornerNorms, quad.Lengths.ToVector4()); matPropertyBlock.SetMatrix(uniforms.tangentFrameToWorld, quad.TangentFrameToWorld.ToMatrix4x4()); }
/// <summary> /// Updates the internal quadtree to make it identical to the given terrain quadtree. /// This method releases the texture tiles corresponding to deleted quads. /// </summary> /// <param name="tree">Internal quadtree.</param> /// <param name="quad">Quad.</param> protected virtual void PutTiles(QuadTree tree, TerrainQuad quad) { if (tree == null) { return; } // Check if this tile is needed, if not put tile. tree.IsNeedTile = NeedTile(quad); if (!tree.IsNeedTile && tree.Tile != null) { Producer.PutTile(tree.Tile); tree.Tile = null; } // If this qiad is a leaf then all children of the tree are not needed if (quad.IsLeaf) { if (!tree.IsLeaf) { tree.RecursiveDeleteChildren(this); } } else if (Producer.HasChildren(quad.Level, quad.Tx, quad.Ty)) { for (byte i = 0; i < 4; ++i) { PutTiles(tree.Children[i], quad.GetChild(i)); } } }
protected override void SetScreenUniforms(TerrainNode node, TerrainQuad quad, Material target) { base.SetScreenUniforms(node, quad, target); target.SetVector(uniforms.screenQuadCornerNorms, quad.Lengths.ToVector4()); target.SetMatrix(uniforms.tangentFrameToWorld, quad.TangentFrameToWorld.ToMatrix4x4()); }
/// <summary> /// Updates the internal quadtree to make it identical to the given terrain quadtree. /// Collects the tasks necessary to create the missing texture tiles, corresponding to newly created quads. /// </summary> /// <param name="parent">Parent quadtree.</param> /// <param name="tree">Internal quadtree.</param> /// <param name="quad">Quad.</param> protected virtual void GetTiles(QuadTree parent, ref QuadTree tree, TerrainQuad quad) { // If tree not created, create a new tree and check if its tile is needed if (tree == null) { tree = new QuadTree(parent); tree.IsNeedTile = NeedTile(quad); } // If this trees tile is needed get a tile and add its task to the schedular if the task is not already done if (tree.IsNeedTile && tree.Tile == null) { tree.Tile = Producer.GetTile(quad.Level, quad.Tx, quad.Ty); if (!tree.Tile.Task.IsDone) { // If task not done schedule task Schedular.Instance.Add(tree.Tile.Task); } } if (!quad.IsLeaf && Producer.HasChildren(quad.Level, quad.Tx, quad.Ty)) { for (byte i = 0; i < 4; ++i) { GetTiles(tree, ref tree.Children[i], quad.GetChild(i)); } } }
private TerrainQuad GetSelectedQuad() { if (quads == null) { return(null); } Vector2 mousePos = Event.current.mousePosition; Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); float bestT = -1.0f; TerrainQuad best = null; foreach (Dictionary <Vector3, TerrainQuad> quadDictionary in quads.Values) { foreach (TerrainQuad quad in quadDictionary.Values) { if (mode == EditMode.Painting && paintingNormal != quad.normal) { continue; } float t = MathHelper3D.RayDistanceForQuad(vertices, tris, ray, quad); if (t > 0.0f && (t < bestT || bestT == -1.0f)) { bestT = t; best = quad; } } } return(best); }
/// <summary> /// A tile is needed for the given terrain quad? /// </summary> /// <param name="quad">Quad.</param> /// <returns>Returns 'True' if a tile is needed for the given terrain quad.</returns> protected virtual bool NeedTile(TerrainQuad quad) { var needTile = StoreLeaf; // If the quad is not a leaf and producer has children and if have been asked not to store parent then dont need tile if (!StoreParent && !quad.IsLeaf && Producer.HasChildren(quad.Level, quad.Tx, quad.Ty)) { needTile = false; } // Check if any of the filters have determined that this tile is not needed foreach (var filter in Filters) { if (filter.DiscardTile(quad)) { needTile = false; break; } } // If this quad is not visilbe and have not been asked to store invisilbe quads dont need tile if (!StoreInvisible && !quad.IsVisible) { needTile = false; } return(needTile); }
public virtual Matrix4x4 CalculateDeformedLocalToTangent(TerrainNode node, TerrainQuad quad) { return((node.DeformedLocalToTangent * new Matrix4x4d(quad.Length, 0.0, quad.Ox - node.LocalCameraPosition.x, 0.0, 0.0, quad.Length, quad.Oy - node.LocalCameraPosition.y, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0)).ToMatrix4x4()); }
private void UpdateTile(TerrainQuad quad, Tile tile) { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; quad.UpdateTile(tile, tileset, 0.0f); terrain.SetTile((int)quad.pos.x, (int)quad.pos.z, tile); }
private void UpdateTile(TerrainQuad quad, OrthoDir dir, Tile tile) { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; quad.UpdateTile(tile, tileset, quad.pos.y); terrain.SetTile((int)quad.pos.x, (int)quad.pos.z, quad.pos.y - 0.5f, dir, tile); }
public virtual Vector4 CalculateDeformedCameraPosition(TerrainNode node, TerrainQuad quad) { return(new Vector4((float)((node.LocalCameraPosition.x - quad.Ox) / quad.Length), (float)((node.LocalCameraPosition.y - quad.Oy) / quad.Length), (float)((node.LocalCameraPosition.z - node.ParentBody.HeightZ) / (quad.Length * (double)node.DistanceFactor)), (float)node.LocalCameraPosition.z)); }
private void AddQuad(Vector3 lowerLeft, Vector3 upperRight, Tile tile, Vector3 pos, Vector3 normal) { TerrainQuad quad = new TerrainQuad(tris, vertices, uvs, lowerLeft, upperRight, tile, tileset, pos, normal); if (!quads.ContainsKey(pos)) { quads[pos] = new Dictionary <Vector3, TerrainQuad>(); } quads[pos][normal] = quad; }
protected virtual void SetScreenUniforms(TerrainNode node, TerrainQuad quad, MaterialPropertyBlock matPropertyBlock) { var p0 = new Vector3d(quad.Ox, quad.Oy, 0.0); var p1 = new Vector3d(quad.Ox + quad.Length, quad.Oy, 0.0); var p2 = new Vector3d(quad.Ox, quad.Oy + quad.Length, 0.0); var p3 = new Vector3d(quad.Ox + quad.Length, quad.Oy + quad.Length, 0.0); matPropertyBlock.SetMatrix(uniforms.screenQuadCorners, (localToScreen * new Matrix4x4d(p0.x, p1.x, p2.x, p3.x, p0.y, p1.y, p2.y, p3.y, p0.z, p1.z, p2.z, p3.z, 1.0, 1.0, 1.0, 1.0)).ToMatrix4x4()); matPropertyBlock.SetMatrix(uniforms.screenQuadVerticals, (localToScreen * new Matrix4x4d(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0)).ToMatrix4x4()); }
private void AddQuad(MeshGenerationResult result, Vector3 lowerLeft, Vector3 upperRight, Tile tile, Vector3 pos, Vector3 normal) { TerrainQuad quad = new TerrainQuad(result.tris, result.vertices, result.uvs, lowerLeft, upperRight, tile, tileset, pos, normal); if (!result.quads.ContainsKey(pos)) { result.quads[pos] = new Dictionary <Vector3, TerrainQuad>(); } result.quads[pos][normal] = quad; }
public static float GetHeightAtMouse(TerrainQuad relativeToQuad) { //Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); //Vector3 midpoint = relativeToQuad.pos + new Vector3(0.5f, 0.0f, 0.5f); //Plane plane = new Plane(-1.0f * Camera.current.transform.forward, midpoint); //plane.Raycast(ray, out float enter); //Vector3 hit = ray.GetPoint(enter); //float height = Mathf.Round(hit.y * 2.0f) / 2.0f; //return height > 0 ? height : 0; return(0.0f); }
private void PaintTileIfNeeded() { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; foreach (TerrainQuad quad in selectedQuads) { if (quad.normal.y > 0.0f) { int originX = (int)primarySelection.pos.x - Mathf.FloorToInt(Mathf.RoundToInt(selectionSize.x) / 2.0f); int originY = (int)primarySelection.pos.z - Mathf.FloorToInt(Mathf.RoundToInt(selectionSize.y) / 2.0f); Tile tile = TileForSelection((int)(quad.pos.x - originX), (int)(quad.pos.z - originY)); UpdateTile(quad, tile); } else { Tile tile; if (quad.normal.x != 0.0f) { int originX = (int)primarySelection.pos.z - Mathf.FloorToInt(Mathf.RoundToInt(selectionSize.x) / 2.0f); int originY = (int)primarySelection.pos.y - Mathf.FloorToInt(Mathf.RoundToInt(selectionSize.y) / 2.0f); tile = TileForSelection((int)(quad.pos.z - originX), (int)(quad.pos.y - originY)); } else { int originX = (int)primarySelection.pos.x - Mathf.FloorToInt(Mathf.RoundToInt(selectionSize.x) / 2.0f); int originY = (int)primarySelection.pos.y - Mathf.FloorToInt(Mathf.RoundToInt(selectionSize.y) / 2.0f); tile = TileForSelection((int)(quad.pos.x - originX), (int)(quad.pos.y - originY)); } if (wraparoundPaintMode) { foreach (OrthoDir dir in Enum.GetValues(typeof(OrthoDir))) { UpdateTile(quad, dir, tile); } } else { UpdateTile(quad, OrthoDirExtensions.DirectionOf3D(quad.normal), tile); } } } RepaintMesh(); primarySelection = GetSelectedQuad(); CaptureSelection(primarySelection); PrefabStage prefabStage = PrefabStageUtility.GetPrefabStage(terrain.gameObject); if (prefabStage != null) { EditorSceneManager.MarkSceneDirty(prefabStage.scene); } }
public virtual void SetUniforms(TerrainNode node, TerrainQuad quad, Material target) { if (target == null || node == null || quad == null) { return; } target.SetVector(uniforms.offset, CalculateDeformedOffset(quad)); target.SetVector(uniforms.camera, CalculateDeformedCameraPosition(node, quad)); target.SetMatrix(uniforms.tileToTangent, CalculateDeformedLocalToTangent(node, quad)); SetScreenUniforms(node, quad, target); }
private bool FindDrawableSamplers(TerrainQuad quad, List <TileSampler> samplers) { for (short i = 0; i < samplers.Count; ++i) { var producer = samplers[i].Producer; if (producer.HasTile(quad.Level, quad.Tx, quad.Ty) && producer.FindTile(quad.Level, quad.Tx, quad.Ty, false, true) == null) { return(true); } } return(false); }
public static List <TerrainQuad> GetQuadsAroundQuad(Dictionary <Vector3, Dictionary <Vector3, TerrainQuad> > quads, TerrainQuad quad, Vector2 selectionSize) { List <TerrainQuad> selectedQuads = new List <TerrainQuad>(); if (quad == null) { return(selectedQuads); } int dx = Mathf.RoundToInt(selectionSize.x); int dy = Mathf.RoundToInt(selectionSize.y); int lowX = -1 * Mathf.CeilToInt(dx / 2.0f) + 1; int lowY = -1 * Mathf.CeilToInt(dy / 2.0f) + 1; int highX = Mathf.FloorToInt(dx / 2.0f); int highY = Mathf.FloorToInt(dy / 2.0f); for (int i = lowY; i <= highY; i += 1) { for (int j = lowX; j <= highX; j += 1) { Vector3 newPos = quad.pos; if (quad.normal.x != 0) { newPos = new Vector3( quad.pos.x, quad.pos.y + i * 0.5f, quad.pos.z + j); } else if (quad.normal.y != 0) { newPos = new Vector3( quad.pos.x + j, quad.pos.y, quad.pos.z + i); } else if (quad.normal.z != 0) { newPos = new Vector3( quad.pos.x + j, quad.pos.y + i * 0.5f, quad.pos.z); } if (quads.ContainsKey(newPos) && quads[newPos].ContainsKey(quad.normal)) { selectedQuads.Add(quads[newPos][quad.normal]); } } } return(selectedQuads); }
/// <summary> /// Override the default <see cref="TileSampler"/>'s <see cref="TileSampler.NeedTile"/> to retrive the tile, /// that is below the camera as well as it's default behaviour. /// </summary> /// <param name="quad">Quad.</param> /// <returns>Return 'True' if needs tile.</returns> protected override bool NeedTile(TerrainQuad quad) { var localCameraPosition = quad.Owner.LocalCameraPosition; var l = quad.Level; var ox = quad.Ox; var oy = quad.Oy; if (localCameraPosition.x >= ox && localCameraPosition.x < ox + l && localCameraPosition.y >= oy && localCameraPosition.y < oy + l) { return(true); } return(base.NeedTile(quad)); }
/// <summary> /// Init special <see cref="TileProducer"/> uniforms for target <see cref="TerrainQuad"/>. /// </summary> /// <param name="target">Target <see cref="MaterialPropertyBlock"/>.</param> /// <param name="quad">Target quad.</param> public void InitUniforms(MaterialPropertyBlock target, TerrainQuad quad) { if (target == null) { return; } if (quad == null) { return; } if (!Producer.IsGPUProducer) { return; } }
protected override void SetScreenUniforms(TerrainNode node, TerrainQuad quad, MaterialPropertyBlock matPropertyBlock) { var ox = quad.Ox; var oy = quad.Oy; var l = quad.Length; var p0 = new Vector3d(ox, oy, R); var p1 = new Vector3d(ox + l, oy, R); var p2 = new Vector3d(ox, oy + l, R); var p3 = new Vector3d(ox + l, oy + l, R); var pc = (p0 + p3) * 0.5; double l0 = 0.0, l1 = 0.0, l2 = 0.0, l3 = 0.0; var v0 = p0.Normalized(ref l0); var v1 = p1.Normalized(ref l1); var v2 = p2.Normalized(ref l2); var v3 = p3.Normalized(ref l3); Matrix4x4d deformedCorners = new Matrix4x4d(v0.x * R, v1.x * R, v2.x * R, v3.x * R, v0.y * R, v1.y * R, v2.y * R, v3.y * R, v0.z * R, v1.z * R, v2.z * R, v3.z * R, 1.0, 1.0, 1.0, 1.0); Matrix4x4d deformedVerticals = new Matrix4x4d(v0.x, v1.x, v2.x, v3.x, v0.y, v1.y, v2.y, v3.y, v0.z, v1.z, v2.z, v3.z, 0.0, 0.0, 0.0, 0.0); var uz = pc.Normalized(); var ux = (new Vector3d(0, 1, 0)).Cross(uz).Normalized(); var uy = uz.Cross(ux); var ltow = node.LocalToWorld; Matrix3x3d tangentFrameToWorld = new Matrix3x3d(ltow.m[0, 0], ltow.m[0, 1], ltow.m[0, 2], ltow.m[1, 0], ltow.m[1, 1], ltow.m[1, 2], ltow.m[2, 0], ltow.m[2, 1], ltow.m[2, 2]); Matrix3x3d m = new Matrix3x3d(ux.x, uy.x, uz.x, ux.y, uy.y, uz.y, ux.z, uy.z, uz.z); matPropertyBlock.SetMatrix(uniforms.screenQuadCorners, (localToScreen * deformedCorners).ToMatrix4x4()); matPropertyBlock.SetMatrix(uniforms.screenQuadVerticals, (localToScreen * deformedVerticals).ToMatrix4x4()); matPropertyBlock.SetVector(uniforms.screenQuadCornerNorms, new Vector4((float)l0, (float)l1, (float)l2, (float)l3)); matPropertyBlock.SetMatrix(uniforms.tangentFrameToWorld, (tangentFrameToWorld * m).ToMatrix4x4()); }
// assume that q1/q2 share a normal public static List <TerrainQuad> GetQuadsInRect(Dictionary <Vector3, Dictionary <Vector3, TerrainQuad> > quads, TerrainQuad q1, TerrainQuad q2) { List <TerrainQuad> selectedQuads = new List <TerrainQuad>(); for (float x = Mathf.Min(q1.pos.x, q2.pos.x); x <= Math.Max(q1.pos.x, q2.pos.x); x += 1) { for (float z = Mathf.Min(q1.pos.z, q2.pos.z); z <= Math.Max(q1.pos.z, q2.pos.z); z += 1) { for (float y = Mathf.Min(q1.pos.y, q2.pos.y); y <= Math.Max(q1.pos.y, q2.pos.y); y += 0.5f) { selectedQuads.Add(quads[new Vector3(x, y, z)][q1.normal]); } } } return(selectedQuads); }
protected virtual void SetScreenUniforms(TerrainNode node, TerrainQuad quad, MaterialPropertyBlock matPropertyBlock) { var ox = quad.Ox; var oy = quad.Oy; var l = quad.Length; var p0 = new Vector3d(ox, oy, 0.0); var p1 = new Vector3d(ox + l, oy, 0.0); var p2 = new Vector3d(ox, oy + l, 0.0); var p3 = new Vector3d(ox + l, oy + l, 0.0); var corners = new Matrix4x4d(p0.x, p1.x, p2.x, p3.x, p0.y, p1.y, p2.y, p3.y, p0.z, p1.z, p2.z, p3.z, 1.0, 1.0, 1.0, 1.0); var verticals = new Matrix4x4d(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0); matPropertyBlock.SetMatrix(uniforms.screenQuadCorners, (localToScreen * corners).ToMatrix4x4()); matPropertyBlock.SetMatrix(uniforms.screenQuadVerticals, (localToScreen * verticals).ToMatrix4x4()); }
public void OnSceneGUI() { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; if (quads == null) { Rebuild(false); } int controlId = GUIUtility.GetControlID(FocusType.Passive); EventType typeForControl = Event.current.GetTypeForControl(controlId); switch (Event.current.button) { case 0: HandleLeftclick(typeForControl, controlId); break; case 1: HandleRightclick(typeForControl, controlId); break; } TerrainQuad quad = GetSelectedQuad(); switch (typeForControl) { case EventType.MouseMove: switch (mode) { case EditMode.None: case EditMode.Painting: if (quad != primarySelection) { CaptureSelection(quad); primarySelection = quad; SceneView.RepaintAll(); } break; } break; } MathHelper3D.DrawQuads(selectedQuads, Color.white); }
public virtual void SetUniforms(TerrainNode node, TerrainQuad quad, MaterialPropertyBlock matPropertyBlock) { if (matPropertyBlock == null || node == null || quad == null) { return; } matPropertyBlock.SetVector(uniforms.offset, new Vector4((float)quad.Ox, (float)quad.Oy, (float)quad.Length, (float)quad.Level)); matPropertyBlock.SetVector(uniforms.camera, new Vector4((float)((node.LocalCameraPosition.x - quad.Ox) / quad.Length), (float)((node.LocalCameraPosition.y - quad.Oy) / quad.Length), (float)((node.LocalCameraPosition.z - node.ParentBody.HeightZ) / (quad.Length * (double)node.DistanceFactor)), (float)node.LocalCameraPosition.z)); matPropertyBlock.SetMatrix(uniforms.tileToTangent, (localToTangent * new Matrix3x3d(quad.Length, 0.0, quad.Ox - node.LocalCameraPosition.x, 0.0, quad.Length, quad.Oy - node.LocalCameraPosition.y, 0.0, 0.0, 1.0)).ToMatrix4x4()); SetScreenUniforms(node, quad, matPropertyBlock); }
protected override void GetTiles(QuadTree parent, ref QuadTree tree, TerrainQuad quad) { if (tree == null) { tree = new QuadTreeZ(parent, quad); tree.IsNeedTile = NeedTile(quad); } var treeZ = tree as QuadTreeZ; if (treeZ == null) { Debug.LogError("TileSamplerZ.GetTiles: Can't get provided tree as QuadTreeZ!"); base.GetTiles(parent, ref tree, quad); return; } // If tile needs elevation data read back add to container if (treeZ.Tile != null && treeZ.Tile.Task.IsDone && !treeZ.ReadBack && MaxReadBacksPerFrame > 0) { if (!NeedsReadBackDictionary.ContainsKey(treeZ.Tile.ID)) { treeZ.ReadBack = true; NeedsReadBackDictionary.Add(treeZ.Tile.ID, treeZ); } } base.GetTiles(parent, ref tree, quad); // Check if this TerrainQuad is below the camera. If so store a reference to it. if (CameraQuad == null && treeZ.Tile != null && treeZ.Tile.Task.IsDone) { var cameraPosition = quad.Owner.LocalCameraPosition; var l = quad.Length; var ox = quad.Ox; var oy = quad.Oy; if (cameraPosition.x >= ox && cameraPosition.x < ox + l && cameraPosition.y >= oy && cameraPosition.y < oy + l) { CameraQuadCoordinates = new Vector2((float)((cameraPosition.x - ox) / l), (float)((cameraPosition.y - oy) / l)); CameraQuad = treeZ; } } }
private void FindDrawableQuads(TerrainQuad quad, List <TileSampler> samplers) { quad.Drawable = false; if (!quad.IsVisible) { quad.Drawable = true; return; } if (quad.IsLeaf) { if (FindDrawableSamplers(quad, samplers)) { return; } } else { byte drawableCount = 0; for (byte i = 0; i < 4; ++i) { FindDrawableQuads(quad.GetChild(i), samplers); if (quad.GetChild(i).Drawable) { ++drawableCount; } } if (drawableCount < 4) { if (FindDrawableSamplers(quad, samplers)) { return; } } } quad.Drawable = true; }
/// <summary> /// Set special <see cref="TileProducer"/> uniforms for target <see cref="TerrainQuad"/>. /// </summary> /// <param name="target">Target <see cref="MaterialPropertyBlock"/>.</param> /// <param name="quad">Target quad.</param> public void SetUniforms(MaterialPropertyBlock target, TerrainQuad quad) { if (target == null) { return; } if (quad == null) { return; } if (!Producer.IsGPUProducer) { return; } CalculateTileGPUCoordinates(ref SamplerTextureBuffer, ref SamplerCoordsBuffer, ref SamplerSizeBuffer, quad.Level, quad.Tx, quad.Ty); target.SetTexture(uniforms.tile, SamplerTextureBuffer); target.SetVector(uniforms.tileCoords, SamplerCoordsBuffer); target.SetVector(uniforms.tileSize, SamplerSizeBuffer); }
public virtual void SetUniforms(TerrainNode node, TerrainQuad quad, MaterialPropertyBlock matPropertyBlock) { if (matPropertyBlock == null || node == null || quad == null) { return; } var ox = quad.Ox; var oy = quad.Oy; var l = quad.Length; var distFactor = (double)node.DistanceFactor; var level = quad.Level; var camera = node.LocalCameraPosition; var tileToTangent = localToTangent * (new Matrix3x3d(l, 0.0, ox - camera.x, 0.0, l, oy - camera.y, 0.0, 0.0, 1.0)); matPropertyBlock.SetVector(uniforms.offset, new Vector4((float)ox, (float)oy, (float)l, (float)level)); matPropertyBlock.SetVector(uniforms.camera, new Vector4((float)((camera.x - ox) / l), (float)((camera.y - oy) / l), (float)((camera.z - node.Body.HeightZ) / (l * distFactor)), (float)camera.z)); matPropertyBlock.SetMatrix(uniforms.tileToTangent, tileToTangent.ToMatrix4x4()); SetScreenUniforms(node, quad, matPropertyBlock); }
protected override void SetScreenUniforms(TerrainNode node, TerrainQuad quad, Material target) { base.SetScreenUniforms(node, quad, target); }