- Home /
How to cut a hole in a wall?
Hello,
I have generated procedural buildings and there is still one issue left that I couldn't solve up to this day. I don't know how to cut holes into walls so that I can place the windows there.
I tried using stencil shaders, but I couldn't manage to get realistic results...
I will attach a image below to make my question more clear.
As a final mention, please keep in mind that I used a layer-based approach for creating the buildings:
I start from a simple cube - first layer
Then I add the facades: front, back, left, right, top and bottom - second layer
Each facade is vertically divided into a random number of floors - third layer
Each individual floor is horizontally divided into window areas - fourth layer
Into each window area a window is placed - fifth layer
Any help is appreciated!
Thank you in advance.
Why do you want to cut holes into existing walls? If you are generating them procedurally, why not just create the meshes with holes already in them? Trying to do this afterwards is possible but very complicated because you first have to find out how to get the right vertex and triangles indices... A nightmare if I might say so.
Answer by aldonaletto · Jun 20, 2017 at 04:53 AM
I would create a few meshes to work as building blocks: one mesh covering the area of one level with a window, another similar mesh with a door, another mesh for the same area without door or window (the lateral walls) and combine the meshes together in order to make a building.
You could use Mesh.CombineMeshes in order to combine any number of meshes in a building, or generate the meshes on the fly.
EDITED: I've added a simple script that creates a 1x1 mesh with a window, and also the code for blind walls and walls with a door.
The window is a hole, so it will show anything behind it - but remember that a mesh is invisible when seen from inside, thus you'll see whatever is behind the building, not a dark interior. You can put a black cube inside the building and set its size just a little smaller, so that you'll see it through the windows and doors. An alternative is to close the windows and doors with the last two triangles, which are commented out in this script. Attach this script to an empty game object and run: it generates the mesh and adds the necessary MeshFilter and MeshRenderer components, so that the wall magically appears.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WindowMesh : MonoBehaviour {
public Material material;
Vector3[] verts = {
new Vector3(-0.5f, 0.5f, 0.0f), new Vector3( 0.5f, 0.5f, 0.0f),
new Vector3( 0.5f,-0.5f, 0.0f), new Vector3(-0.5f,-0.5f, 0.0f),
new Vector3(-0.2f, 0.3f, 0.0f), new Vector3( 0.2f, 0.3f, 0.0f),
new Vector3( 0.2f,-0.1f, 0.0f), new Vector3(-0.2f,-0.1f, 0.0f),
new Vector3(-0.2f, 0.3f, 0.0f), new Vector3( 0.2f, 0.3f, 0.0f),
new Vector3( 0.2f,-0.1f, 0.0f), new Vector3(-0.2f,-0.1f, 0.0f),
new Vector3(-0.2f, 0.3f, 0.1f), new Vector3( 0.2f, 0.3f, 0.1f),
new Vector3( 0.2f,-0.1f, 0.1f), new Vector3(-0.2f,-0.1f, 0.1f),
new Vector3(-0.2f, 0.3f, 0.1f), new Vector3( 0.2f, 0.3f, 0.1f),
new Vector3( 0.2f,-0.1f, 0.1f), new Vector3(-0.2f,-0.1f, 0.1f)
};
int[] tris = {
0,1,4, 1,5,4, 1,2,5, 2,6,5,
2,3,6, 3,7,6, 3,0,7, 0,4,7,
8,9,12, 9,13,12, 9,10,13, 10,14,13,
10,11,14, 11,15,14, 11,8,15, 8,12,15
//, 16,17,19, 17,18,19 // uncomment this line in order to close the window
};
void Start () {
MeshFilter mF = gameObject.AddComponent<MeshFilter> (); // as MeshFilter;
MeshRenderer render = gameObject.AddComponent<MeshRenderer> () as MeshRenderer;
render.material = material;
Mesh msh = new Mesh ();
msh.vertices = verts;
msh.triangles = tris;
msh.RecalculateNormals ();
mF.mesh = msh;
}
void Update () {
}
}
The door mesh is a little simpler, with two less triangles - just replace both arrays with the ones below:
Vector3[] verts = {
new Vector3(-0.5f, 0.5f, 0.0f), new Vector3( 0.5f, 0.5f, 0.0f),
new Vector3( 0.5f,-0.5f, 0.0f), new Vector3(-0.5f,-0.5f, 0.0f),
new Vector3(-0.2f, 0.3f, 0.0f), new Vector3( 0.2f, 0.3f, 0.0f),
new Vector3( 0.2f,-0.5f, 0.0f), new Vector3(-0.2f,-0.5f, 0.0f),
new Vector3(-0.2f, 0.3f, 0.0f), new Vector3( 0.2f, 0.3f, 0.0f),
new Vector3( 0.2f,-0.5f, 0.0f), new Vector3(-0.2f,-0.5f, 0.0f),
new Vector3(-0.2f, 0.3f, 0.1f), new Vector3( 0.2f, 0.3f, 0.1f),
new Vector3( 0.2f,-0.5f, 0.1f), new Vector3(-0.2f,-0.5f, 0.1f),
new Vector3(-0.2f, 0.3f, 0.1f), new Vector3( 0.2f, 0.3f, 0.1f),
new Vector3( 0.2f,-0.5f, 0.1f), new Vector3(-0.2f,-0.5f, 0.1f)
};
int[] tris = {
0,1,4, 1,5,4, 1,2,5, 2,6,5,
3,0,7, 0,4,7, // <- two triangles less in the door mesh
8,9,12, 9,13,12, 9,10,13, 10,14,13,
10,11,14, 11,15,14, 11,8,15, 8,12,15
//,16,17,19, 17,18,19 // <- these triangles close the door
};
A blind wall is even simpler, only two triangles and five vertices (the 5th vertex is there just to fool Unity and add a "ghost" thickness 0.1, just like the other elements) :
Vector3[] verts = {
new Vector3(-0.5f, 0.5f, 0.0f), new Vector3( 0.5f, 0.5f, 0.0f),
new Vector3( 0.5f,-0.5f, 0.0f), new Vector3(-0.5f,-0.5f, 0.0f),
new Vector3( 0.0f, 0.0f, 0.1f)
};
int[] tris = {
0,1,3, 1,2,3
};
OBS: The 5th vertex can be simply deleted - the pseudo thickness it adds to the wall only makes difference in some cases, like when procedurally adding a box collider to the object.
What are you asking?!? You create meshes in a 3d modelling application or via code, either way you can freely decide how it looks.
Do you mean true holes or depressions in the mesh? Both are easy to make in 3D editing software, but you can as well generate a mesh on-the-fly, defining arrays of triangles, vertices, uv and normals and assigning them to a $$anonymous$$esh. A single wall with one window would require 18 triangles and 20 vertices (12 for the main vertices, and 8 more in order to define different normals at the window corners). I'll edit my answer later and include an example.
You're a lifesaver. This might be exactly what I needed. Thank you so much!
Answer by sparkzbarca · Jun 20, 2017 at 03:06 AM
are you certain they did cut the holes? It's quite possible (though hard to tell with that resolution) that they simply actually really did make the complex geography of hole cut walls in modelling software, baked the lighting and everything to make a texture and because they baked a resolution version they got a texture that appears 3D but is in fact a 2d image designed to appear 3D.
But you might look at the code for stuff like minecraft. I BELIEVE the way they created procedural holes is using whats basically subtractive stuff. That is with minecraft they start with a 1k by 1k block of cubes and subtract cubes to create shapes.
likewise, you'd want to do that. your going to start from not one block but tons of tiny ones. With modern processors and occlusion culling (the processor not worrying about things you can't see) as minecraft shows you really can have a stupid amount of these simple blocks in a scene.
so in your first image, imagine the grey windows as actually 4 blocks in a square, material glass. Between them top and bottom is a single block, material brick. on each side is a 1x2 section of brick.
Now you can see how by make this wall two deep as it were so you actually intially have 4 blocks in a square for windows but with a depth of two. You can remove the first layer and now you have a layer of brick with a hole and behind it bricks with glass.
This is the AS I UNDERSTAND IT generally accepted method for doing this sort of thing. Through subtraction not addition.
I also tried using voxels, but from what I heard, they aren't the best choice when it comes to generating large scenes. In this case, my final goal is to create a city with 100 buildings let's say. Is it possible to have so many cubes in a scene or would it be some kind of overkill?
Your answer
Follow this Question
Related Questions
GPU performance with tris and verts 1 Answer
Creating a convex MESH (not collider) 2 Answers
Vertex Colors not smooth enough? 0 Answers
C# Proceducal Mesh terrain 2 Answers
How to achieve Assasins Creed fragmented shader effect? 0 Answers