Added player character and step in/out of dialogue in scene 101
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly:InternalsVisibleTo("Unity.ProBuilder")]
|
||||
[assembly:InternalsVisibleTo("Unity.ProBuilder.Editor")]
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90c015bd1316c423b9aad70704f602ff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,134 @@
|
||||
// Original CSG.JS library by Evan Wallace (http://madebyevan.com), under the MIT license.
|
||||
// GitHub: https://github.com/evanw/csg.js/
|
||||
//
|
||||
// C++ port by Tomasz Dabrowski (http://28byteslater.com), under the MIT license.
|
||||
// GitHub: https://github.com/dabroz/csgjs-cpp/
|
||||
//
|
||||
// C# port by Karl Henkel (parabox.co), under MIT license.
|
||||
//
|
||||
// Constructive Solid Geometry (CSG) is a modeling technique that uses Boolean
|
||||
// operations like union and intersection to combine 3D solids. This library
|
||||
// implements CSG operations on meshes elegantly and concisely using BSP trees,
|
||||
// and is meant to serve as an easily understandable implementation of the
|
||||
// algorithm. All edge cases involving overlapping coplanar polygons in both
|
||||
// solids are correctly handled.
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Unity.ProBuilder.Editor.Tests")]
|
||||
|
||||
namespace UnityEngine.ProBuilder.Csg
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for CSG operations. Contains GameObject level methods for Subtraction, Intersection, and Union
|
||||
/// operations. The GameObjects passed to these functions will not be modified.
|
||||
/// </summary>
|
||||
static class CSG
|
||||
{
|
||||
public enum BooleanOp
|
||||
{
|
||||
Intersection,
|
||||
Union,
|
||||
Subtraction
|
||||
}
|
||||
|
||||
const float k_DefaultEpsilon = 0.00001f;
|
||||
static float s_Epsilon = k_DefaultEpsilon;
|
||||
|
||||
/// <summary>
|
||||
/// Tolerance used by <see cref="Plane.SplitPolygon"/> determine whether planes are coincident.
|
||||
/// </summary>
|
||||
public static float epsilon
|
||||
{
|
||||
get => s_Epsilon;
|
||||
set => s_Epsilon = value;
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
static void ResetStaticsOnLoad()
|
||||
{
|
||||
s_Epsilon = k_DefaultEpsilon;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Performs a boolean operation on two GameObjects.
|
||||
/// </summary>
|
||||
/// <returns>A new mesh.</returns>
|
||||
public static Model Perform(BooleanOp op, GameObject lhs, GameObject rhs)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case BooleanOp.Intersection:
|
||||
return Intersect(lhs, rhs);
|
||||
case BooleanOp.Union:
|
||||
return Union(lhs, rhs);
|
||||
case BooleanOp.Subtraction:
|
||||
return Subtract(lhs, rhs);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new mesh by merging @lhs with @rhs.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The base mesh of the boolean operation.</param>
|
||||
/// <param name="rhs">The input mesh of the boolean operation.</param>
|
||||
/// <returns>A new mesh if the operation succeeds, or null if an error occurs.</returns>
|
||||
public static Model Union(GameObject lhs, GameObject rhs)
|
||||
{
|
||||
Model csg_model_a = new Model(lhs);
|
||||
Model csg_model_b = new Model(rhs);
|
||||
|
||||
Node a = new Node(csg_model_a.ToPolygons());
|
||||
Node b = new Node(csg_model_b.ToPolygons());
|
||||
|
||||
List<Polygon> polygons = Node.Union(a, b).AllPolygons();
|
||||
|
||||
return new Model(polygons);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new mesh by subtracting @lhs with @rhs.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The base mesh of the boolean operation.</param>
|
||||
/// <param name="rhs">The input mesh of the boolean operation.</param>
|
||||
/// <returns>A new mesh if the operation succeeds, or null if an error occurs.</returns>
|
||||
public static Model Subtract(GameObject lhs, GameObject rhs)
|
||||
{
|
||||
Model csg_model_a = new Model(lhs);
|
||||
Model csg_model_b = new Model(rhs);
|
||||
|
||||
Node a = new Node(csg_model_a.ToPolygons());
|
||||
Node b = new Node(csg_model_b.ToPolygons());
|
||||
|
||||
List<Polygon> polygons = Node.Subtract(a, b).AllPolygons();
|
||||
|
||||
return new Model(polygons);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new mesh by intersecting @lhs with @rhs.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The base mesh of the boolean operation.</param>
|
||||
/// <param name="rhs">The input mesh of the boolean operation.</param>
|
||||
/// <returns>A new mesh if the operation succeeds, or null if an error occurs.</returns>
|
||||
public static Model Intersect(GameObject lhs, GameObject rhs)
|
||||
{
|
||||
Model csg_model_a = new Model(lhs);
|
||||
Model csg_model_b = new Model(rhs);
|
||||
|
||||
Node a = new Node(csg_model_a.ToPolygons());
|
||||
Node b = new Node(csg_model_b.ToPolygons());
|
||||
|
||||
List<Polygon> polygons = Node.Intersect(a, b).AllPolygons();
|
||||
|
||||
return new Model(polygons);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 136c7ff4a0ec419280b8df0d260180d0
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 291cedf2747a43b19e37963cf9100589
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityEngine.ProBuilder.Csg
|
||||
{
|
||||
/// <summary>
|
||||
/// Representation of a mesh in CSG terms. Contains methods for translating to and from UnityEngine.Mesh.
|
||||
/// </summary>
|
||||
sealed class Model
|
||||
{
|
||||
List<Vertex> m_Vertices;
|
||||
List<Material> m_Materials;
|
||||
List<List<int>> m_Indices;
|
||||
|
||||
public List<Material> materials
|
||||
{
|
||||
get { return m_Materials; }
|
||||
set { m_Materials = value; }
|
||||
}
|
||||
|
||||
public List<Vertex> vertices
|
||||
{
|
||||
get { return m_Vertices; }
|
||||
set { m_Vertices = value; }
|
||||
}
|
||||
|
||||
public List<List<int>> indices
|
||||
{
|
||||
get { return m_Indices; }
|
||||
set { m_Indices = value; }
|
||||
}
|
||||
|
||||
public Mesh mesh
|
||||
{
|
||||
get { return (Mesh)this; }
|
||||
}
|
||||
|
||||
public Model(GameObject gameObject) :
|
||||
this(gameObject.GetComponent<MeshFilter>()?.sharedMesh,
|
||||
gameObject.GetComponent<MeshRenderer>()?.sharedMaterials,
|
||||
gameObject.GetComponent<Transform>())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize a Model from a UnityEngine.Mesh and transform.
|
||||
/// </summary>
|
||||
public Model(Mesh mesh, Material[] materials, Transform transform)
|
||||
{
|
||||
if(mesh == null)
|
||||
throw new ArgumentNullException("mesh");
|
||||
|
||||
if(transform == null)
|
||||
throw new ArgumentNullException("transform");
|
||||
|
||||
m_Vertices = VertexUtility.GetVertices(mesh).Select(x => transform.TransformVertex(x)).ToList();
|
||||
m_Materials = new List<Material>(materials);
|
||||
m_Indices = new List<List<int>>();
|
||||
|
||||
for (int i = 0, c = mesh.subMeshCount; i < c; i++)
|
||||
{
|
||||
if (mesh.GetTopology(i) != MeshTopology.Triangles)
|
||||
continue;
|
||||
var indices = new List<int>();
|
||||
mesh.GetIndices(indices, i);
|
||||
m_Indices.Add(indices);
|
||||
}
|
||||
}
|
||||
|
||||
internal Model(List<Polygon> polygons)
|
||||
{
|
||||
m_Vertices = new List<Vertex>();
|
||||
Dictionary<Material, List<int>> submeshes = new Dictionary<Material, List<int>>();
|
||||
|
||||
int p = 0;
|
||||
|
||||
for (int i = 0; i < polygons.Count; i++)
|
||||
{
|
||||
Polygon poly = polygons[i];
|
||||
List<int> indices;
|
||||
|
||||
if (!submeshes.TryGetValue(poly.material, out indices))
|
||||
submeshes.Add(poly.material, indices = new List<int>());
|
||||
|
||||
for (int j = 2; j < poly.vertices.Count; j++)
|
||||
{
|
||||
m_Vertices.Add(poly.vertices[0]);
|
||||
indices.Add(p++);
|
||||
|
||||
m_Vertices.Add(poly.vertices[j - 1]);
|
||||
indices.Add(p++);
|
||||
|
||||
m_Vertices.Add(poly.vertices[j]);
|
||||
indices.Add(p++);
|
||||
}
|
||||
}
|
||||
|
||||
m_Materials = submeshes.Keys.ToList();
|
||||
m_Indices = submeshes.Values.ToList();
|
||||
}
|
||||
|
||||
internal List<Polygon> ToPolygons()
|
||||
{
|
||||
List<Polygon> list = new List<Polygon>();
|
||||
|
||||
for (int s = 0, c = m_Indices.Count; s < c; s++)
|
||||
{
|
||||
var indices = m_Indices[s];
|
||||
|
||||
for (int i = 0, ic = indices.Count; i < indices.Count; i += 3)
|
||||
{
|
||||
List<Vertex> triangle = new List<Vertex>()
|
||||
{
|
||||
m_Vertices[indices[i + 0]],
|
||||
m_Vertices[indices[i + 1]],
|
||||
m_Vertices[indices[i + 2]]
|
||||
};
|
||||
|
||||
list.Add(new Polygon(triangle, m_Materials[s]));
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static explicit operator Mesh(Model model)
|
||||
{
|
||||
var mesh = new Mesh();
|
||||
VertexUtility.SetMesh(mesh, model.m_Vertices);
|
||||
mesh.subMeshCount = model.m_Indices.Count;
|
||||
for (int i = 0, c = mesh.subMeshCount; i < c; i++)
|
||||
mesh.SetIndices(model.m_Indices[i], MeshTopology.Triangles, i);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14789abc21c8f4551995149f67010e23
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,256 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityEngine.ProBuilder.Csg
|
||||
{
|
||||
sealed class Node
|
||||
{
|
||||
public List<Polygon> polygons;
|
||||
|
||||
public Node front;
|
||||
public Node back;
|
||||
|
||||
public Plane plane;
|
||||
|
||||
public Node()
|
||||
{
|
||||
front = null;
|
||||
back = null;
|
||||
}
|
||||
|
||||
public Node(List<Polygon> list)
|
||||
{
|
||||
Build(list);
|
||||
}
|
||||
|
||||
public Node(List<Polygon> list, Plane plane, Node front, Node back)
|
||||
{
|
||||
this.polygons = list;
|
||||
this.plane = plane;
|
||||
this.front = front;
|
||||
this.back = back;
|
||||
}
|
||||
|
||||
public Node Clone()
|
||||
{
|
||||
Node clone = new Node(this.polygons, this.plane, this.front, this.back);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Remove all polygons in this BSP tree that are inside the other BSP tree
|
||||
// `bsp`.
|
||||
public void ClipTo(Node other)
|
||||
{
|
||||
this.polygons = other.ClipPolygons(this.polygons);
|
||||
|
||||
if (this.front != null)
|
||||
{
|
||||
this.front.ClipTo(other);
|
||||
}
|
||||
|
||||
if (this.back != null)
|
||||
{
|
||||
this.back.ClipTo(other);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert solid space to empty space and empty space to solid space.
|
||||
public void Invert()
|
||||
{
|
||||
for (int i = 0; i < this.polygons.Count; i++)
|
||||
this.polygons[i].Flip();
|
||||
|
||||
this.plane.Flip();
|
||||
|
||||
if (this.front != null)
|
||||
{
|
||||
this.front.Invert();
|
||||
}
|
||||
|
||||
if (this.back != null)
|
||||
{
|
||||
this.back.Invert();
|
||||
}
|
||||
|
||||
Node tmp = this.front;
|
||||
this.front = this.back;
|
||||
this.back = tmp;
|
||||
}
|
||||
|
||||
// Build a BSP tree out of `polygons`. When called on an existing tree, the
|
||||
// new polygons are filtered down to the bottom of the tree and become new
|
||||
// nodes there. Each set of polygons is partitioned using the first polygon
|
||||
// (no heuristic is used to pick a good split).
|
||||
public void Build(List<Polygon> list)
|
||||
{
|
||||
if (list.Count < 1)
|
||||
return;
|
||||
|
||||
bool newNode = plane == null || !plane.Valid();
|
||||
|
||||
if (newNode)
|
||||
{
|
||||
plane = new Plane();
|
||||
plane.normal = list[0].plane.normal;
|
||||
plane.w = list[0].plane.w;
|
||||
}
|
||||
|
||||
if (polygons == null)
|
||||
polygons = new List<Polygon>();
|
||||
|
||||
var listFront = new List<Polygon>();
|
||||
var listBack = new List<Polygon>();
|
||||
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
plane.SplitPolygon(list[i], polygons, polygons, listFront, listBack);
|
||||
|
||||
|
||||
if (listFront.Count > 0)
|
||||
{
|
||||
// SplitPolygon can fail to correctly identify coplanar planes when the epsilon value is too low. When
|
||||
// this happens, the front or back list will be filled and built into a new node recursively. This
|
||||
// check catches that case and sorts the front/back lists into the coplanar polygons collection.
|
||||
if (newNode && list.SequenceEqual(listFront))
|
||||
polygons.AddRange(listFront);
|
||||
else
|
||||
(front ?? (front = new Node())).Build(listFront);
|
||||
}
|
||||
|
||||
if (listBack.Count > 0)
|
||||
{
|
||||
if (newNode && list.SequenceEqual(listBack))
|
||||
polygons.AddRange(listBack);
|
||||
else
|
||||
(back ?? (back = new Node())).Build(listBack);
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively remove all polygons in `polygons` that are inside this BSP tree.
|
||||
public List<Polygon> ClipPolygons(List<Polygon> list)
|
||||
{
|
||||
if (!this.plane.Valid())
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
List<Polygon> list_front = new List<Polygon>();
|
||||
List<Polygon> list_back = new List<Polygon>();
|
||||
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
this.plane.SplitPolygon(list[i], list_front, list_back, list_front, list_back);
|
||||
}
|
||||
|
||||
if (this.front != null)
|
||||
{
|
||||
list_front = this.front.ClipPolygons(list_front);
|
||||
}
|
||||
|
||||
if (this.back != null)
|
||||
{
|
||||
list_back = this.back.ClipPolygons(list_back);
|
||||
}
|
||||
else
|
||||
{
|
||||
list_back.Clear();
|
||||
}
|
||||
|
||||
// Position [First, Last]
|
||||
// list_front.insert(list_front.end(), list_back.begin(), list_back.end());
|
||||
list_front.AddRange(list_back);
|
||||
|
||||
return list_front;
|
||||
}
|
||||
|
||||
// Return a list of all polygons in this BSP tree.
|
||||
public List<Polygon> AllPolygons()
|
||||
{
|
||||
List<Polygon> list = this.polygons;
|
||||
List<Polygon> list_front = new List<Polygon>(), list_back = new List<Polygon>();
|
||||
|
||||
if (this.front != null)
|
||||
{
|
||||
list_front = this.front.AllPolygons();
|
||||
}
|
||||
|
||||
if (this.back != null)
|
||||
{
|
||||
list_back = this.back.AllPolygons();
|
||||
}
|
||||
|
||||
list.AddRange(list_front);
|
||||
list.AddRange(list_back);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
#region STATIC OPERATIONS
|
||||
|
||||
// Return a new CSG solid representing space in either this solid or in the
|
||||
// solid `csg`. Neither this solid nor the solid `csg` are modified.
|
||||
public static Node Union(Node a1, Node b1)
|
||||
{
|
||||
Node a = a1.Clone();
|
||||
Node b = b1.Clone();
|
||||
|
||||
a.ClipTo(b);
|
||||
b.ClipTo(a);
|
||||
b.Invert();
|
||||
b.ClipTo(a);
|
||||
b.Invert();
|
||||
|
||||
a.Build(b.AllPolygons());
|
||||
|
||||
Node ret = new Node(a.AllPolygons());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Return a new CSG solid representing space in this solid but not in the
|
||||
// solid `csg`. Neither this solid nor the solid `csg` are modified.
|
||||
public static Node Subtract(Node a1, Node b1)
|
||||
{
|
||||
Node a = a1.Clone();
|
||||
Node b = b1.Clone();
|
||||
|
||||
a.Invert();
|
||||
a.ClipTo(b);
|
||||
b.ClipTo(a);
|
||||
b.Invert();
|
||||
b.ClipTo(a);
|
||||
b.Invert();
|
||||
a.Build(b.AllPolygons());
|
||||
a.Invert();
|
||||
|
||||
Node ret = new Node(a.AllPolygons());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Return a new CSG solid representing space both this solid and in the
|
||||
// solid `csg`. Neither this solid nor the solid `csg` are modified.
|
||||
public static Node Intersect(Node a1, Node b1)
|
||||
{
|
||||
Node a = a1.Clone();
|
||||
Node b = b1.Clone();
|
||||
|
||||
a.Invert();
|
||||
b.ClipTo(a);
|
||||
b.Invert();
|
||||
a.ClipTo(b);
|
||||
b.ClipTo(a);
|
||||
|
||||
a.Build(b.AllPolygons());
|
||||
a.Invert();
|
||||
|
||||
Node ret = new Node(a.AllPolygons());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b6fe112f5d10423ab960f97d7b6e699
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityEngine.ProBuilder.Csg
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a plane in 3d space.
|
||||
/// <remarks>Does not include position.</remarks>
|
||||
/// </summary>
|
||||
sealed class Plane
|
||||
{
|
||||
public Vector3 normal;
|
||||
public float w;
|
||||
|
||||
[System.Flags]
|
||||
enum EPolygonType
|
||||
{
|
||||
Coplanar = 0,
|
||||
Front = 1,
|
||||
Back = 2,
|
||||
Spanning = 3 /// 3 is Front | Back - not a separate entry
|
||||
};
|
||||
|
||||
public Plane()
|
||||
{
|
||||
normal = Vector3.zero;
|
||||
w = 0f;
|
||||
}
|
||||
|
||||
public Plane(Vector3 a, Vector3 b, Vector3 c)
|
||||
{
|
||||
normal = Vector3.Cross(b - a, c - a);//.normalized;
|
||||
w = Vector3.Dot(normal, a);
|
||||
}
|
||||
|
||||
public override string ToString() => $"{normal} {w}";
|
||||
|
||||
public bool Valid()
|
||||
{
|
||||
return normal.magnitude > 0f;
|
||||
}
|
||||
|
||||
public void Flip()
|
||||
{
|
||||
normal *= -1f;
|
||||
w *= -1f;
|
||||
}
|
||||
|
||||
// Split `polygon` by this plane if needed, then put the polygon or polygon
|
||||
// fragments in the appropriate lists. Coplanar polygons go into either
|
||||
// `coplanarFront` or `coplanarBack` depending on their orientation with
|
||||
// respect to this plane. Polygons in front or in back of this plane go into
|
||||
// either `front` or `back`.
|
||||
public void SplitPolygon(Polygon polygon, List<Polygon> coplanarFront, List<Polygon> coplanarBack, List<Polygon> front, List<Polygon> back)
|
||||
{
|
||||
// Classify each point as well as the entire polygon into one of the above
|
||||
// four classes.
|
||||
EPolygonType polygonType = 0;
|
||||
List<EPolygonType> types = new List<EPolygonType>();
|
||||
|
||||
for (int i = 0; i < polygon.vertices.Count; i++)
|
||||
{
|
||||
float t = Vector3.Dot(this.normal, polygon.vertices[i].position) - this.w;
|
||||
EPolygonType type = (t < -CSG.epsilon) ? EPolygonType.Back : ((t > CSG.epsilon) ? EPolygonType.Front : EPolygonType.Coplanar);
|
||||
polygonType |= type;
|
||||
types.Add(type);
|
||||
}
|
||||
|
||||
// Put the polygon in the correct list, splitting it when necessary.
|
||||
switch (polygonType)
|
||||
{
|
||||
case EPolygonType.Coplanar:
|
||||
{
|
||||
if (Vector3.Dot(this.normal, polygon.plane.normal) > 0)
|
||||
coplanarFront.Add(polygon);
|
||||
else
|
||||
coplanarBack.Add(polygon);
|
||||
}
|
||||
break;
|
||||
|
||||
case EPolygonType.Front:
|
||||
{
|
||||
front.Add(polygon);
|
||||
}
|
||||
break;
|
||||
|
||||
case EPolygonType.Back:
|
||||
{
|
||||
back.Add(polygon);
|
||||
}
|
||||
break;
|
||||
|
||||
case EPolygonType.Spanning:
|
||||
{
|
||||
List<Vertex> f = new List<Vertex>();
|
||||
List<Vertex> b = new List<Vertex>();
|
||||
|
||||
for (int i = 0; i < polygon.vertices.Count; i++)
|
||||
{
|
||||
int j = (i + 1) % polygon.vertices.Count;
|
||||
|
||||
EPolygonType ti = types[i], tj = types[j];
|
||||
|
||||
Vertex vi = polygon.vertices[i], vj = polygon.vertices[j];
|
||||
|
||||
if (ti != EPolygonType.Back)
|
||||
{
|
||||
f.Add(vi);
|
||||
}
|
||||
|
||||
if (ti != EPolygonType.Front)
|
||||
{
|
||||
b.Add(vi);
|
||||
}
|
||||
|
||||
if ((ti | tj) == EPolygonType.Spanning)
|
||||
{
|
||||
float t = (this.w - Vector3.Dot(this.normal, vi.position)) / Vector3.Dot(this.normal, vj.position - vi.position);
|
||||
|
||||
Vertex v = VertexUtility.Mix(vi, vj, t);
|
||||
|
||||
f.Add(v);
|
||||
b.Add(v);
|
||||
}
|
||||
}
|
||||
|
||||
if (f.Count >= 3)
|
||||
{
|
||||
if (f.SequenceEqual(polygon.vertices))
|
||||
front.Add(polygon);
|
||||
else
|
||||
{
|
||||
var p = new Polygon(f, polygon.material);
|
||||
if (p.plane.Valid())
|
||||
front.Add(p);
|
||||
}
|
||||
}
|
||||
|
||||
if (b.Count >= 3)
|
||||
{
|
||||
if (b.SequenceEqual(polygon.vertices))
|
||||
back.Add(polygon);
|
||||
else
|
||||
{
|
||||
var p = new Polygon(b, polygon.material);
|
||||
if (p.plane.Valid())
|
||||
back.Add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} // End switch(polygonType)
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2665d2fb2b90b4916bfb3868cda99ea3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEngine.ProBuilder.Csg
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a polygon face with an arbitrary number of vertices.
|
||||
/// </summary>
|
||||
sealed class Polygon
|
||||
{
|
||||
public List<Vertex> vertices;
|
||||
public Plane plane;
|
||||
public Material material;
|
||||
|
||||
public Polygon(List<Vertex> list, Material mat)
|
||||
{
|
||||
vertices = list;
|
||||
plane = new Plane(list[0].position, list[1].position, list[2].position);
|
||||
material = mat;
|
||||
}
|
||||
|
||||
public void Flip()
|
||||
{
|
||||
vertices.Reverse();
|
||||
|
||||
for (int i = 0; i < vertices.Count; i++)
|
||||
vertices[i].Flip();
|
||||
|
||||
plane.Flip();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[{vertices.Count}] {plane.normal}";
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 52ebe52d390074084bebc0878e3f74b6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEngine.ProBuilder.Csg
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds information about a single vertex, and provides methods for averaging between many.
|
||||
/// <remarks>All values are optional. Where not present a default value will be substituted if necessary.</remarks>
|
||||
/// </summary>
|
||||
struct Vertex
|
||||
{
|
||||
Vector3 m_Position;
|
||||
Color m_Color;
|
||||
Vector3 m_Normal;
|
||||
Vector4 m_Tangent;
|
||||
Vector2 m_UV0;
|
||||
Vector2 m_UV2;
|
||||
Vector4 m_UV3;
|
||||
Vector4 m_UV4;
|
||||
VertexAttributes m_Attributes;
|
||||
|
||||
/// <value>
|
||||
/// The position in model space.
|
||||
/// </value>
|
||||
public Vector3 position
|
||||
{
|
||||
get { return m_Position; }
|
||||
set
|
||||
{
|
||||
hasPosition = true;
|
||||
m_Position = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// Vertex color.
|
||||
/// </value>
|
||||
public Color color
|
||||
{
|
||||
get { return m_Color; }
|
||||
set
|
||||
{
|
||||
hasColor = true;
|
||||
m_Color = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// Unit vector normal.
|
||||
/// </value>
|
||||
public Vector3 normal
|
||||
{
|
||||
get { return m_Normal; }
|
||||
set
|
||||
{
|
||||
hasNormal = true;
|
||||
m_Normal = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// Vertex tangent (sometimes called binormal).
|
||||
/// </value>
|
||||
public Vector4 tangent
|
||||
{
|
||||
get { return m_Tangent; }
|
||||
set
|
||||
{
|
||||
hasTangent = true;
|
||||
m_Tangent = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// UV 0 channel. Also called textures.
|
||||
/// </value>
|
||||
public Vector2 uv0
|
||||
{
|
||||
get { return m_UV0; }
|
||||
set
|
||||
{
|
||||
hasUV0 = true;
|
||||
m_UV0 = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// UV 2 channel.
|
||||
/// </value>
|
||||
public Vector2 uv2
|
||||
{
|
||||
get { return m_UV2; }
|
||||
set
|
||||
{
|
||||
hasUV2 = true;
|
||||
m_UV2 = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// UV 3 channel.
|
||||
/// </value>
|
||||
public Vector4 uv3
|
||||
{
|
||||
get { return m_UV3; }
|
||||
set
|
||||
{
|
||||
hasUV3 = true;
|
||||
m_UV3 = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// UV 4 channel.
|
||||
/// </value>
|
||||
public Vector4 uv4
|
||||
{
|
||||
get { return m_UV4; }
|
||||
set
|
||||
{
|
||||
hasUV4 = true;
|
||||
m_UV4 = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find if a vertex attribute has been set.
|
||||
/// </summary>
|
||||
/// <param name="attribute">The attribute or attributes to test for.</param>
|
||||
/// <returns>True if this vertex has the specified attributes set, false if they are default values.</returns>
|
||||
public bool HasArrays(VertexAttributes attribute)
|
||||
{
|
||||
return (m_Attributes & attribute) == attribute;
|
||||
}
|
||||
|
||||
public bool hasPosition
|
||||
{
|
||||
get { return (m_Attributes & VertexAttributes.Position) == VertexAttributes.Position; }
|
||||
private set { m_Attributes = value ? (m_Attributes | VertexAttributes.Position) : (m_Attributes & ~(VertexAttributes.Position)); }
|
||||
}
|
||||
|
||||
public bool hasColor
|
||||
{
|
||||
get { return (m_Attributes & VertexAttributes.Color) == VertexAttributes.Color; }
|
||||
private set { m_Attributes = value ? (m_Attributes | VertexAttributes.Color) : (m_Attributes & ~(VertexAttributes.Color)); }
|
||||
}
|
||||
|
||||
public bool hasNormal
|
||||
{
|
||||
get { return (m_Attributes & VertexAttributes.Normal) == VertexAttributes.Normal; }
|
||||
private set { m_Attributes = value ? (m_Attributes | VertexAttributes.Normal) : (m_Attributes & ~(VertexAttributes.Normal)); }
|
||||
}
|
||||
|
||||
public bool hasTangent
|
||||
{
|
||||
get { return (m_Attributes & VertexAttributes.Tangent) == VertexAttributes.Tangent; }
|
||||
private set { m_Attributes = value ? (m_Attributes | VertexAttributes.Tangent) : (m_Attributes & ~(VertexAttributes.Tangent)); }
|
||||
}
|
||||
|
||||
public bool hasUV0
|
||||
{
|
||||
get { return (m_Attributes & VertexAttributes.Texture0) == VertexAttributes.Texture0; }
|
||||
private set { m_Attributes = value ? (m_Attributes | VertexAttributes.Texture0) : (m_Attributes & ~(VertexAttributes.Texture0)); }
|
||||
}
|
||||
|
||||
public bool hasUV2
|
||||
{
|
||||
get { return (m_Attributes & VertexAttributes.Texture1) == VertexAttributes.Texture1; }
|
||||
private set { m_Attributes = value ? (m_Attributes | VertexAttributes.Texture1) : (m_Attributes & ~(VertexAttributes.Texture1)); }
|
||||
}
|
||||
|
||||
public bool hasUV3
|
||||
{
|
||||
get { return (m_Attributes & VertexAttributes.Texture2) == VertexAttributes.Texture2; }
|
||||
private set { m_Attributes = value ? (m_Attributes | VertexAttributes.Texture2) : (m_Attributes & ~(VertexAttributes.Texture2)); }
|
||||
}
|
||||
|
||||
public bool hasUV4
|
||||
{
|
||||
get { return (m_Attributes & VertexAttributes.Texture3) == VertexAttributes.Texture3; }
|
||||
private set { m_Attributes = value ? (m_Attributes | VertexAttributes.Texture3) : (m_Attributes & ~(VertexAttributes.Texture3)); }
|
||||
}
|
||||
|
||||
public void Flip()
|
||||
{
|
||||
if(hasNormal)
|
||||
m_Normal *= -1f;
|
||||
|
||||
if (hasTangent)
|
||||
m_Tangent *= -1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eace57ffc03f348e48d541e3ac67ae90
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
namespace UnityEngine.ProBuilder.Csg
|
||||
{
|
||||
/// <summary>
|
||||
/// Mesh attributes bitmask.
|
||||
/// </summary>
|
||||
[System.Flags]
|
||||
enum VertexAttributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Vertex positions.
|
||||
/// </summary>
|
||||
Position = 0x1,
|
||||
/// <summary>
|
||||
/// First UV channel.
|
||||
/// </summary>
|
||||
Texture0 = 0x2,
|
||||
/// <summary>
|
||||
/// Second UV channel. Commonly called UV2 or Lightmap UVs in Unity terms.
|
||||
/// </summary>
|
||||
Texture1 = 0x4,
|
||||
/// <summary>
|
||||
/// Second UV channel. Commonly called UV2 or Lightmap UVs in Unity terms.
|
||||
/// </summary>
|
||||
Lightmap = 0x4,
|
||||
/// <summary>
|
||||
/// Third UV channel.
|
||||
/// </summary>
|
||||
Texture2 = 0x8,
|
||||
/// <summary>
|
||||
/// Vertex UV4.
|
||||
/// </summary>
|
||||
Texture3 = 0x10,
|
||||
/// <summary>
|
||||
/// Vertex colors.
|
||||
/// </summary>
|
||||
Color = 0x20,
|
||||
/// <summary>
|
||||
/// Vertex normals.
|
||||
/// </summary>
|
||||
Normal = 0x40,
|
||||
/// <summary>
|
||||
/// Vertex tangents.
|
||||
/// </summary>
|
||||
Tangent = 0x80,
|
||||
/// <summary>
|
||||
/// All stored mesh attributes.
|
||||
/// </summary>
|
||||
All = 0xFF
|
||||
};
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7aeb98aaff5054383b10b45f4518f968
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEngine.ProBuilder.Csg
|
||||
{
|
||||
static class VertexUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// Allocate and fill all attribute arrays. This method will fill all arrays, regardless of whether or not real data populates the values (check what attributes a Vertex contains with HasAttribute()).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you are using this function to rebuild a mesh, use SetMesh instead. SetMesh handles setting null arrays where appropriate for you.
|
||||
/// </remarks>
|
||||
/// <seealso cref="SetMesh"/>
|
||||
/// <param name="vertices">The source vertices.</param>
|
||||
/// <param name="position">A new array of the vertex position values.</param>
|
||||
/// <param name="color">A new array of the vertex color values.</param>
|
||||
/// <param name="uv0">A new array of the vertex uv0 values.</param>
|
||||
/// <param name="normal">A new array of the vertex normal values.</param>
|
||||
/// <param name="tangent">A new array of the vertex tangent values.</param>
|
||||
/// <param name="uv2">A new array of the vertex uv2 values.</param>
|
||||
/// <param name="uv3">A new array of the vertex uv3 values.</param>
|
||||
/// <param name="uv4">A new array of the vertex uv4 values.</param>
|
||||
public static void GetArrays(
|
||||
IList<Vertex> vertices,
|
||||
out Vector3[] position,
|
||||
out Color[] color,
|
||||
out Vector2[] uv0,
|
||||
out Vector3[] normal,
|
||||
out Vector4[] tangent,
|
||||
out Vector2[] uv2,
|
||||
out List<Vector4> uv3,
|
||||
out List<Vector4> uv4)
|
||||
{
|
||||
GetArrays(vertices, out position, out color, out uv0, out normal, out tangent, out uv2, out uv3, out uv4, VertexAttributes.All);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocate and fill the requested attribute arrays.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you are using this function to rebuild a mesh, use SetMesh instead. SetMesh handles setting null arrays where appropriate for you.
|
||||
/// </remarks>
|
||||
/// <seealso cref="SetMesh"/>
|
||||
/// <param name="vertices">The source vertices.</param>
|
||||
/// <param name="position">A new array of the vertex position values if requested by the attributes parameter, or null.</param>
|
||||
/// <param name="color">A new array of the vertex color values if requested by the attributes parameter, or null.</param>
|
||||
/// <param name="uv0">A new array of the vertex uv0 values if requested by the attributes parameter, or null.</param>
|
||||
/// <param name="normal">A new array of the vertex normal values if requested by the attributes parameter, or null.</param>
|
||||
/// <param name="tangent">A new array of the vertex tangent values if requested by the attributes parameter, or null.</param>
|
||||
/// <param name="uv2">A new array of the vertex uv2 values if requested by the attributes parameter, or null.</param>
|
||||
/// <param name="uv3">A new array of the vertex uv3 values if requested by the attributes parameter, or null.</param>
|
||||
/// <param name="uv4">A new array of the vertex uv4 values if requested by the attributes parameter, or null.</param>
|
||||
/// <param name="attributes">A flag with the MeshAttributes requested.</param>
|
||||
/// <seealso cref="HasArrays"/>
|
||||
public static void GetArrays(
|
||||
IList<Vertex> vertices,
|
||||
out Vector3[] position,
|
||||
out Color[] color,
|
||||
out Vector2[] uv0,
|
||||
out Vector3[] normal,
|
||||
out Vector4[] tangent,
|
||||
out Vector2[] uv2,
|
||||
out List<Vector4> uv3,
|
||||
out List<Vector4> uv4,
|
||||
VertexAttributes attributes)
|
||||
{
|
||||
if (vertices == null)
|
||||
throw new ArgumentNullException("vertices");
|
||||
|
||||
int vc = vertices.Count;
|
||||
var first = vc < 1 ? new Vertex() : vertices[0];
|
||||
|
||||
bool hasPosition = ((attributes & VertexAttributes.Position) == VertexAttributes.Position) && first.hasPosition;
|
||||
bool hasColor = ((attributes & VertexAttributes.Color) == VertexAttributes.Color) && first.hasColor;
|
||||
bool hasUv0 = ((attributes & VertexAttributes.Texture0) == VertexAttributes.Texture0) && first.hasUV0;
|
||||
bool hasNormal = ((attributes & VertexAttributes.Normal) == VertexAttributes.Normal) && first.hasNormal;
|
||||
bool hasTangent = ((attributes & VertexAttributes.Tangent) == VertexAttributes.Tangent) && first.hasTangent;
|
||||
bool hasUv2 = ((attributes & VertexAttributes.Texture1) == VertexAttributes.Texture1) && first.hasUV2;
|
||||
bool hasUv3 = ((attributes & VertexAttributes.Texture2) == VertexAttributes.Texture2) && first.hasUV3;
|
||||
bool hasUv4 = ((attributes & VertexAttributes.Texture3) == VertexAttributes.Texture3) && first.hasUV4;
|
||||
|
||||
position = hasPosition ? new Vector3[vc] : null;
|
||||
color = hasColor ? new Color[vc] : null;
|
||||
uv0 = hasUv0 ? new Vector2[vc] : null;
|
||||
normal = hasNormal ? new Vector3[vc] : null;
|
||||
tangent = hasTangent ? new Vector4[vc] : null;
|
||||
uv2 = hasUv2 ? new Vector2[vc] : null;
|
||||
uv3 = hasUv3 ? new List<Vector4>(vc) : null;
|
||||
uv4 = hasUv4 ? new List<Vector4>(vc) : null;
|
||||
|
||||
for (int i = 0; i < vc; i++)
|
||||
{
|
||||
if (hasPosition)
|
||||
position[i] = vertices[i].position;
|
||||
if (hasColor)
|
||||
color[i] = vertices[i].color;
|
||||
if (hasUv0)
|
||||
uv0[i] = vertices[i].uv0;
|
||||
if (hasNormal)
|
||||
normal[i] = vertices[i].normal;
|
||||
if (hasTangent)
|
||||
tangent[i] = vertices[i].tangent;
|
||||
if (hasUv2)
|
||||
uv2[i] = vertices[i].uv2;
|
||||
if (hasUv3)
|
||||
uv3.Add(vertices[i].uv3);
|
||||
if (hasUv4)
|
||||
uv4.Add(vertices[i].uv4);
|
||||
}
|
||||
}
|
||||
|
||||
public static Vertex[] GetVertices(this Mesh mesh)
|
||||
{
|
||||
if (mesh == null)
|
||||
return null;
|
||||
|
||||
int vertexCount = mesh.vertexCount;
|
||||
Vertex[] v = new Vertex[vertexCount];
|
||||
|
||||
Vector3[] positions = mesh.vertices;
|
||||
Color[] colors = mesh.colors;
|
||||
Vector3[] normals = mesh.normals;
|
||||
Vector4[] tangents = mesh.tangents;
|
||||
Vector2[] uv0s = mesh.uv;
|
||||
Vector2[] uv2s = mesh.uv2;
|
||||
List<Vector4> uv3s = new List<Vector4>();
|
||||
List<Vector4> uv4s = new List<Vector4>();
|
||||
mesh.GetUVs(2, uv3s);
|
||||
mesh.GetUVs(3, uv4s);
|
||||
|
||||
bool _hasPositions = positions != null && positions.Length == vertexCount;
|
||||
bool _hasColors = colors != null && colors.Length == vertexCount;
|
||||
bool _hasNormals = normals != null && normals.Length == vertexCount;
|
||||
bool _hasTangents = tangents != null && tangents.Length == vertexCount;
|
||||
bool _hasUv0 = uv0s != null && uv0s.Length == vertexCount;
|
||||
bool _hasUv2 = uv2s != null && uv2s.Length == vertexCount;
|
||||
bool _hasUv3 = uv3s.Count == vertexCount;
|
||||
bool _hasUv4 = uv4s.Count == vertexCount;
|
||||
|
||||
for (int i = 0; i < vertexCount; i++)
|
||||
{
|
||||
v[i] = new Vertex();
|
||||
|
||||
if (_hasPositions)
|
||||
v[i].position = positions[i];
|
||||
|
||||
if (_hasColors)
|
||||
v[i].color = colors[i];
|
||||
|
||||
if (_hasNormals)
|
||||
v[i].normal = normals[i];
|
||||
|
||||
if (_hasTangents)
|
||||
v[i].tangent = tangents[i];
|
||||
|
||||
if (_hasUv0)
|
||||
v[i].uv0 = uv0s[i];
|
||||
|
||||
if (_hasUv2)
|
||||
v[i].uv2 = uv2s[i];
|
||||
|
||||
if (_hasUv3)
|
||||
v[i].uv3 = uv3s[i];
|
||||
|
||||
if (_hasUv4)
|
||||
v[i].uv4 = uv4s[i];
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace mesh values with vertex array. Mesh is cleared during this function, so be sure to set the triangles after calling.
|
||||
/// </summary>
|
||||
/// <param name="mesh">The target mesh.</param>
|
||||
/// <param name="vertices">The vertices to replace the mesh attributes with.</param>
|
||||
public static void SetMesh(Mesh mesh, IList<Vertex> vertices)
|
||||
{
|
||||
if (mesh == null)
|
||||
throw new ArgumentNullException("mesh");
|
||||
|
||||
if (vertices == null)
|
||||
throw new ArgumentNullException("vertices");
|
||||
|
||||
Vector3[] positions = null;
|
||||
Color[] colors = null;
|
||||
Vector2[] uv0s = null;
|
||||
Vector3[] normals = null;
|
||||
Vector4[] tangents = null;
|
||||
Vector2[] uv2s = null;
|
||||
List<Vector4> uv3s = null;
|
||||
List<Vector4> uv4s = null;
|
||||
|
||||
GetArrays(vertices, out positions,
|
||||
out colors,
|
||||
out uv0s,
|
||||
out normals,
|
||||
out tangents,
|
||||
out uv2s,
|
||||
out uv3s,
|
||||
out uv4s);
|
||||
|
||||
mesh.Clear();
|
||||
|
||||
Vertex first = vertices[0];
|
||||
|
||||
if (first.hasPosition) mesh.vertices = positions;
|
||||
if (first.hasColor) mesh.colors = colors;
|
||||
if (first.hasUV0) mesh.uv = uv0s;
|
||||
if (first.hasNormal) mesh.normals = normals;
|
||||
if (first.hasTangent) mesh.tangents = tangents;
|
||||
if (first.hasUV2) mesh.uv2 = uv2s;
|
||||
if (first.hasUV3)
|
||||
if (uv3s != null)
|
||||
mesh.SetUVs(2, uv3s);
|
||||
if (first.hasUV4)
|
||||
if (uv4s != null)
|
||||
mesh.SetUVs(3, uv4s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Linearly interpolate between two vertices.
|
||||
/// </summary>
|
||||
/// <param name="x">Left parameter.</param>
|
||||
/// <param name="y">Right parameter.</param>
|
||||
/// <param name="weight">The weight of the interpolation. 0 is fully x, 1 is fully y.</param>
|
||||
/// <returns>A new vertex interpolated by weight between x and y.</returns>
|
||||
public static Vertex Mix(this Vertex x, Vertex y, float weight)
|
||||
{
|
||||
float i = 1f - weight;
|
||||
|
||||
Vertex v = new Vertex();
|
||||
|
||||
v.position = x.position * i + y.position * weight;
|
||||
|
||||
if (x.hasColor && y.hasColor)
|
||||
v.color = x.color * i + y.color * weight;
|
||||
else if (x.hasColor)
|
||||
v.color = x.color;
|
||||
else if (y.hasColor)
|
||||
v.color = y.color;
|
||||
|
||||
if (x.hasNormal && y.hasNormal)
|
||||
v.normal = x.normal * i + y.normal * weight;
|
||||
else if (x.hasNormal)
|
||||
v.normal = x.normal;
|
||||
else if (y.hasNormal)
|
||||
v.normal = y.normal;
|
||||
|
||||
if (x.hasTangent && y.hasTangent)
|
||||
v.tangent = x.tangent * i + y.tangent * weight;
|
||||
else if (x.hasTangent)
|
||||
v.tangent = x.tangent;
|
||||
else if (y.hasTangent)
|
||||
v.tangent = y.tangent;
|
||||
|
||||
if (x.hasUV0 && y.hasUV0)
|
||||
v.uv0 = x.uv0 * i + y.uv0 * weight;
|
||||
else if (x.hasUV0)
|
||||
v.uv0 = x.uv0;
|
||||
else if (y.hasUV0)
|
||||
v.uv0 = y.uv0;
|
||||
|
||||
if (x.hasUV2 && y.hasUV2)
|
||||
v.uv2 = x.uv2 * i + y.uv2 * weight;
|
||||
else if (x.hasUV2)
|
||||
v.uv2 = x.uv2;
|
||||
else if (y.hasUV2)
|
||||
v.uv2 = y.uv2;
|
||||
|
||||
if (x.hasUV3 && y.hasUV3)
|
||||
v.uv3 = x.uv3 * i + y.uv3 * weight;
|
||||
else if (x.hasUV3)
|
||||
v.uv3 = x.uv3;
|
||||
else if (y.hasUV3)
|
||||
v.uv3 = y.uv3;
|
||||
|
||||
if (x.hasUV4 && y.hasUV4)
|
||||
v.uv4 = x.uv4 * i + y.uv4 * weight;
|
||||
else if (x.hasUV4)
|
||||
v.uv4 = x.uv4;
|
||||
else if (y.hasUV4)
|
||||
v.uv4 = y.uv4;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transform a vertex into world space.
|
||||
/// </summary>
|
||||
/// <param name="transform">The transform to apply.</param>
|
||||
/// <param name="vertex">A model space vertex.</param>
|
||||
/// <returns>A new vertex in world coordinate space.</returns>
|
||||
public static Vertex TransformVertex(this Transform transform, Vertex vertex)
|
||||
{
|
||||
var v = new Vertex();
|
||||
|
||||
if (vertex.HasArrays(VertexAttributes.Position))
|
||||
v.position = transform.TransformPoint(vertex.position);
|
||||
|
||||
if (vertex.HasArrays(VertexAttributes.Color))
|
||||
v.color = vertex.color;
|
||||
|
||||
if (vertex.HasArrays(VertexAttributes.Normal))
|
||||
v.normal = transform.TransformDirection(vertex.normal);
|
||||
|
||||
if (vertex.HasArrays(VertexAttributes.Tangent))
|
||||
v.tangent = transform.rotation * vertex.tangent;
|
||||
|
||||
if (vertex.HasArrays(VertexAttributes.Texture0))
|
||||
v.uv0 = vertex.uv0;
|
||||
|
||||
if (vertex.HasArrays(VertexAttributes.Texture1))
|
||||
v.uv2 = vertex.uv2;
|
||||
|
||||
if (vertex.HasArrays(VertexAttributes.Texture2))
|
||||
v.uv3 = vertex.uv3;
|
||||
|
||||
if (vertex.HasArrays(VertexAttributes.Texture3))
|
||||
v.uv4 = vertex.uv4;
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a629cb73b331b40449fd411043caf7d3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "Unity.ProBuilder.Csg",
|
||||
"references": [],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": []
|
||||
}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26434c0544da24d83a23c99deaa60965
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user