Copying Mesh effectively - unity3d

I've needed to copy a mesh with submeshes in case there are more than one material. I've came up with this code.
public static Mesh Copy(this Mesh original)
{
Mesh m = new Mesh();
original.CopyTo(ref m);
return m;
}
public static void CopyTo(this Mesh original, ref Mesh copy)
{
copy.name = original.name;
copy.vertices = original.vertices;
copy.normals = original.normals;
copy.tangents = original.tangents;
copy.triangles = original.triangles;
copy.bounds = original.bounds;
copy.uv = original.uv;
copy.uv2 = original.uv2;
copy.uv3 = original.uv3;
copy.uv4 = original.uv4;
copy.uv5 = original.uv5;
copy.uv6 = original.uv6;
copy.uv7 = original.uv7;
copy.uv8 = original.uv8;
copy.colors = original.colors;
copy.bindposes = original.bindposes;
copy.boneWeights = original.boneWeights;
copy.indexFormat = original.indexFormat;
copy.indexBufferTarget = original.indexBufferTarget;
copy.vertexBufferTarget = original.vertexBufferTarget;
copy.subMeshCount = original.subMeshCount;
for (int i = 0; i < original.subMeshCount; i++)
{
copy.SetSubMesh(i, original.GetSubMesh(i));
}
}
Do I miss something?
Also does it save any memory if I use CopyTo to reuse existing mesh?

Related

Holes in Mesh only showing from one side

For a sailing game I'm working on, I've added functionality to programmatically create damage holes in a mesh (e.g. cannonball holes in a sail). This is largely based on the method here (link to the example code here)
private void MessWithMesh() {
filter = this.transform.parent.gameObject.GetComponent<MeshFilter>();
mesh = filter.mesh;
filter.mesh = GenerateMeshWithHoles();
}
private IEnumerator GenerateTrisWithVertex() {
// Destroying the sail won't work until this has finished, but it only takes a second or two so I don't think anybody will notice.
trisWithVertex = new List<int>[origvertices.Length];
for (int i = 0; i <origvertices.Length; ++i)
{
trisWithVertex[i] = ArrayHelper.IndexOf(origtriangles, i);
yield return null;
}
yield return null;
}
Mesh GenerateMeshWithHoles()
{
float damageRadius = 1f;
Transform parentTransform = this.transform.parent.transform;
Hole[] holes = this.GetComponentsInChildren<Hole>();
foreach (Hole hole in holes) {
Vector3 trackPos = hole.transform.position;
float closest = float.MaxValue;
int closestIndex = -1;
int countDisabled = 0;
damageRadius = hole.diameter;
for (int i = 0; i <origvertices.Length; ++i)
{
Vector3 v = new Vector3(origvertices[i].x * parentTransform.localScale.x, origvertices[i].y * parentTransform.localScale.y, origvertices[i].z * parentTransform.localScale.z) + parentTransform.position;
Vector3 difference = v - trackPos;
if (difference.magnitude < closest)
{
closest = difference.magnitude;
closestIndex = i;
}
if (difference.magnitude < damageRadius)
{
for (int j = 0; j <trisWithVertex[i].Count; ++j)
{
int value = trisWithVertex[i][j];
int remainder = value % 3;
trianglesDisabled[value - remainder] = true;
trianglesDisabled[value - remainder + 1] = true;
trianglesDisabled[value - remainder + 2] = true;
countDisabled++;
}
}
}
// If no triangles were removed, then we'll just remove the one that was closest to the hole.
// This shouldn't really happen, but in case the hole is off by a bit from where it should have hit the mesh, we'll do this to make sure there's at least a hole.
if (countDisabled == 0 && closestIndex > -1) {
Debug.Log("Removing closest vertex: " + closestIndex);
for (int j = 0; j < trisWithVertex[closestIndex].Count; ++j)
{
int value = trisWithVertex[closestIndex][j];
int remainder = value % 3;
trianglesDisabled[value - remainder] = true;
trianglesDisabled[value - remainder + 1] = true;
trianglesDisabled[value - remainder + 2] = true;
}
}
}
triangles = ArrayHelper.RemoveAllSpecifiedIndicesFromArray(origtriangles, trianglesDisabled).ToArray();
mesh.SetTriangles(triangles, 0);
for (int i = 0; i <trianglesDisabled.Length; ++i)
trianglesDisabled[i] = false;
return mesh;
}
When a cannonball hits the sail, I add a Hole object at the location of the impact, and I call MessWithMesh. The holes are often generated correctly, but many times they're only visible from one side of the sail (it looks fully intact from the other side). It's often visible from the opposite side of the sail that the cannonball impacted (the far side, not the near side), if that's at all helpful. The ship I'm using is this free asset.
I'm not really familiar with meshes, so I don't really understand what's going on.

Are there any examples of pedestrian modelling in repast simphony?

Are there any examples of pedestrian modelling in repast simphony? I am novice in repast and was trying to model a simple pedestrian movement simulation. Any pointers to useful resources/ examples?
Andrew Crook's blog GIS and Agent-Based Modeling (http://www.gisagents.org/) has lots of interesting links to pedestrian models. I think there are even some specific to Repast.
Repast isn't the best for open libraries, but I've had some luck searching GitHub. Here's a basic ped agent I built once, you'll have to build a context with a scheduler class to call the pedestrians:
context:
public class RoadBuilder extends DefaultContext<Object> implements ContextBuilder<Object> {
context.setId("driving1");
ContinuousSpaceFactory spaceFactory =
ContinuousSpaceFactoryFinder.createContinuousSpaceFactory(null);
ContinuousSpace<Object> space =
spaceFactory.createContinuousSpace("space",context, new SimpleCartesianAdder<Object>(),
new StrictBorders(), roadL, worldW);
clock = RunEnvironment.getInstance().getCurrentSchedule();
flowSource = new Scheduler();
context.add(flowSource);
return context;
}
the scheduler:
public class Scheduler {
static ArrayList<Ped> allPeds;
#ScheduledMethod(start = 1, interval = 1, priority = 1)
public void doStuff() {
Ped addedPed = addPed(1);
allPeds.add(addedPed);
for (Ped a : allPeds) {
a.calc();}
for (Ped b : allPeds) {
b.walk();}
public Ped addPed(int direction) {
Context<Object> context = ContextUtils.getContext(this);
ContinuousSpace<Object> space = (ContinuousSpace<Object>) context.getProjection("space");
Ped newPed = new Ped(space,direction);
context.add(newPed);
space.moveTo(newPed,xPlacement,yPlacement);
newPed.myLoc = space.getLocation(newPed);
return(newPed);
}
The pedestrians - This is based on a "generalized force model" (source: Simulating Dynamical Features of Escape Panic - Helbing, Farkas, and Vicsek - https://arxiv.org/pdf/cond-mat/0009448.pdf)
and here's the pedestrian class
public class Ped {
private ContinuousSpace<Object> space;
private List<Double> forcesX, forcesY;
private NdPoint endPt;
private Random rnd = new Random();
private int age;
private double endPtDist, endPtTheta, critGap;
private double side = RoadBuilder.sidewalk;
private double wS, etaS, wV, etaV, sigR; //errors
private double m, horiz, A, B, k, r; //interactive force constants (accT is also)
public NdPoint myLoc, destination;
public double[] v, dv, newV;
public double xTime, accT, maxV, xLoc, yLoc;
public int dir; // dir = 1 walks up, -1 walks down
public void calc() {
myLoc = space.getLocation(this);
dv = accel(myLoc,dir,destination);
newV = sumV(v,dv);
newV = limitV(newV);
}
public void walk() {
v = newV;
move(myLoc,v);
}
public double[] accel(NdPoint location, int direct, NdPoint endPt) {
forcesX = new ArrayList<Double>();
forcesY = new ArrayList<Double>();
double xF, yF;
double[] acc;
xF = yF = 0;
//calculate heading to endpoint
endPtDist = space.getDistance(location, endPt);
double endPtDelX = endPt.getX()-location.getX();
endPtTheta = FastMath.asin((double)direct*endPtDelX/endPtDist);
if (direct == -1) {
endPtTheta += Math.PI;}
//calculate motive force
Double motFx = (maxV*Math.sin(endPtTheta) - v[0])/accT;
Double motFy = (maxV*Math.cos(endPtTheta) - v[1])/accT;
forcesX.add(motFx);
forcesY.add(motFy);
//calculate interactive forces
//TODO: write code to make a threshold for interaction instead of the arbitrary horizon
for (Ped a : Scheduler.allPeds) {
if (a != this) {
NdPoint otherLoc = space.getLocation(a);
double otherY = otherLoc.getY();
double visible = Math.signum((double)dir*(otherY-yLoc));
if (visible == 1) { //peds only affected by those in front of them
double absDist = space.getDistance(location, otherLoc);
if (absDist < horiz) {
double delX = location.getX()-otherLoc.getX();
double delY = location.getY()-otherLoc.getY();
double delXabs = Math.abs(delX);
double signFx = Math.signum(delX);
double signFy = Math.signum(delY);
double theta = FastMath.asin(delXabs/absDist);
double rij = r + a.r;
Double interFx = signFx*A*Math.exp((rij-absDist)/B)*Math.sin(theta)/m;
Double interFy = signFy*A*Math.exp((rij-absDist)/B)*Math.cos(theta)/m;
forcesX.add(interFx);
forcesY.add(interFy);}}}}
//sum all forces
for (Double b : forcesX) {
xF += b;}
for (Double c : forcesY) {
yF += c;}
acc = new double[] {xF, yF};
return acc;
}
public void move(NdPoint loc, double[] displacement) {
double[] zero = new double[] {0,0};
double yl = loc.getY();
if (displacement != zero) {
space.moveByDisplacement(this,displacement);
myLoc = space.getLocation(this);}
}
public double[] limitV(double[] input) {
double totalV, norm;
if (this.dir == 1) {
if (input[1] < 0) {
input[1] = 0;}}
else {
if (input[1] > 0) {
input[1] = 0;}}
totalV = Math.sqrt(input[0]*input[0] + input[1]*input[1]);
if (totalV > maxV) {
norm = maxV/totalV;
input[0] = input[0]*norm;
input[1] = input[1]*norm;}
return input;
}
public double[] sumV(double[] a, double[] b) {
double[] c = new double[2];
for (int i = 0; i < 2; i++) {
c[i] = a[i] + b[i];}
return c;
}
public Ped(ContinuousSpace<Object> contextSpace, int direction) {
space = contextSpace;
maxV = rnd.nextGaussian() * UserPanel.pedVsd + UserPanel.pedVavg;
dir = direction; // 1 moves up, -1 moves down
v = new double[] {0,(double)dir*.5*maxV};
age = 0;
//3-circle variables - from Helbing, et al (2000) [r from Rouphail et al 1998]
accT = 0.5/UserPanel.tStep; //acceleration time
m = 80; //avg ped mass in kg
horiz = 5/RoadBuilder.spaceScale; //distance at which peds affect each other
A = 2000*UserPanel.tStep*UserPanel.tStep/RoadBuilder.spaceScale; //ped interaction constant (kg*space units/time units^2)
B = 0.08/RoadBuilder.spaceScale; //ped distance interaction constant (space units)
k = 120000*UserPanel.tStep*UserPanel.tStep; //wall force constant
r = 0.275/RoadBuilder.spaceScale; //ped radius (space units)
}
}

How to cut a mesh by plane in Unity3d

I want to cut meshes by plane.
try this code, but get only one of parts of cutting mesh.
Screenshot 1
Screenshot 2
public void SliceIt()
{
Vector3[] vertices = mesh.vertices;
Transform clone = clone = ((Transform)Instantiate(transform, transform.position + new Vector3(0, 0.25f, 0), transform.rotation));
Mesh meshSlice = clone.GetComponent<MeshFilter>().sharedMesh;
Vector3[] verticesSlice = meshSlice.vertices;
List<Vector3> verticesSlice2 = new List<Vector3>();
Mesh cutplanemesh = cutplane.GetComponent<MeshFilter>().sharedMesh;
Vector3[] cutplanevertices = cutplanemesh.vertices;
p1 = cutplane.TransformPoint(cutplanevertices[40]);
p2 = cutplane.TransformPoint(cutplanevertices[20]);
p3 = cutplane.TransformPoint(cutplanevertices[0]);
var myplane = new Plane(p1, p2, p3);
for (var i = 0; i < vertices.Length; i++)
{
var tmpverts = transform.TransformPoint(vertices[i]); // original object vertices
if (myplane.GetSide(tmpverts))
{
vertices[i] = transform.InverseTransformPoint(new Vector3(tmpverts.x, tmpverts.y - (myplane.GetDistanceToPoint(tmpverts)), tmpverts.z));
verticesSlice[i] = transform.InverseTransformPoint(new Vector3(tmpverts.x, tmpverts.y, tmpverts.z));
var v = transform.InverseTransformPoint(new Vector3(tmpverts.x, tmpverts.y, tmpverts.z));
verticesSlice2.Add(v);
}
else
{
var v = transform.InverseTransformPoint(new Vector3(tmpverts.x, tmpverts.y - (myplane.GetDistanceToPoint(tmpverts)), tmpverts.z));
verticesSlice2.Add(v);
}
}
mesh.vertices = verticesSlice;
mesh.RecalculateBounds();
meshSlice.vertices = verticesSlice2.ToArray();
meshSlice.RecalculateBounds();
}
I got this code from here.
I also read this question, but I couldn't figure how to split triangles which belong to positive and negative sides of plane.
You can use already existing assets on asset store:
https://www.assetstore.unity3d.com/#!/content/59618
It is not only cut a mesh, it also cut colliders, do some optimizations and it is extandable.

How to set second material to a second submesh in a combined mesh?

I have this code (not originally my invention) that is working fine, but I have hit upon a problem with it. I can't seem to render the second submesh, with another material.
I can't figure out the problem lies in [renderer] part or the 2nd "submesh" that is perhaps never combining.
#script RequireComponent(MeshFilter)
#script RequireComponent(MeshRenderer)
private var matarray : Material[] = new Material[2];
var mat : Material;
var mat2 : Material;
function Start () {
matarray[0] = mat;
matarray[1] = mat2;
for (var child in transform)
child.position += transform.position;
transform.position = Vector3.zero;
transform.rotation = Quaternion.identity;
var meshFilters = GetComponentsInChildren(MeshFilter);
var combine : CombineInstance[] = new CombineInstance[meshFilters.Length-1];
var index = 0;
for (var i = 0; i < meshFilters.Length; i++) {
if (meshFilters[i].sharedMesh == null)
continue;
combine[index].mesh = meshFilters[i].sharedMesh;
combine[index++].transform = meshFilters[i].transform.localToWorldMatrix;
renderer.sharedMaterials = matarray;
meshFilters[i].active = false;
}
GetComponent(MeshFilter).mesh = new Mesh();
GetComponent(MeshFilter).mesh.CombineMeshes(combine);
renderer.active = true;
//here seems to be the trouble.
renderer.sharedMaterials = matarray;
}
Alternatively I have tried,
renderer.sharedMaterials[1] = matarray[1];
In short, I'm in trouble. I have to save few draw calls, which is not looking good unless this gets fixed.

Add Object To Other Object Scripts that require an Object

Ok , I have problem with adding object let's first see what is this about.
I Have Map when i click at map i create Sphere on map.
then i serialized the point, msg and name .....
void Start () {
Ser = new Serial();
Ser.read();
for (int i =0 ; i < Ser.list.Count; i++)
{
Data d = new Data();
d = Ser.list[i];
GameObject a = GameObject.CreatePrimitive(PrimitiveType.Sphere);
a.name = d.Id;
a.transform.position = new Vector3(d.x,d.y,0);
a.transform.localScale =new Vector3(0.5f , 0.5f , 0.5f);
Follow putTarget = new Follow();
Data Pos_In_File = new Data();
Pos_In_File = Ser.list[i];
GUIText GText = new GUIText();
Vector3 SP = new Vector3();
GameObject TextObj = new GameObject("GUIText" + Convert.ToString(i));
GText = (GUIText)TextObj.AddComponent(typeof(GUIText));
GText.text = Pos_In_File.msg;
GText.material.color = new Color(0 , 0 , 1);
GText.fontSize = 20;
GText.fontStyle = FontStyle.Bold;
SP = Camera.main.WorldToViewportPoint(new Vector3(Pos_In_File.x , Pos_In_File.y , Pos_In_File.z));
TextObj.transform.position = SP;
TextObj.AddComponent(typeof(Follow));
GameObject OBJ = GameObject.Find(Pos_In_File.Id);
putTarget =GetComponent<Follow>();
putTarget.target = OBJ.transform;
}
}
now in last three lines i want to add OBJ to TextOBJ->Follow(Script)->target
What i am messing up ?
i asked this quastion long ago my software have been finnished a 10 month
and the i get through this problem is
void Start () {
Resources.UnloadUnusedAssets();
Ser = new Serial();
Screen.fullScreen = true;
Ser.read();
for (int i =0 ; i < Ser.list.Count; i++)
{
Data d = new Data();
d = Ser.list[i];
GameObject a = GameObject.CreatePrimitive(PrimitiveType.Sphere);
a.name = d.Id;
a.transform.position = new Vector3(d.x,d.y,0);
a.renderer.material.color = Color.green;
Data Pos_In_File = new Data();
Pos_In_File = Ser.list[i];
GUIText GText = new GUIText();
Vector3 SP = new Vector3();
GameObject TextObj = new GameObject(Pos_In_File.Id+"h");
GText = (GUIText)TextObj.AddComponent(typeof(GUIText));
GText.text = Pos_In_File.msg;
GText.material.color = new Color(0 , 0 , 1);
GText.fontSize = 20 + (int)Camera.main.transform.position.z;
GText.fontStyle = FontStyle.Bold;
SP = Camera.main.WorldToViewportPoint(new Vector3(Pos_In_File.x , Pos_In_File.y , Pos_In_File.z));
TextObj.transform.position = SP;
TextObj.AddComponent(typeof(Follow));
}