Vector3[] ComputeEdgeRelativePosition(HexagonTypeData types, Hexagon[] neighbours, int faceIndex, float height) { Vector3[] edge = new Vector3[2]; edge[0] = ComputeVertexRelativePosition(types, neighbours, faceIndex, height); edge[1] = ComputeVertexRelativePosition(types, neighbours, (faceIndex + 1) % 6, height); return(edge); }
void GenerateTop(ref Chunk.MeshData meshData, Vector3 coordinateOffset, HexagonTypeData types, Hexagon[] neighbours) { // Get referential vertice. int verticesOffset = meshData.vertices.Count; for (int i = 0; i < positionsLookup.GetLength(0); i++) { Vector3 vertexRelativePosition; if (i != 0 && types[_typeID].SizeMultiplier < 1 - HexagonUtils.FloatEpsilon) { vertexRelativePosition = ComputeVertexRelativePosition(types, neighbours, i - 1, Height); } else { vertexRelativePosition = new Vector3(positionsLookup[i, 0], Height, positionsLookup[i, 1]); } AddVertex(ref meshData, vertexRelativePosition.Mult(Scale) + coordinateOffset, new Vector2(topUVsLookup[i, 0], topUVsLookup[i, 1])); } // triangles for (int i = 0; i < topTrianglesLookup.GetLength(0); i++) { meshData.triangles[types[_typeID].TopMaterialIndex].Add(verticesOffset + topTrianglesLookup[i, 0]); meshData.triangles[types[_typeID].TopMaterialIndex].Add(verticesOffset + topTrianglesLookup[i, 1]); meshData.triangles[types[_typeID].TopMaterialIndex].Add(verticesOffset + topTrianglesLookup[i, 2]); } }
Vector3 ComputeVertexRelativePosition(HexagonTypeData types, Hexagon[] neighbours, int vertexIndex, float height) { bool firstNeighbourVisibility = IsSideVisible(neighbours[(vertexIndex + 5) % 6], types); bool secondNeighbourVisibility = IsSideVisible(neighbours[vertexIndex], types); if (types[_typeID].SizeMultiplier > 1 - HexagonUtils.FloatEpsilon || (!firstNeighbourVisibility && !secondNeighbourVisibility)) { return(new Vector3(positionsLookup[vertexIndex + 1, 0], height, positionsLookup[vertexIndex + 1, 1])); } else if (firstNeighbourVisibility && secondNeighbourVisibility) { return(new Vector3(positionsLookup[vertexIndex + 1, 0] * types[_typeID].SizeMultiplier, height, positionsLookup[vertexIndex + 1, 1] * types[_typeID].SizeMultiplier)); } else if (firstNeighbourVisibility && !secondNeighbourVisibility) { return(new Vector3(neighbourRelativePosition[(vertexIndex + 5) % 6, 0] + positionsLookup[(vertexIndex + 2) % 6 + 1, 0] * (2 - types[_typeID].SizeMultiplier), height, neighbourRelativePosition[(vertexIndex + 5) % 6, 1] + positionsLookup[(vertexIndex + 2) % 6 + 1, 1] * (2 - types[_typeID].SizeMultiplier))); } else if (!firstNeighbourVisibility && secondNeighbourVisibility) { return(new Vector3(neighbourRelativePosition[(vertexIndex + 0) % 6, 0] + positionsLookup[(vertexIndex + 4) % 6 + 1, 0] * (2 - types[_typeID].SizeMultiplier), height, neighbourRelativePosition[(vertexIndex + 0) % 6, 1] + positionsLookup[(vertexIndex + 4) % 6 + 1, 1] * (2 - types[_typeID].SizeMultiplier))); } throw new Exception(); }
void GenerateSide(ref Chunk.MeshData meshData, Vector3 coordinateOffset, int faceIndex, Hexagon[] neighbours, HexagonTypeData types) { float bottomEdgeHeight = Height - types[_typeID].EdgeHeight; if (neighbours[faceIndex] != null && bottomEdgeHeight < neighbours[faceIndex].Height) { // If the bottomEdge go lower than the neighbour hexagon, make them match. //bottomEdgeHeight = neighbours[faceIndex].Height; } // Make Edge if (types[_typeID].EdgeHeight > HexagonUtils.FloatEpsilon || types[_typeID].SizeMultiplier < 1 - HexagonUtils.FloatEpsilon) { Vector3[] topEdgePosition = ComputeEdgeRelativePosition(types, neighbours, faceIndex, Height); Vector3[] bottomEdgePosition = ComputeEdgeRelativePositionBase(faceIndex, bottomEdgeHeight); AddSideQuad(ref meshData, coordinateOffset, topEdgePosition, bottomEdgePosition, types[_typeID].EdgeMaterialIndex, 0f); } // Make Side float baseLevel = neighbours[faceIndex] == null ? -10 : neighbours[faceIndex].Height - types[neighbours[faceIndex].TypeID].EdgeHeight; Vector3[] topSidePosition = ComputeEdgeRelativePositionBase(faceIndex, bottomEdgeHeight); Vector3[] baseEdgePosition = ComputeEdgeRelativePositionBase(faceIndex, baseLevel); // TODO: remove unneeded underneath geometry when a corner don't make the side visible. if (baseLevel < bottomEdgeHeight - HexagonUtils.FloatEpsilon) { AddSideQuad(ref meshData, coordinateOffset, topSidePosition, baseEdgePosition, types[_typeID].SideMaterialIndex, 1 - (bottomEdgeHeight - baseLevel) * types[_typeID].SideLoopFrequency); } }
void OnGUI() { // Create HexTerrainData EditorGUILayout.LabelField("Terrain data"); EditorGUI.indentLevel++; _terrainData = EditorGUILayout.ObjectField("object:", _terrainData, typeof(HexTerrainData), false) as HexTerrainData; if (_terrainData != null) { _terrainName = _terrainData.name; _size = _terrainData.Size; } EditorGUILayout.Separator(); GUI.enabled = _terrainData == null; _terrainName = EditorGUILayout.TextField("name: ", _terrainName); _size = EditorGUILayout.IntField("Size: ", _size); if (GUILayout.Button("Create Terrain data")) { _terrainData = MakeHexTerrainData(_terrainName, _size); } GUI.enabled = true; EditorGUI.indentLevel--; EditorGUILayout.Space(); // Create HexagonTypeData EditorGUILayout.LabelField("Type data"); EditorGUI.indentLevel++; _typeData = EditorGUILayout.ObjectField("object:", _typeData, typeof(HexagonTypeData), false) as HexagonTypeData; if (_typeData != null) { _typeName = _typeData.name; } EditorGUILayout.Separator(); GUI.enabled = _typeData == null; _typeName = EditorGUILayout.TextField("name: ", _typeName); if (GUILayout.Button("Create Type data")) { _typeData = MakeHexType(_typeName); } GUI.enabled = true; EditorGUI.indentLevel--; EditorGUILayout.Space(); // Create Map _gameObjectName = EditorGUILayout.TextField("new gameObject name: ", _gameObjectName); GUI.enabled = _typeData != null && _terrainData != null; if (GUILayout.Button("Instantiate gameObject")) { if (MakeHexTerrain(_gameObjectName, _terrainData, _typeData)) { this.Close(); } } GUI.enabled = true; }
static HexagonTypeData MakeHexType(string name) { HexagonTypeData types = ScriptableObject.CreateInstance <HexagonTypeData>(); AssetDatabase.CreateAsset(types, AssetDatabase.GenerateUniqueAssetPath("Assets/" + name + ".asset")); EditorUtility.FocusProjectWindow(); Selection.activeObject = types; AssetDatabase.SaveAssets(); return(types); }
static bool MakeHexTerrain(string name, HexTerrainData terrainData, HexagonTypeData typeData) { GameObject gameObject = new GameObject(name); HexTerrain hexTerrain = gameObject.AddComponent <HexTerrain>(); hexTerrain.HexData = terrainData; hexTerrain.Types = typeData; hexTerrain.BuildChunks(); return(true); }
/// <summary> /// Add the geometry of this Hexagon inside the MeshData structure of the calling Chunk. /// </summary> /// <param name="meshData">MeshData structure to be filed </param> /// <param name="chunkOffSet">world offset of the parent chunk </param> /// <param name="coordinate">2d grid coordinate of this hexa relative to its chunk </param> /// <param name="neighbours"> Array containing the 6 neighbours of this hex, some can be null</param> public void AddToChunk(ref Chunk.MeshData meshData, Vector3 chunkOffSet, Vector2i coordinate, Hexagon[] neighbours, HexagonTypeData types) { //TODO: compute top vertex position of this hexagon at start to avoid multiple recomputation. // Compute hexagon position. Vector3 coordinateOffset = HexagonUtils.ConvertHexaSpaceToOrthonormal(coordinate) + chunkOffSet; GenerateTop(ref meshData, coordinateOffset, types, neighbours); for (int i = 0; i < 6; i++) { if (IsSideVisible(neighbours[i], types)) { GenerateSide(ref meshData, coordinateOffset, i, neighbours, types); } } }
bool IsSideVisible(Hexagon neighbour, HexagonTypeData types) { return(neighbour == null || neighbour.Height < this.Height - HexagonUtils.FloatEpsilon); }
/// <summary>Constructor used when the asset is first created.</summary> /// <param name="container">HexagonTypeData holding this type.</param> public HexagonType(HexagonTypeData container) { _container = container; }