I'm trying to make a chess game in Augmented Reality. I wrote a script which places chessboard on the Plane in AR. Then I created mesh with 64 squares which match chessboard tiles. I have a problem placing mesh to match my chessboard(screenshots). I think I should rotate mesh by Y axis, but I wasn't able to do that.
placing chessboard:
GameObject placedObject = Instantiate(objectToPlace, placementPose.position, placementPose.rotation * Quaternion.Euler(-90f, 0f, 0f));
script that creates and places mesh:
private float yAdjust = 0F;
private Vector3 boardCenter = GameObject.Find("Interaction").GetComponent<TapToPlaceObject>().placementPose.position;
private void GenerateSquares(float squareSize)
{
adjust = new Vector3(-4 * squareSize, 0, -4 * squareSize) + boardCenter;
squares = new GameObject[8,8];
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
squares[i, j] = CreateSquare(squareSize,i,j);
}
}
}
private GameObject CreateSquare(float squareSize, int i, int j)
{
GameObject square = new GameObject(string.Format("{0},{1}", i, j));
square.transform.parent = transform;
Vector3[] vertices = new Vector3[4];
vertices[0] = new Vector3(i * squareSize, yAdjust, j * squareSize) + adjust;
vertices[1] = new Vector3(i * squareSize, yAdjust, (j + 1) * squareSize) + adjust;
vertices[2] = new Vector3((i + 1) * squareSize, yAdjust, j * squareSize) + adjust;
vertices[3] = new Vector3((i + 1) * squareSize, yAdjust, (j + 1) * squareSize) + adjust;
int[] triangles = new int[] { 0, 1, 2, 1, 3, 2 };
Mesh mesh = new Mesh();
square.AddComponent<MeshFilter>().mesh = mesh;
square.AddComponent<MeshRenderer>().material = squareMaterial;
//square.transform.rotation = Quaternion.Euler(new Vector3(0, boardRotation.eulerAngles.y, 0));
//square.transform.rotation = boardRotation;
mesh.vertices = vertices;
mesh.triangles = triangles;
square.AddComponent<BoxCollider>();
return square;
}
screenshot of my problem
You could probably try and just add another
* Quaternion.Euler(0f, 45f, 0f)
In general though for your squares there is Transform.SetParent which allows you to pass the optional parameter worldPositionStays as false which is probably what you would want to do. By setting
transform.parent = parent
equals calling
transform.SetParent(parent);
which equals calling
transform.SetParent(parent, true);
so the objects keep their original world space orientation and position.
However, I would actually rather recommend you already create that board once in edit mode, make the entire board a prefab and now when you spawn the board you only need to take care of placing and rotating one single object and all children will already be their correctly placed and rotated within the board.
Related
I use the following code to generate a Cube as a single mesh. My purpose is to generate a sphere from it by normalizing as I have shown in the commented line (I just have to do that to all those statements in the following lines). The problem here is that the mesh changes from a cube to a flat plane as I keep increasing the resolution (parameter given as public int resolution).
(This code was inspired by this video https://youtu.be/QN39W020LqU . But I am using the technique in my own way as given by the following code, so that I can generate a single mesh instead of a combination of 6 meshes, this is required for my work)
[code=CSharp]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Sc_Planet : MonoBehaviour
{
[Range(2, 512)]
public int resolution = 2;
[Range(2, 256)]
public int radius = 10;
MeshFilter meshFilter;
void OnValidate()
{
Initialize();
}
void Initialize()
{
if (meshFilter == null)
{
GameObject meshObj = new GameObject("mesh_Planet");
meshObj.transform.parent = transform;
meshObj.AddComponent<MeshRenderer>().sharedMaterial = new Material(Shader.Find("Standard"));
meshFilter = meshObj.AddComponent<MeshFilter>();
meshFilter.sharedMesh = new Mesh();
}
int xmax = resolution + 1;
int ymax = resolution + 1;
float dx = 1.0f / resolution;
float dy = 1.0f / resolution;
Vector3[] vertsTop = new Vector3[xmax * ymax];
Vector3[] vertsRight = new Vector3[xmax * ymax];
Vector3[] vertsFront = new Vector3[xmax * ymax];
Vector3[] vertsBottom = new Vector3[xmax * ymax];
Vector3[] vertsLeft = new Vector3[xmax * ymax];
Vector3[] vertsBack = new Vector3[xmax * ymax];
for (int y = 0; y < ymax; y++)
{
for (int x = 0; x < xmax; x++)
{
float px = dx * x - 0.5f;
float py = dy * y - 0.5f;
int t = x + y * xmax;
//vertsTop[t] = new Vector3(py, 0.5f, px).normalized * radius;
vertsTop[t] = new Vector3(py, 0.5f, px);
vertsRight[t] = new Vector3(px, py, 0.5f);
vertsFront[t] = new Vector3(0.5f, px, py);
vertsBottom[t] = new Vector3(px, -0.5f, py);
vertsLeft[t] = new Vector3(py, px, -0.5f);
vertsBack[t] = new Vector3(-0.5f, py, px);
}
}
List<int> trianglesList = new List<int>();
for (int y = 0; y < ymax - 1; ++y)
{
for (int x = 0; x < xmax; ++x)
{
if (x % xmax != xmax - 1)
{
int f = x + y * xmax;
trianglesList.Add(f);
trianglesList.Add(f + 1);
trianglesList.Add(f + 1 + xmax);
trianglesList.Add(f);
trianglesList.Add(f + 1 + xmax);
trianglesList.Add(f + xmax);
}
}
}
List<Vector3> verts = new List<Vector3>();
Dictionary<Vector3, int> vdict = new Dictionary<Vector3, int>();
List<int> triangles = new List<int>();
int nextIndex = 0;
void addFace(Vector3 [] in_verts, List<int> in_triangles)
{
for(int i = 0; i < in_verts.Length; ++i)
{
if (!vdict.ContainsKey(in_verts[i]))
{
vdict.Add(in_verts[i], nextIndex);
verts.Add(in_verts[i]);
++nextIndex;
}
}
for(int i = 0; i < in_triangles.Count; ++i)
{
triangles.Add(vdict[in_verts[in_triangles[i]]]);
}
}
addFace(vertsTop, trianglesList);
addFace(vertsRight, trianglesList);
addFace(vertsFront, trianglesList);
addFace(vertsBottom, trianglesList);
addFace(vertsLeft, trianglesList);
addFace(vertsBack, trianglesList);
var mesh = meshFilter.sharedMesh;
mesh.Clear();
mesh.vertices = verts.ToArray();
mesh.triangles = triangles.ToArray();
mesh.RecalculateNormals();
}
}
[/code]
This code works in Blender (I used python to script it on Blender and it works very well for any resolution).
The only problem is that when I use this in Unity, the meshes become weird as I have shown in the images I have attached below.
At Resolution = 96 :
At Resolution = 122 :
At Resolution = 182 :
At Resolution = 344:
Why is this happening?
How should I correct it?
(I have also posted this in unity forums: Why cube mesh becomes a plane when in high resolution?)
Ok I found the answer. This is exceeding the limit of vertices on unity api for 16-bit based meshes. I had to change it to a 32-bit indexed mesh to correct it.
Details are in this docuemntaiton page : https://docs.unity3d.com/ScriptReference/Rendering.IndexFormat.html?_ga=2.9556401.501737799.1635227368-67181881.1629608252
I just had to add the code :
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
That was it.
I am creating a simple 2D tile game. To approach the task of creating lots of tiles at runtime I have decided to create a mesh and apply a texture created procedurally over top. To accomplish this I have a reference tileMap which contains every sort of tile. I then assign the UVs to the map. This method works fairly well but a gap appears between certain tiles. Any idea why?
Below I inserted 2 functions, buildTexture is creating the texture itself and chopTileMap returns a 2D array with Vector2s which are unique to each tile. This array can then be used such that the array of Vector2s and index 0 will return the 4 coordinates of the bottom left tile in my tile map.
void buildTexture()
{
Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector2[][] tileMap = chopTileMap();
List<Vector2> uvList = new List<Vector2>();
mesh.GetUVs(0, uvList);
Vector2[] uvs = uvList.ToArray();
//To set a UV it has to be given the fraction regarding to the tile map out of 1 (for a tile map 3 wide the vectors would be 0,1/2,2/3,1)
//tileMap is set as tileMap[tileID(index)][Point on tile (0-3)]
//for each UV, assign the set of 4 to points on the tile map
for (int r = 0; r < rowCount; r++)
{
for (int c = 0; c < colCount; c++)
{
//int tileIndex = Random.Range(0, tileMap.Length-1);
int tileIndex = Random.Range(0,4);
uvs[((r * colCount + c) * 4) + 0] = tileMap[tileIndex][0];
uvs[((r * colCount + c) * 4) + 1] = tileMap[tileIndex][1];
uvs[((r * colCount + c) * 4) + 2] = tileMap[tileIndex][2];
uvs[((r * colCount + c) * 4) + 3] = tileMap[tileIndex][3];
}
}
textureMap.Apply();
mesh.uv = uvs;
MeshRenderer meshRenderer = GetComponent<MeshRenderer>();
meshRenderer.materials[0].mainTexture = textureMap;
}
Vector2[][] chopTileMap()
{
int numColsOfMap = textureMap.width / tileResolution;
int numRowsOfMap = textureMap.height / tileResolution;
Vector2[][] tiles = new Vector2[numColsOfMap * numRowsOfMap][];
for (int r = 0; r < numRowsOfMap; r++){
for (int c = 0; c < numColsOfMap; c++){
tiles[r * numColsOfMap + c] = new Vector2[4];
tiles[r * numColsOfMap + c][0] = new Vector2((float)(c) / numColsOfMap, (float)(r) / numRowsOfMap);
tiles[r * numColsOfMap + c][1] = new Vector2((float)(c+1) / numColsOfMap, (float)(r) / numRowsOfMap);
tiles[r * numColsOfMap + c][2] = new Vector2((float)(c) / numColsOfMap, (float)(r+1) / numRowsOfMap);
tiles[r * numColsOfMap + c][3] = new Vector2((float)(c+1) / numColsOfMap, (float)(r+1) / numRowsOfMap);
}
}
return tiles;
}
In this picture thin blue lines can be seen between the tiles which is the background coming through.
The amount off by is less than a pixel as noted when trying to adjust the UV to compensate for this and as a result is hard to see but is defintly noticeable at runtime. The most predominant line in the image below is the thin blue one running vertically next to the player on the left.
I am following a tutorial about voxel meshes and ran into an error that I did not expect. Here is the tutorial, I am on the second part if you go and take a look at that. I also thought maybe this is a unity version issue as this is from 2014. The errors I have searched and found no conclusive results. I checked for the void statements over and over and seen many repetitive stackoverflow questions. I have also tried restarting unity multiple times. More specific information on the errors: On Line 118,119,and 120 i get these two errors. Error CS0501: Method Must have return type. Error CS0501: 'PolygonGenerator.PolygonGenerator()' must declare a body because it is not marked abstract, extern, or partial. Anyways, my code is as follows: (also, please correct my comments and add more)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PolygonGenerator : MonoBehaviour
{
// This first list contains every vertex of the mesh that we are going to render
public List<Vector3> newVertices = new List<Vector3>();
// The triangles tell Unity how to build each section of the mesh joining
// the vertices
public List<int> newTriangles = new List<int>();
// The UV list is unimportant right now but it tells Unity how the texture is
// aligned on each polygon
public List<Vector2> newUV = new List<Vector2>();
private float tUnit = 0.25f;
private Vector2 tStone = new Vector2(0, 0);
private Vector2 tGrass = new Vector2(0, 1);
// A mesh is made up of the vertices, triangles and UVs we are going to define,
// after we make them up we'll save them as this mesh
private Mesh mesh;
private int squareCount;
public byte[,] blocks; //0=air 1=rock, 2=grass
// Start is called before the first frame update
void Start()
{
//gets the mesh of the gameobject
mesh = GetComponent<MeshFilter>().mesh;
//gets the x,y, and z values of the gameobject
//writing x is easier than transform.position.x many times
float x = transform.position.x;
float y = transform.position.y;
float z = transform.position.z;
// defines what corners of the mesh to use for the four corners of the texture
newUV.Add(new Vector2(tUnit * tStone.x, tUnit * tStone.y + tUnit));
newUV.Add(new Vector2(tUnit * tStone.x + tUnit, tUnit * tStone.y + tUnit));
newUV.Add(new Vector2(tUnit * tStone.x + tUnit, tUnit * tStone.y));
newUV.Add(new Vector2(tUnit * tStone.x, tUnit * tStone.y));
//clear anything within the meshes boundries
mesh.Clear();
mesh.vertices = newVertices.ToArray(); //set the meshes vertecies to the new ones we just made
mesh.triangles = newTriangles.ToArray();
mesh.uv = newUV.ToArray(); // applys uvs to the mesh
mesh.Optimize(); //unity does some stuff
mesh.RecalculateNormals(); //
}
void GenSquare(int x, int y, Vector2 texture)
{
//defines the vertexes of the new square
newVertices.Add(new Vector3(x, y, z));
newVertices.Add(new Vector3(x + 1, y, z));
newVertices.Add(new Vector3(x + 1, y - 1, z));
newVertices.Add(new Vector3(x, y - 1, z));
//without triangels all we have is points in space, no connections
//these are added clockwise
newTriangles.Add(squareCount * 4); // 0,0
newTriangles.Add((squareCount * 4) +1); // 1,0
newTriangles.Add((squareCount * 4)+3); // -1,0
newTriangles.Add((squareCount * 4)+1); // 1,0
newTriangles.Add((squareCount * 4)+2); // -1,1
newTriangles.Add((squareCount * 4)+3); // -1,0
// defines what corners of the mesh to use for the four corners of the texture
newUV.Add(new Vector2(tUnit * texture.x, tUnit * texture.y + tUnit));
newUV.Add(new Vector2(tUnit * texture.x + tUnit, tUnit * texture.y + tUnit));
newUV.Add(new Vector2(tUnit * texture.x + tUnit, tUnit * texture.y));
newUV.Add(new Vector2(tUnit * texture.x, tUnit * texture.y));
squareCount++;
}
void GenTerrain()
{
blocks = new byte[10, 10];
for (int px = 0; px < blocks.GetLength(0); px++)
{
for (int py = 0; py < blocks.GetLength(1); py++)
{
if (py >= 5)
{
blocks[px, py] = 2;
}
else if (py < 5)
{
blocks[px, py] = 1;
}
}
}
}
void BuildMesh()
{
for (int px = 0; px < blocks.GetLength(0); px++)
{
for (int py = 0; py < blocks.GetLength(1); py++)
{
if (blocks[px, py] == 1)
{
GenSquare(px, py, tStone);
}
else if (blocks[px, py] == 2)
{
GenSquare(px, py, tGrass);
}
}
}
}
GenTerrain();
BuildMesh();
UpdateMesh();
// Update is called once per frame
void Update()
{
//clear anything within the meshes boundries
mesh.Clear();
mesh.vertices = newVertices.ToArray(); //set the meshes vertecies to the new ones we just made
mesh.triangles = newTriangles.ToArray();
mesh.uv = newUV.ToArray(); // applys uvs to the mesh
mesh.Optimize(); //unity does some stuff
mesh.RecalculateNormals(); //
squareCount = 0;
newVertices.Clear();
newTriangles.Clear();
newUV.Clear();
}
}
GenTerrain();
BuildMesh();
UpdateMesh();
These three method calls should be in a method, probably start or update. The computer thinks you're trying to define new methods here.
I currently have a "CreateMesh" script that can be put as a component of an object with a Mesh Renderer, and a Mesh Filter, and a 2D mesh is created with a polygon collider in the dimensions of the mesh given a "MeshType" variable is set to either "tri" or "box" (for a triangle and rectangle mesh respectively.) I want to also add the ability to create a circular mesh however from some research I've realised this isn't as simple as I first thought. However I'm yet to find anything that's helping.
This is the code I have for the box and triangle meshes:
public float width = 5f;
public float height = 5f;
public string meshType;
public PolygonCollider2D polyCollider;
void Start()
{
polyCollider = GetComponent<PolygonCollider2D>();
}
// Update is called once per frame
void Update () {
if (meshType == "tri")
{
TriangleMesh(width, height);
}
if (meshType == "box")
{
BoxMesh(width, height);
}
}
void TriangleMesh(float width, float height)
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//Verticies
Vector3[] verticies = new Vector3[3]
{
new Vector3(0,0,0), new Vector3(width, 0, 0), new Vector3(0, height, 0)
};
//Triangles
int[] tri = new int[3];
tri[0] = 0;
tri[1] = 2;
tri[2] = 1;
//normals
Vector3[] normals = new Vector3[3];
normals[0] = -Vector3.forward;
normals[1] = -Vector3.forward;
normals[2] = -Vector3.forward;
//UVs
Vector2[] uv = new Vector2[3];
uv[0] = new Vector2(0, 0);
uv[0] = new Vector2(1, 0);
uv[0] = new Vector2(0, 1);
//initialise
mesh.vertices = verticies;
mesh.triangles = tri;
mesh.normals = normals;
mesh.uv = uv;
//setting up collider
polyCollider.pathCount = 1;
Vector2[] path = new Vector2[3]
{
new Vector2(0,0), new Vector2(0, height), new Vector2(width, 0)
};
polyCollider.SetPath(0, path);
}
void BoxMesh(float width, float height)
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//Verticies
Vector3[] verticies = new Vector3[4]
{
new Vector3(0,0,0), new Vector3(0, height, 0), new Vector3(width, height, 0), new Vector3(width, 0, 0)
};
//Triangles
int[] tri = new int[6];
tri[0] = 0;
tri[1] = 1;
tri[2] = 3;
tri[3] = 1;
tri[4] = 2;
tri[5] = 3;
//normals
Vector3[] normals = new Vector3[4];
normals[0] = -Vector3.forward;
normals[1] = -Vector3.forward;
normals[2] = -Vector3.forward;
normals[3] = -Vector3.forward;
//UVs
Vector2[] uv = new Vector2[4];
uv[0] = new Vector2(0, 0);
uv[1] = new Vector2(0, 1);
uv[2] = new Vector2(1, 1);
uv[3] = new Vector2(1, 0);
//initialise
mesh.vertices = verticies;
mesh.triangles = tri;
mesh.normals = normals;
mesh.uv = uv;
//setting up collider
polyCollider.pathCount = 1;
Vector2[] path = new Vector2[4]
{
new Vector2(0,0), new Vector2(0, height), new Vector2(width, height), new Vector2(width, 0)
};
polyCollider.SetPath(0, path);
}
So essentially I want a function that I could call in the update method that would simply create a circular mesh. E.g:
void Update () {
if (meshType == "tri")
{
TriangleMesh(width, height);
}
if (meshType == "box")
{
BoxMesh(width, height);
}
if (meshType == "circle")
{
CircleMesh(radius);
}
}
The solution I've managed to find involves creating a regular polygon of n sides with a large value of n. I have a function called PolyMesh which creates a regular polygon mesh with n sides and a given radius.
Generating the vertices
For each vertex of a regular polygon with n sides the coordinates relative to the centre of the polygon are given by x = r*i*sin(θ) and y = r*i*cos(θ) so therefore x = r*i*sin(2π/2) and y = r*i*cos(2π/2). Where i iterates from 0 to n-1. We can therefore have a list which has vertices assigned to it and then is converted to an array afterwards:
//verticies
List<Vector3> verticiesList = new List<Vector3> { };
float x;
float y;
for (int i = 0; i < n; i ++)
{
x = radius * Mathf.Sin((2 * Mathf.PI * i) / n);
y = radius * Mathf.Cos((2 * Mathf.PI * i) / n);
verticiesList.Add(new Vector3(x, y, 0f));
}
Vector3[] verticies = verticiesList.ToArray();
Generating the triangles
A given regular polygon of n sides can be split into n-2 triangles from the same point. So we can generate each triangle as follows:
//triangles
List<int> trianglesList = new List<int> { };
for(int i = 0; i < (n-2); i++)
{
trianglesList.Add(0);
trianglesList.Add(i+1);
trianglesList.Add(i+2);
}
int[] triangles = trianglesList.ToArray();
Generating the Normals
Since this is a 2d object we can have every normal as -Vector3.forward like so:
//normals
List<Vector3> normalsList = new List<Vector3> { };
for (int i = 0; i < verticies.Length; i++)
{
normalsList.Add(-Vector3.forward);
}
Vector3[] normals = normalsList.ToArray();
Generating the collider
We could just use a circle collider with the same radius but in order to make this function work for a polygon of a smaller value of n we must use a PolygonCollider2D. Since the vertices are already in order in the vertices array we can simply use them as the paths for our PolygonCollider2D.
//polyCollider
polyCollider.pathCount = 1;
List<Vector2> pathList = new List<Vector2> { };
for (int i = 0; i < n; i++)
{
pathList.Add(new Vector2(verticies[i].x, verticies[i].y));
}
Vector2[] path = pathList.ToArray();
polyCollider.SetPath(0, path);
The complete code should look like this:
public PolygonCollider2D polyCollider;
void Start()
{
polyCollider = GetComponent<PolygonCollider2D>();
}
void PolyMesh(float radius, int n)
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//verticies
List<Vector3> verticiesList = new List<Vector3> { };
float x;
float y;
for (int i = 0; i < n; i ++)
{
x = radius * Mathf.Sin((2 * Mathf.PI * i) / n);
y = radius * Mathf.Cos((2 * Mathf.PI * i) / n);
verticiesList.Add(new Vector3(x, y, 0f));
}
Vector3[] verticies = verticiesList.ToArray();
//triangles
List<int> trianglesList = new List<int> { };
for(int i = 0; i < (n-2); i++)
{
trianglesList.Add(0);
trianglesList.Add(i+1);
trianglesList.Add(i+2);
}
int[] triangles = trianglesList.ToArray();
//normals
List<Vector3> normalsList = new List<Vector3> { };
for (int i = 0; i < verticies.Length; i++)
{
normalsList.Add(-Vector3.forward);
}
Vector3[] normals = normalsList.ToArray();
//initialise
mesh.vertices = verticies;
mesh.triangles = triangles;
mesh.normals = normals;
//polyCollider
polyCollider.pathCount = 1;
List<Vector2> pathList = new List<Vector2> { };
for (int i = 0; i < n; i++)
{
pathList.Add(new Vector2(verticies[i].x, verticies[i].y));
}
Vector2[] path = pathList.ToArray();
polyCollider.SetPath(0, path);
}
An introduction to meshes
I have less than 50 reputation and so I can't just comment on #Tom Ryan's answer.
With that said, beware that his solution doesn't include the UVs for the mesh. Here is that addition:
//uvs
Vector2[] uvs = new Vector2[vertices.Length];
for (int i = 0; i < uvs.Length; i++)
{
uvs[i] = new Vector2(vertices[i].x / (radius*2) + 0.5f, vertices[i].y / (radius*2) + 0.5f);
}
// Later...
mesh.uv = uvs;
I have a texture that I want to slice into 2 parts, using a Vector2 array.
I have all the Vector2 points for the curved line.
Question
How can I slice the texture into 2 parts using the curved line of points.
Alternative Solutions/Questions
How can I 'pixel' fill a Vector2[] shape to create a Texture?
My attempts
1) Generating Vector2 points to create a square, with the top part being the curve edge. Looked promising but when I tried generating a Mesh, the points sorting was incorrect.
2) Dynamically created a Polygon2D Collider - mimicking the bottom part of the sliced texture - this had the same issue as attempt 1, the point ordering. So when convert the Collider to Mesh, it obviously had the same results as attempt
In the picture below:
The red line simulates my Vector2 array
The gray+green square is the texture 1024 x 1024 pixels
The green area is the target area I want
This makes a mesh that is the shape you want (but with jagged edges on top), hopefully that is a step in the right direction. The Vector2 points[] array contains your red line. It should be sorted by the x coordinate, and all the numbers should be between 0 and 1. Needs a mesh filter and a mesh renderer with your texture.
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class createMesh : MonoBehaviour {
void Start () {
Vector2[] points = new Vector2[4];
points [0] = new Vector2 (0, .5f);
points [1] = new Vector2 (.33f, 1f);
points [2] = new Vector2 (.66f, .5f);
points [3] = new Vector2 (1, 1f);
MeshFilter mf = GetComponent<MeshFilter> ();
Mesh mesh = new Mesh();
Vector3[] verticies = new Vector3[points.Length * 2];
int[] triangles = new int[(points.Length - 1)*6];
Vector3[] normals = new Vector3[points.Length * 2];
Vector2[] uv = new Vector2[points.Length * 2];
int vIndex = 0;
int tIndex = 0;
int nIndex = 0;
int uvIndex = 0;
for (int i = 0; i< points.Length; i++) {
Vector3 topVert = points[i];
Vector3 bottomVert = topVert;
bottomVert.y = 0;
verticies[vIndex++]= bottomVert;
verticies[vIndex++]=topVert;
//uv
uv[uvIndex++] = bottomVert;
uv[uvIndex++] = topVert;
//normals
normals[nIndex++] = -Vector3.forward;
normals[nIndex++] = -Vector3.forward;
if (i<points.Length - 1) {
//triangles
triangles[tIndex++] = (i)*2;
triangles[tIndex++] = (i)*2+1;
triangles[tIndex++] = (i)*2+2;
triangles[tIndex++] = (i)*2+2;
triangles[tIndex++] = (i)*2+1;
triangles[tIndex++] = (i)*2+3;
}
}
mesh.vertices = verticies;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uv;
mf.mesh = mesh;
}
}
Bonus: here's a way to do it just with the texture. To use this the bitmap has to be set to Advanced, with read/write enabled in the import settings. This method uses 0 to 1023 (or however large your texture is) for coordinates, and should work for numbers out of that range too.
using UnityEngine;
using System.Collections;
public class tex2d : MonoBehaviour {
public Vector2[] points;
void Start () {
MeshRenderer mr;
Texture2D t2d;
Texture2D newTex = new Texture2D (1024, 1024);
mr = GetComponent<MeshRenderer> ();
t2d = mr.material.GetTexture (0) as Texture2D;
MakeTex (points, t2d, ref newTex, 1024);
mr.material.SetTexture (0, newTex);
}
void MakeTex(Vector2[] pnts, Texture2D inputTex, ref Texture2D outputTex, int size){
Color bgcolor = new Color (1, 0, 1, 1);
for (int i=0; i<(pnts.Length-1); i++) {
Vector2 p1=pnts[i];
Vector2 p2=pnts[i+1];
//skip points that are out of range
if ((p1.x <0 && p2.x <0) || (p1.x > size && p2.x>size)) continue;
for (int x =(int)p1.x; x<(int)p2.x; x++) {
if (x<0) continue;
if (x>=size) break;
float interpX = (x-p1.x)/(p2.x-p1.x);
int interpY = (int) ((p2.y-p1.y)*interpX + p1.y);
for (int y=0; y<interpY; y++) {
outputTex.SetPixel(x,y,inputTex.GetPixel(x,y));
}
for (int y= interpY; y<size; y++) {
outputTex.SetPixel(x,y,bgcolor);
}
}
}
outputTex.Apply ();
}
}