Rasterization
Rasterization
DDA
GridMesh.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
// Pre-setting before scripts
// Step1: Create a material, name White and choose shader "Sprites -> Default"
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class GridMesh : MonoBehaviour
{
public Mesh mesh;
private Vector3[] _vertices;
private Color[] _colors;
private int[] _triangles;
// Grid setting
public float cellSize;
public Vector3 gridoffset;
public int gridSize;
// Use this for initialization
void Awake()
{
mesh = GetComponent<MeshFilter>().mesh;
Vector3 gridPos = new Vector3(0, 0, 0);
GetComponent<Transform>().position = gridPos;
Debug.Log($"position = {GetComponent<Transform>().position}");
}
// Start is called before the first frame update
void Start()
{
CreateProceduralGrid();
UpdateMesh();
}
void CreateProceduralGrid()
{
// Set array sizes
_vertices = new Vector3[4 * gridSize * gridSize];
_colors = new Color[4 * gridSize * gridSize];
_triangles = new int[6 * gridSize * gridSize];
// Set tracker integers
int v = 0;
int t = 0;
// Set vertex offset
float vertexOffset = cellSize * 0.5f;
for (int x = 0; x < gridSize; x++)
{
for (int z = 0; z < gridSize; z++)
{
Vector3 cellOffset = new Vector3(x * cellSize, 0, z * cellSize);
_vertices[v + 0] = new Vector3(-vertexOffset, 0, -vertexOffset) + cellOffset + gridoffset;
_vertices[v + 1] = new Vector3(-vertexOffset, 0, vertexOffset) + cellOffset + gridoffset;
_vertices[v + 2] = new Vector3(vertexOffset, 0, -vertexOffset) + cellOffset + gridoffset;
_vertices[v + 3] = new Vector3(vertexOffset, 0, vertexOffset) + cellOffset + gridoffset;
_colors[v + 0] = _colors[v + 1] = _colors[v + 2] = _colors[v + 3] = new Color(1, 1, 1, 1);
_triangles[t + 0] = v;
_triangles[t + 1] = _triangles[t + 4] = v + 1;
_triangles[t + 2] = _triangles[t + 3] = v + 2;
_triangles[t + 5] = v + 3;
v += 4;
t += 6;
}
}
}
void UpdateMesh()
{
// Clear all vertex data and all triangle indices
mesh.Clear();
// Assign our vertices and triangles to mesh object
mesh.vertices = _vertices;
mesh.colors = _colors;
mesh.triangles = _triangles;
mesh.RecalculateNormals();
}
// Update is called once per frame
void Update()
{
}
}
DDA.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Pre-setting before scripts
// Step1: Create an empty game object, name Source and add material blue
// Step2: Create an empty game object, name Target and add material red
// Step3: Create an empty game object, name Grid and attach GridMesh script and add material white
// Step4: Create an empty game object, name DDA and attach DDA script
public class DDA : MonoBehaviour
{
private GameObject _source;
private GameObject _target;
private GameObject _gridMesh;
private Mesh _mesh;
private int _gridSize;
private float _cellSize;
// Use this for initialization
void Awake()
{
// Get the GameObject information
_source = GameObject.Find("Source");
_target = GameObject.Find("Target");
_gridMesh = GameObject.Find("Grid");
_mesh = _gridMesh.GetComponent<MeshFilter>().mesh;
_gridSize = _gridMesh.GetComponent<GridMesh>().gridSize;
_cellSize = _gridMesh.GetComponent<GridMesh>().cellSize;
// Reset grid position
Vector3 gridPosition = _gridMesh.transform.position = new Vector3(0, 0, 0);
// Reset source and target position
Vector3 sourcePos = new Vector3(
gridPosition.x,
gridPosition.y,
gridPosition.z
);
Vector3 targetPos = new Vector3(
(_gridSize - 1) * _cellSize,
gridPosition.y,
(_gridSize - 1) * _cellSize
);
// Initialize positions
_source.transform.position = sourcePos;
_target.transform.position = targetPos;
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Vector3 gridPosition = _gridMesh.transform.position;
// Update positions
Vector3 sourcePos = _source.transform.position;
sourcePos.y = gridPosition.y;
Vector3 targetPos = _target.transform.position;
targetPos.y = gridPosition.y;
// Debug.Log($"sourcePos = {sourcePos }");
_source.transform.position = sourcePos;
_target.transform.position = targetPos;
ComputeDDA();
}
void ComputeDDA()
{
Vector3 sourcePos = _source.transform.position;
Vector3 targetPos = _target.transform.position;
// Create new colors array where the colors will be created.
Color[] colors = _mesh.colors;
// Reset colors of the grid mesh to white
for (int i = 0; i < colors.Length; i++)
{
colors[i].r = colors[i].g = colors[i].b = colors[i].a = 1;
}
float dx = (targetPos.x - sourcePos.x);
float dz = (targetPos.z - sourcePos.z);
//float dx = (targetPos.x - sourcePos.x) / _cellSize;
//float dz = (targetPos.z - sourcePos.z) / _cellSize;
float m = dz / dx;
float x = sourcePos.x;
float z = sourcePos.z;
//float x = sourcePos.x / _cellSize;
//float z = sourcePos.z / _cellSize;
DrawPixel(colors, (int)Math.Round(x), (int)Math.Round(z));
// m <= 1
if (m <= 1)
{
for (int i = 0; i < dx; i++)
{
x += 1;
z += m;
DrawPixel(colors, (int)Math.Round(x), (int)Math.Round(z));
}
}
// m > 1
else
{
m = dx / dz;
for (int i = 0; i < dz; i++)
{
x += m;
z += 1;
DrawPixel(colors, (int)Math.Round(x), (int)Math.Round(z));
}
}
// Update the grid colors
_mesh.colors = colors;
}
void DrawPixel(Color[] colors, int x, int z)
{
// Debug.Log($"(x,z) = ({x},{z})");
if (x >= _gridSize || z >= _gridSize) return;
// Debug.Log($"vertices.Length = {vertices.Length}");
// Assign the array of colors to the Mesh.
int v = 4 * (x * _gridSize + z);
colors[v] = new Color(0, 0, 0, 1);
colors[v + 1] = new Color(0, 0, 0, 1);
colors[v + 2] = new Color(0, 0, 0, 1);
colors[v + 3] = new Color(0, 0, 0, 1);
}
}
Bresenham’s Line Algorithm
Bresenham.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Pre-setting before scripts
// Step1: Create an empty game object, name Source and add material blue
// Step2: Create an empty game object, name Target and add material red
// Step3: Create an empty game object, name Grid and attach GridMesh script and add material white
// Step4: Create an empty game object, name DDA and attach Bresenham script
public class Bresenham : MonoBehaviour
{
private GameObject _source;
private GameObject _target;
private GameObject _gridMesh;
private Mesh _mesh;
private int _gridSize;
private float _cellSize;
// Use this for initialization
void Awake()
{
// Get the GameObject information
_source = GameObject.Find("Source");
_target = GameObject.Find("Target");
_gridMesh = GameObject.Find("Grid");
_mesh = _gridMesh.GetComponent<MeshFilter>().mesh;
_gridSize = _gridMesh.GetComponent<GridMesh>().gridSize;
_cellSize = _gridMesh.GetComponent<GridMesh>().cellSize;
// Reset grid position
Vector3 gridPosition = _gridMesh.transform.position = new Vector3(0, 0, 0);
// Reset source and target position
Vector3 sourcePos = new Vector3(
gridPosition.x,
gridPosition.y,
gridPosition.z
);
Vector3 targetPos = new Vector3(
(_gridSize - 1) * _cellSize,
gridPosition.y,
(_gridSize - 1) * _cellSize
);
// Initialize positions
_source.transform.position = sourcePos;
_target.transform.position = targetPos;
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Vector3 gridPosition = _gridMesh.transform.position;
// Update positions
Vector3 sourcePos = _source.transform.position;
sourcePos.y = gridPosition.y;
Vector3 targetPos = _target.transform.position;
targetPos.y = gridPosition.y;
// Debug.Log($"sourcePos = {sourcePos }");
_source.transform.position = sourcePos;
_target.transform.position = targetPos;
ComputeBresenham();
}
void ComputeBresenham()
{
Vector3 sourcePos = _source.transform.position;
Vector3 targetPos = _target.transform.position;
// Create new colors array where the colors will be created.
Color[] colors = _mesh.colors;
// Reset colors of the grid mesh to white
for (int i = 0; i < colors.Length; i++)
{
colors[i].r = colors[i].g = colors[i].b = colors[i].a = 1;
}
// 1. store left line endpoint in (x0,y0)
int xk = (int)(sourcePos.x / _cellSize);
int zk = (int)(sourcePos.z / _cellSize);
int dx = (int)((targetPos.x - sourcePos.x) / _cellSize);
int dz = (int)((targetPos.z - sourcePos.z) / _cellSize);
// 2. draw pixel (x0,y0)
DrawPixel(colors, xk, zk);
// m <= 1
if (dz <= dx)
{
// 3. calculate constants Dx, Dy, 2Dy, 2Dy - 2Dx, and obtain p0 = 2Dy - Dx
int twodz_twodx = 2 * dz - 2 * dx;
int twodz = 2 * dz;
int pk = 2 * dz - dx;
// 4. at each xk along the line, perform test:
// if pk<0
// then draw pixel (xk+1,yk); pk+1 = pk+ 2Dy
// else draw pixel (xk+1,yk+1); pk+1= pk+ 2Dy - 2Dx
// 5. perform “step 4” (Dx - 1) times.
for (int i = 0; i < dx; i++)
{
if (pk < 0)
{
DrawPixel(colors, xk + 1, zk);
pk = pk + twodz;
}
else
{
DrawPixel(colors, xk + 1, zk + 1);
zk++;
pk = pk + twodz_twodx;
}
xk++;
}
}
// m <= 1
else
{
// 3. calculate constants Dx, Dy, 2Dy, 2Dy - 2Dx, and obtain p0 = 2Dy - Dx
int twodx_twodz = 2 * dx - 2 * dz;
int twodx = 2 * dx;
int pk = 2 * dx - dz;
// 4. at each xk along the line, perform test:
// if pk<0
// then draw pixel (xk+1,yk); pk+1 = pk+ 2Dy
// else draw pixel (xk+1,yk+1); pk+1= pk+ 2Dy - 2Dx
// 5. perform “step 4” (Dx - 1) times.
for (int i = 0; i < dz; i++)
{
if (pk < 0)
{
DrawPixel(colors, xk, zk + 1);
pk = pk + twodx;
}
else
{
DrawPixel(colors, xk + 1, zk + 1);
xk++;
pk = pk + twodx_twodz;
}
zk++;
}
}
// Update the grid colors
_mesh.colors = colors;
}
void DrawPixel(Color[] colors, int x, int z)
{
// Debug.Log($"(x,z) = ({x},{z})");
if (x >= _gridSize || z >= _gridSize) return;
// Debug.Log($"vertices.Length = {vertices.Length}");
// Assign the array of colors to the Mesh.
int v = 4 * (x * _gridSize + z);
colors[v] = new Color(0, 0, 0, 1);
colors[v + 1] = new Color(0, 0, 0, 1);
colors[v + 2] = new Color(0, 0, 0, 1);
colors[v + 3] = new Color(0, 0, 0, 1);
}
}