private void CreateMesh(ParseTree parseTree, ParseTreeNode node, IReadOnlyList <Material> grammarMaterials) { var submeshes = new List <Tuple <Mesh, int> >(); foreach (var pair in node.GetLeafNodes(parseTree).Select(n => n.Shape) .GroupBy(p => p.MaterialID, p => p, (key, p) => new { Material = key, GeometricModel = p })) { var mesh = new Mesh(); mesh.CombineMeshes(pair.GeometricModel.Select(model => new CombineInstance { mesh = MeshUtilities.MeshFromGeometricModel(model), transform = MeshUtilities.MatrixFromArray(model.Transform) }).ToArray()); submeshes.Add(Tuple.Create(mesh, pair.Material)); } objectMesh = new Mesh(); var finalCombine = new List <CombineInstance>(); var materials = new List <Material>(); foreach (var m in submeshes) { finalCombine.Add(new CombineInstance { mesh = m.Item1, transform = Matrix4x4.identity }); materials.Add(grammarMaterials[m.Item2]); } objectMesh.CombineMeshes(finalCombine.ToArray(), false); MeshFilter.sharedMesh = objectMesh; MeshRenderer.sharedMaterials = materials.ToArray(); transform.localPosition = new Vector3(0, 0, 0); }
public static bool IsEarTip(List <Vector3> vertices, List <PolyVertex> pvs, PolyVertex pv) { if (pv.wasRemoved || !pv.isConvex) { return(false); } var prev = pv.prevIndex; var curr = pv.currIndex; var next = pv.nextIndex; var prevVert = vertices[prev]; var currVert = vertices[curr]; var nextVert = vertices[next]; var isEar = true; foreach (var p in pvs) { if (!p.wasRemoved && !p.isConvex && p.currIndex != prev && p.currIndex != curr && p.currIndex != next) { if (MeshUtilities.IsPointInTriangle(vertices[p.currIndex], prevVert, currVert, nextVert, true, true)) { isEar = false; break; } } } return(isEar); }
public virtual void LoadBlock(MeshData d, WorldGeneration w) { Vector3 o = worldPosition; MeshUtilities.FaceUp(d, o); Block n = w.GetBlock(x, y, z + 1); if (n == null || !n.isSolid) { MeshUtilities.FaceNorth(d, o); } Block s = w.GetBlock(x, y, z - 1); if (s == null || !s.isSolid) { MeshUtilities.FaceSouth(d, o); } Block we = w.GetBlock(x - 1, y, z); if (we == null || !we.isSolid) { MeshUtilities.FaceWest(d, o); } Block e = w.GetBlock(x + 1, y, z); if (e == null || !e.isSolid) { MeshUtilities.FaceEast(d, o); } }
private void Start() { // Reorient the transforms if they are not on the diagonal // pointing towards the world origin. Vector3 min, max; min.x = Mathf.Min(minCorner.position.x, maxCorner.position.x); min.y = Mathf.Min(minCorner.position.y, maxCorner.position.y); min.z = Mathf.Min(minCorner.position.z, maxCorner.position.z); max.x = Mathf.Max(minCorner.position.x, maxCorner.position.x); max.y = Mathf.Max(minCorner.position.y, maxCorner.position.y); max.z = Mathf.Max(minCorner.position.z, maxCorner.position.z); minCorner.position = min; maxCorner.position = max; // Setup the mesh generation. int xCuts = Mathf.FloorToInt((max.x - min.x) / detailStep); int zCuts = Mathf.FloorToInt((max.z - min.z) / detailStep); surfaceMesh = MeshUtilities.GenerateGrid(xCuts, zCuts, detailStep); // Assign the generated mesh data and create the mesh components. MeshRenderer MR = gameObject.AddComponent <MeshRenderer>(); MeshFilter MF = gameObject.AddComponent <MeshFilter>(); MR.material = fluidMaterial; MF.mesh = surfaceMesh; // Make this liquid accessible to other scene objects. SceneLiquids.Add(this); }
/// <summary> /// Instantiates new GameObject at the pivot of node specified by id. /// </summary> /// <param name="nodeId">The node Id from current parse tree.</param> /// <returns>Instantiated GameObject.</returns> public GameObject AttachGameObjectToNode(uint nodeId) { var node = ParseTree[nodeId]; var newObject = new GameObject(); newObject.transform.SetParent(transform); newObject.transform.position = MeshUtilities.MatrixFromArray(node.Shape.Transform).ExtractPosition(); return(newObject); }
/// <summary> /// Updates highlights of selected parse tree nodes visible in scene view. /// </summary> public void UpdateNodeHighlights() { MeshHighlights = treeViewState.selectedIDs.Where(id => ParseTree[(uint)id].Rule != "ROOT") .Select(id => { var node = ParseTree[(uint)id]; var matrix = MeshUtilities.MatrixFromArray(node.Shape.Transform); return(new MeshGizmoData { Position = matrix.ExtractPosition(), Rotation = matrix.ExtractRotation(), Scale = matrix.ExtractScale() + new Vector3(0.05f, 0.05f, 0.05f), Model = node.Shape }); }) .ToList(); }
/// <summary> /// Generates the mesh with low-poly rendering. /// </summary> public static Mesh SetupFlatMesh(Mesh p_mesh) { int l_triangleCount = p_mesh.triangles.Length / 3; var l_vertices = new List <Vector3>(p_mesh.vertexCount); var l_triangles = new List <int>(l_triangleCount * 3); var l_normals = new List <Vector3>(p_mesh.vertexCount); int l_vertexCount = 0; for (int i = 0; i < l_triangleCount; i++) { // Get the three vertices of triangle int l_triangleIndex = i * 3; int l_vertexIndexA = p_mesh.triangles[l_triangleIndex]; int l_vertexIndexB = p_mesh.triangles[l_triangleIndex + 1]; int l_vertexIndexC = p_mesh.triangles[l_triangleIndex + 2]; Vector3 l_vertexPositionA = p_mesh.vertices[l_vertexIndexA]; Vector3 l_vertexPositionB = p_mesh.vertices[l_vertexIndexB]; Vector3 l_vertexPositionC = p_mesh.vertices[l_vertexIndexC]; //Vertices l_vertices.Add(l_vertexPositionA); l_vertices.Add(l_vertexPositionB); l_vertices.Add(l_vertexPositionC); //Triangles l_triangles.Add(l_vertexCount++); l_triangles.Add(l_vertexCount++); l_triangles.Add(l_vertexCount++); // Compute a vector perpendicular to the face. // NORMAL Vector3 l_normal = MeshUtilities.GetNormalFace(l_vertexPositionA, l_vertexPositionB, l_vertexPositionC); l_normals.Add(l_normal); l_normals.Add(l_normal); l_normals.Add(l_normal); } var l_completeMesh = new Mesh(); l_completeMesh.vertices = l_vertices.ToArray(); l_completeMesh.triangles = l_triangles.ToArray(); l_completeMesh.normals = l_normals.ToArray(); l_completeMesh = MeshUtilities.PerfectUVMesh(l_completeMesh, 1, 1); l_completeMesh.RecalculateBounds(); //save this mesh for next generation l_completeMesh.name = "CompleteMesh"; return(l_completeMesh); }
private void CreateMesh(ParseTree parseTree, IReadOnlyDictionary <int, MaterialModel> materialsDictionary) { DeleteOldMeshes(); ParseTreeData.ParseTree = parseTree; materials = materialsDictionary.Select(m => MeshUtilities.MaterialFromModel(m.Value)).ToArray(); var nodes = ParseTree.GetMeshNodes(); foreach (var node in nodes) { ParseTreeScript.Construct(transform, ParseTree, node, materials); } }
private void ShuffleEdgesAndTurnIntoPolygon() { var totalEdgeCount = _edges.Count + _holeEdges.Count; var shuffledIndices = new List <int>(capacity: totalEdgeCount); for (int i = 0; i < totalEdgeCount; ++i) { shuffledIndices.Add(i); } for (int i = 0; i < shuffledIndices.Count - 1; ++i) { var left = Random.Range(0, i + 1); var right = Random.Range(i + 1, shuffledIndices.Count); var tmp = shuffledIndices[left]; shuffledIndices[left] = shuffledIndices[right]; shuffledIndices[right] = tmp; } var shuffledEdges = new List <Edge>(capacity: totalEdgeCount); foreach (var index in shuffledIndices) { if (index < _edges.Count) { shuffledEdges.Add(_edges[index]); } else { shuffledEdges.Add(_holeEdges[index - _edges.Count]); } } var polys = MeshUtilities.ConnectEdges(shuffledEdges); _polyA = polys[0]; _aIsHole = false; if (polys.Count > 1) { _polyB = polys[1]; _aIsHole = MeshUtilities.IsSecondHoleInFirst(_polyB, _polyA); _bIsHole = MeshUtilities.IsSecondHoleInFirst(_polyA, _polyB); } }
internal MDSubMeshVifBatch(ref int index, ushort nodeIndex, bool isLast, List <VIFPacket> packets) { SetHeader(ref index, nodeIndex, packets); for (int i = 0; i < 31; i++) { if (BitHelper.IsBitSet(_flags, i)) { switch (i) { case 21: // Triangle indices SetTriangleIndices(ref index, packets); break; case 22: // Vertex Positions SetVertexPositionsAndWeights(ref index, packets); break; case 23: // Vertex Normals SetVertexNormals(ref index, packets); break; case 24: // Texture Coordinates if (isLast) { SetTextureCoordinates(ref index, packets); } break; case 25: // Vertex Colors if (isLast) { SetVertexColors(ref index, packets); } break; } } } // Some meshes don't store normals, so generate average normals in case we want to export it. if (_normals == null) { _normals = MeshUtilities.CalculateAverageNormals(_triangleIndices, _positions); } }
protected override Mesh DoProcessing(MeshSqueezerData data) { Vector3 center = MeshUtilities.GetCenter(data.mesh.Clone().vertices, data.CenterType); Mesh mesh = data.mesh.Clone(); Vector3[] v = (Vector3[])mesh.vertices.Clone(); Quaternion r = data.Rotation; float f = data.Force; for (int i = 0; i < v.Length; i++) { Vector3 tempPoint = r * (v[i] - center); v[i] = (Quaternion.Inverse(r) * new Vector3(tempPoint.x, tempPoint.y * f, tempPoint.z)) + center; } mesh.vertices = v; return(mesh); }
GameObject CreateRing(float radius) { float innerRadius = .01f; int nbRadSeg = 80; int nbSides = 20; GameObject result = new GameObject(); MeshUtilities.AddTorusMeshFilter(result, radius, innerRadius, nbRadSeg, nbSides); MeshRenderer renderer = result.AddComponent <MeshRenderer>(); renderer.enabled = false; // start off hidden renderer.material = ringMaterial; return(result); }
public Mesh(BXDAMesh.BXDASubMesh mesh, Vector3 position) { Vector3[] vertData = MeshUtilities.DataToVector(mesh.verts); Vector3[] normsData = MeshUtilities.DataToVector(mesh.norms); vertexData = mesh.verts; //Translate objects for (int i = 0; i < vertexData.Length;) { vertexData[i++] += position.X; vertexData[i++] += position.Y; vertexData[i++] += position.Z; } for (int i = 0; i < vertData.Length; i++) { vertData[i] *= 0.001f; } vertices = new List <Vertex>(); //for(int i = 0; i < vertData.Length; i++) //{ // Vertex toAdd = new Vertex() // { // position = vertData[i], // normal = normsData[i], // texCoord = new Vector2(0, 0) // }; // vertices.Add(toAdd); //} vertices = vertData.Zip(normsData, (v, n) => new Vertex { position = v, normal = n, texCoord = new Vector2(0, 0) }).ToList(); indices = new List <int>(); mesh.surfaces.ForEach((s) => indices = new List <int>(indices.Concat(s.indicies))); IEnumerable <double> temp = vertexData.Zip(indices, (v, i) => vertexData[i]); //vertexData = temp.ToArray(); textures = new List <Texture>(); setupMesh(); }
/// <summary> /// Turns a BXDA mesh into a CompoundShape centered around the origin /// </summary> /// <param name="mesh"></param> /// <returns></returns> private static CompoundShape GetShape(BXDAMesh mesh) { CompoundShape shape = new CompoundShape(); Vector3[] meshVertices = mesh.AllColliderVertices().ToArray(); for (int i = 0; i < mesh.colliders.Count; i++) { BXDAMesh.BXDASubMesh sub = mesh.colliders[i]; Vector3[] vertices = sub.GetVertexData(); StridingMeshInterface sMesh = MeshUtilities.CenteredBulletShapeFromSubMesh(sub); //Add the shape at a location relative to the compound shape such that the compound shape is centered at (0, 0) but child shapes are properly placed shape.AddChildShape(Matrix4.CreateTranslation(MeshUtilities.MeshCenterRelative(sub, mesh)), new ConvexTriangleMeshShape(sMesh)); Console.WriteLine("Successfully created and added sub shape"); } return(shape); }
/// <summary> /// Generates the mesh with smooth rendering. /// </summary> public static Mesh SetupSmoothMesh(Mesh p_mesh) { Mesh l_completeMesh = p_mesh; int l_vertexCount = l_completeMesh.vertices.Length; int l_triangleCount = l_completeMesh.triangles.Length / 3; var l_normals = new Vector3[l_vertexCount]; Vector3 l_zero = Vector3.zero; for (int i = 0; i < l_triangleCount; i++) { // Get the three vertices of triangle int l_triangleIndex = i * 3; int l_vertexIndexA = l_completeMesh.triangles[l_triangleIndex]; int l_vertexIndexB = l_completeMesh.triangles[l_triangleIndex + 1]; int l_vertexIndexC = l_completeMesh.triangles[l_triangleIndex + 2]; Vector3 l_vertexPositionA = l_completeMesh.vertices[l_vertexIndexA]; Vector3 l_vertexPositionB = l_completeMesh.vertices[l_vertexIndexB]; Vector3 l_vertexPositionC = l_completeMesh.vertices[l_vertexIndexC]; // Compute a vector perpendicular to the face. ////NORMAL Vector3 l_normal = MeshUtilities.GetNormalFace(l_vertexPositionA, l_vertexPositionB, l_vertexPositionC); if (l_normal.y >= l_zero.y) { l_normals[l_vertexIndexA] += l_normal; l_normals[l_vertexIndexB] += l_normal; l_normals[l_vertexIndexC] += l_normal; } } l_completeMesh.normals = l_normals; //l_completeMesh = MeshUtilities.PerfectUVMesh(l_completeMesh, 1, 1); l_completeMesh.RecalculateBounds(); //save this mesh for next generation l_completeMesh.name = "CompleteMesh"; return(l_completeMesh); }
void recalcFrustum() { // TODO< transform view frustom mesh by rotation of the camera > // we transform a mesh which describes the view frustum in global space // and then we calculate the normal and distance of the normal of the planes MeshWithExplicitFaces frustumMesh = new MeshWithExplicitFaces(); { // create a VerticesWithAttributes with just positions MutableMeshAttribute positionMeshAttribute = MutableMeshAttribute.makeDouble4ByLength(5); var positionAccessor = positionMeshAttribute.getDouble4Accessor(); positionAccessor[0] = new double[] { -1, -1, 1, 1 }; positionAccessor[1] = new double[] { 1, -1, 1, 1 }; positionAccessor[2] = new double[] { 1, 1, 1, 1 }; positionAccessor[3] = new double[] { -1, 1, 1, 1 }; positionAccessor[4] = new double[] { 0, 0, 0, 1 }; VerticesWithAttributes verticesWithAttributes = new VerticesWithAttributes(new AbstractMeshAttribute[] { positionMeshAttribute }, 0); frustumMesh.verticesWithAttributes = verticesWithAttributes; } frustumMesh.faces = new MeshWithExplicitFaces.Face[] { new MeshWithExplicitFaces.Face(new uint[] { 4, 0, 1 }), // top side new MeshWithExplicitFaces.Face(new uint[] { 4, 1, 2 }), // right side new MeshWithExplicitFaces.Face(new uint[] { 4, 2, 3 }), // bottom side new MeshWithExplicitFaces.Face(new uint[] { 4, 3, 0 }), // left side }; // TODO< use globally transformed vertices > // result is 4 component SpatialVectorDouble[] planesWith4Component = MeshUtilities.calcAllPlanes(frustumMesh.faces, frustumMesh.getVertexPositionsAsVector3Array()); // we only have 4 planes because we dont limit the maximal z frustum.planes = new FrustumPlane[4]; frustum.planes[0] = FrustumPlane.makeFrom4Component(planesWith4Component[0]); frustum.planes[1] = FrustumPlane.makeFrom4Component(planesWith4Component[1]); frustum.planes[2] = FrustumPlane.makeFrom4Component(planesWith4Component[2]); frustum.planes[3] = FrustumPlane.makeFrom4Component(planesWith4Component[3]); }
private void Start() { // Reorient the transforms if they are not on the diagonal // pointing towards the world origin. Vector3 min, max; min.x = Mathf.Min(minCorner.position.x, maxCorner.position.x); min.y = Mathf.Min(minCorner.position.y, maxCorner.position.y); min.z = Mathf.Min(minCorner.position.z, maxCorner.position.z); max.x = Mathf.Max(minCorner.position.x, maxCorner.position.x); max.y = Mathf.Max(minCorner.position.y, maxCorner.position.y); max.z = Mathf.Max(minCorner.position.z, maxCorner.position.z); minCorner.position = min; maxCorner.position = max; // Setup the mesh generation. int xCuts = Mathf.FloorToInt((max.x - min.x) / detailStep); int zCuts = Mathf.FloorToInt((max.z - min.z) / detailStep); Mesh surfaceMesh = MeshUtilities.GenerateGrid(xCuts, zCuts, detailStep); // Add noise to generate the mounds. Vector3[] verts = surfaceMesh.vertices; for (int i = 0; i < verts.Length; i++) { // Use perlin noise relative to location. verts[i].y = visualTurbulenceMagnitude * Mathf.PerlinNoise( verts[i].x * visualTurbulenceStep, verts[i].z * visualTurbulenceStep ); } surfaceMesh.vertices = verts; // Assign the generated mesh data and create the mesh components. MeshRenderer MR = gameObject.AddComponent <MeshRenderer>(); MeshFilter MF = gameObject.AddComponent <MeshFilter>(); MR.material = moundMaterial; MF.mesh = surfaceMesh; }
private void Update() { if (Input.GetKeyDown(KeyCode.C) && (Input.GetKey(KeyCode.RightShift) || Input.GetKey(KeyCode.LeftShift))) { _verticesSetupCount = 0; _isTestPointSetup = false; } if (Input.GetMouseButtonDown(0)) { if (_verticesSetupCount < 3) { _testTriangle[_verticesSetupCount++] = GetMousePoint(); } } if (Input.GetMouseButton(0) && _verticesSetupCount == 3) { _testPoint = GetMousePoint(); _isTestPointSetup = true; _isPointInside = MeshUtilities.IsPointInTriangle(_testPoint, _testTriangle[0], _testTriangle[1], _testTriangle[2], true, true); } }
private void MakeTheCut() { _hasStartedMarkingTheCut = false; var gameObjectsToSlice = CollectSliceables(); foreach (var go in gameObjectsToSlice) { var mMaterial = go.GetComponent <MeshRenderer>().sharedMaterial; var couldSlice = MeshUtilities.SliceMultiTriangleMesh(go, _cutStartPoint, _cutEndPoint, mMaterial, makePiecesDrop, false); if (couldSlice) { Destroy(go); } else { Debug.Log("Couldn't slice"); } _shouldDrawCutNormal = true; } }
/// <summary> /// Creates a Rigid Body from a .bxda file /// </summary> /// <param name="FilePath"></param> public void CreateRigidBody(string FilePath) { CollisionShape shape; WheelDriverMeta wheel = null; DefaultMotionState motion; BXDAMesh mesh = new BXDAMesh(); mesh.ReadFromFile(FilePath); Vector3 loc; Quaternion rot = Quaternion.Identity; //Is it a wheel? if ((wheel = GetSkeletalJoint()?.cDriver?.GetInfo <WheelDriverMeta>()) != null && true) { //Align the cylinders Vector3 min, max; GetShape(mesh).GetAabb(Matrix4.Identity, out min, out max); Vector3 extents = max - min; //Find the thinnest dimension, that is probably wheat the cylinder should be aligned to if (extents.X < extents.Y) //X or Z { if (extents.X < extents.Z) { shape = new CylinderShapeX(wheel.width, wheel.radius, wheel.radius); //X } else { shape = new CylinderShapeZ(wheel.radius, wheel.radius, wheel.width); //Z } } else //Y or Z { if (extents.Y < extents.Z) { shape = new CylinderShape(wheel.radius, wheel.width, wheel.radius); //Y } else { shape = new CylinderShapeZ(wheel.radius, wheel.radius, wheel.width); //Z } } loc = MeshUtilities.MeshCenter(mesh); } //Rigid Body Construction else { shape = GetShape(mesh); loc = MeshUtilities.MeshCenter(mesh); } if (debug) { Console.WriteLine("Rotation is " + rot); } motion = new DefaultMotionState(Matrix4.CreateTranslation(loc + new Vector3(0, 100, 0))); RigidBodyConstructionInfo info = new RigidBodyConstructionInfo(mesh.physics.mass, motion, shape, shape.CalculateLocalInertia(mesh.physics.mass)); //Temp? info.Friction = 100; info.RollingFriction = 100; //info.AngularDamping = 0f; //info.LinearDamping = 0.5f; BulletObject = new RigidBody(info); }
/// <summary> /// Updates Data structures made for Game Objects visibility. /// </summary> /// <param name="planes"></param> /// <param name="allGeoInfos"></param> /// <param name="useBounds"></param> private List <GeometryDataModels.GeoInfo> UpdateGeometryInfoVisibilities(Plane[] planes, List <GeometryDataModels.GeoInfo> allGeoInfos, bool useBounds) { int geoCount = allGeoInfos.Count; int index2 = 0; var newGeoInfos = new List <GeometryDataModels.GeoInfo>(allGeoInfos.Count); newGeoInfos.AddRange(allGeoInfos); this.seenTransforms = new List <Transform>(); UpdateSeenGeometryObjects(); // Updates object collection containing geometry and data related to seen object. Usage is to internally update seen geometry objects by checking objects renderer bounds // against eyes/cameras frustum void UpdateSeenGeometryObjects() { Transform geoInfoTransform = null; for (var i = 0; i < geoCount; i++) { var geoInfo = allGeoInfos[i]; geoInfoTransform = geoInfo.transform; if (!geoInfoTransform) { continue; } if (useBounds) { AddVisibleRenderer(geoInfo, ref index2); } else if (MeshUtilities.IsInsideFrustum(geoInfoTransform.position, planes)) { AddVisibleObject(geoInfo, ref index2); } } allGeoInfos = newGeoInfos; newGeoInfos = null; } return(newSeenGeometriesList.Take(index2).ToList()); // Local functions void AddVisibleRenderer(GeometryDataModels.GeoInfo geInfo, ref int index) { if (!geInfo.renderer) { newGeoInfos.Remove(geInfo); return; } if (GeometryUtility.TestPlanesAABB(GeoVision.Planes, geInfo.renderer.bounds)) { if (GeometryVisionUtilities.TransformIsEffect(geInfo.transform.name)) { return; } this.seenTransforms.Add(geInfo.transform); this.newSeenGeometriesList[index] = geInfo; index += 1; } } void AddVisibleObject(GeometryDataModels.GeoInfo geInfo, ref int index) { if (GeometryVisionUtilities.TransformIsEffect(geInfo.transform.name)) { return; } this.seenTransforms.Add(geInfo.transform); this.newSeenGeometriesList[index] = geInfo; index += 1; } }
private void CreateMesh(string filePath) { Bodies = new List <RigidBody>(); VisualMeshes = new List <Mesh>(); BXDAMesh mesh = new BXDAMesh(); mesh.ReadFromFile(filePath); foreach (FieldNode node in NodeGroup.EnumerateAllLeafFieldNodes()) { if (!GetPropertySets().ContainsKey(node.PropertySetID)) { return; } PropertySet current = GetPropertySets()[node.PropertySetID]; CollisionShape subShape = null; switch (current.Collider.CollisionType) { case PropertySet.PropertySetCollider.PropertySetCollisionType.BOX: { //Create a box shape //This is a mess, though I was told that this is how it works Vector3[] vertices = MeshUtilities.DataToVector(mesh.meshes[node.SubMeshID].verts); StridingMeshInterface temp = MeshUtilities.BulletShapeFromSubMesh(mesh.meshes[node.SubMeshID]); Vector3 min, max; temp.CalculateAabbBruteForce(out min, out max); PropertySet.BoxCollider colliderInfo = (PropertySet.BoxCollider)current.Collider; subShape = new BoxShape((max - min) * colliderInfo.Scale.Convert() * 0.5f); if (debug) { Console.WriteLine("Created Box"); } break; } case PropertySet.PropertySetCollider.PropertySetCollisionType.SPHERE: { //Create a sphere shape PropertySet.SphereCollider colliderInfo = (PropertySet.SphereCollider)current.Collider; subShape = new SphereShape(colliderInfo.Scale); if (debug) { Console.WriteLine("Created Sphere"); } break; } case PropertySet.PropertySetCollider.PropertySetCollisionType.MESH: { //Create a mesh shape if (node.CollisionMeshID == -1) { break; } PropertySet.MeshCollider colliderInfo = (PropertySet.MeshCollider)current.Collider; Vector3[] vertices = MeshUtilities.DataToVector(mesh.colliders[node.CollisionMeshID].verts); if (colliderInfo.Convex) { subShape = new ConvexHullShape(vertices); if (debug) { Console.WriteLine("Created Convex Mesh"); } } else { StridingMeshInterface sMesh = MeshUtilities.BulletShapeFromSubMesh(mesh.colliders[node.CollisionMeshID]); subShape = new ConvexTriangleMeshShape(sMesh, true); //still not really concave if (debug) { Console.WriteLine("Created Concave Mesh"); } } break; } } if (null == subShape) { return; } //set sub shape local position/rotation and add it to the compound shape Vector3 Translation = node.Position.Convert(); Quaternion rotation = node.Rotation.Convert(); DefaultMotionState motion = new DefaultMotionState(Matrix4.CreateFromQuaternion(rotation) * Matrix4.CreateTranslation(Translation)); motion.CenterOfMassOffset = Matrix4.CreateTranslation(mesh.physics.centerOfMass.Convert()); RigidBodyConstructionInfo info = new RigidBodyConstructionInfo(current.Mass, motion, subShape, subShape.CalculateLocalInertia(current.Mass)); info.Friction = current.Friction; Bodies.Add(new RigidBody(info)); VisualMeshes.Add(new Mesh(mesh.meshes[node.SubMeshID], Translation)); if (debug) { Console.WriteLine("Created " + node.PropertySetID); } } }
public static Assimp.Scene ToAssimpScene(RwClumpNode clumpNode) { // Scene var aiScene = new Assimp.Scene(); // RootNode var rootFrame = clumpNode.FrameList[0]; var aiRootNode = new Assimp.Node("RootNode", null); aiRootNode.Transform = new Assimp.Matrix4x4(rootFrame.Transform.M11, rootFrame.Transform.M21, rootFrame.Transform.M31, rootFrame.Transform.M41, rootFrame.Transform.M12, rootFrame.Transform.M22, rootFrame.Transform.M32, rootFrame.Transform.M42, rootFrame.Transform.M13, rootFrame.Transform.M23, rootFrame.Transform.M33, rootFrame.Transform.M43, rootFrame.Transform.M14, rootFrame.Transform.M24, rootFrame.Transform.M34, rootFrame.Transform.M44); aiScene.RootNode = aiRootNode; for (int i = 1; i < clumpNode.FrameList.Count; i++) { var frame = clumpNode.FrameList[i]; var frameName = "_" + frame.HAnimFrameExtensionNode.NameId; Assimp.Node aiParentNode = null; if (frame.Parent != null) { string parentName = "RootNode"; if (frame.Parent.HasHAnimExtension) { parentName = "_" + frame.Parent.HAnimFrameExtensionNode.NameId; } aiParentNode = aiRootNode.FindNode(parentName); } var aiNode = new Assimp.Node(frameName, aiParentNode); aiNode.Transform = new Assimp.Matrix4x4(frame.Transform.M11, frame.Transform.M21, frame.Transform.M31, frame.Transform.M41, frame.Transform.M12, frame.Transform.M22, frame.Transform.M32, frame.Transform.M42, frame.Transform.M13, frame.Transform.M23, frame.Transform.M33, frame.Transform.M43, frame.Transform.M14, frame.Transform.M24, frame.Transform.M34, frame.Transform.M44); aiParentNode.Children.Add(aiNode); } // Meshes, Materials for (int atomicIndex = 0; atomicIndex < clumpNode.Atomics.Count; atomicIndex++) { var atomic = clumpNode.Atomics[atomicIndex]; var geometry = clumpNode.GeometryList[atomic.GeometryIndex]; var frame = clumpNode.FrameList[atomic.FrameIndex]; var aiNodeName = $"Atomic{atomicIndex}"; var aiNode = new Assimp.Node(aiNodeName, aiScene.RootNode); var frameWorldTransform = frame.WorldTransform; aiNode.Transform = new Assimp.Matrix4x4(frameWorldTransform.M11, frameWorldTransform.M21, frameWorldTransform.M31, frameWorldTransform.M41, frameWorldTransform.M12, frameWorldTransform.M22, frameWorldTransform.M32, frameWorldTransform.M42, frameWorldTransform.M13, frameWorldTransform.M23, frameWorldTransform.M33, frameWorldTransform.M43, frameWorldTransform.M14, frameWorldTransform.M24, frameWorldTransform.M34, frameWorldTransform.M44); aiScene.RootNode.Children.Add(aiNode); bool hasVertexWeights = geometry.SkinNode != null; for (int meshIndex = 0; meshIndex < geometry.MeshListNode.MaterialMeshes.Length; meshIndex++) { var mesh = geometry.MeshListNode.MaterialMeshes[meshIndex]; var aiMesh = new Assimp.Mesh($"Atomic{atomicIndex}_Geometry{atomic.GeometryIndex}_Mesh{meshIndex}", Assimp.PrimitiveType.Triangle); // get triangle list indices int[] indices; if (geometry.MeshListNode.PrimitiveType == RwPrimitiveType.TriangleList) { indices = mesh.Indices; } else { indices = MeshUtilities.ToTriangleList(mesh.Indices, false); } // Faces for (int i = 0; i < indices.Length; i += 3) { var faceIndices = new[] { i, i + 1, i + 2 }; var aiFace = new Assimp.Face(faceIndices); aiMesh.Faces.Add(aiFace); } // TextureCoordinateChannels, VertexColorChannels, Vertices, MaterialIndex, Normals for (int triIdx = 0; triIdx < indices.Length; triIdx += 3) { for (int triVertIdx = 0; triVertIdx < 3; triVertIdx++) { int vertexIndex = indices[triIdx + triVertIdx]; // TextureCoordinateChannels if (geometry.HasTextureCoordinates) { for (int channelIdx = 0; channelIdx < geometry.TextureCoordinateChannelCount; channelIdx++) { var textureCoordinate = geometry.TextureCoordinateChannels[channelIdx][vertexIndex]; var aiTextureCoordinate = new Assimp.Vector3D(textureCoordinate.X, textureCoordinate.Y, 0f); aiMesh.TextureCoordinateChannels[channelIdx].Add(aiTextureCoordinate); } } // VertexColorChannels if (geometry.HasColors) { var color = geometry.Colors[vertexIndex]; var aiColor = new Assimp.Color4D(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f); aiMesh.VertexColorChannels[0].Add(aiColor); } // Vertices if (geometry.HasVertices) { var vertex = geometry.Vertices[vertexIndex]; var aiVertex = new Assimp.Vector3D(vertex.X, vertex.Y, vertex.Z); aiMesh.Vertices.Add(aiVertex); } // Normals if (geometry.HasNormals) { var normal = geometry.Normals[vertexIndex]; var aiNormal = new Assimp.Vector3D(normal.X, normal.Y, normal.Z); aiMesh.Normals.Add(aiNormal); } } } // Bones if (hasVertexWeights) { var skinNode = geometry.SkinNode; var aiBoneMap = new Dictionary <int, Assimp.Bone>(); for (int i = 0; i < indices.Length; i++) { var vertexIndex = indices[i]; int realVertexIndex = i; for (int j = 0; j < 4; j++) { var boneIndex = skinNode.VertexBoneIndices[vertexIndex][j]; var boneWeight = skinNode.VertexBoneWeights[vertexIndex][j]; if (boneWeight == 0.0f) { continue; } if (!aiBoneMap.Keys.Contains(boneIndex)) { var aiBone = new Assimp.Bone(); var boneFrame = clumpNode.FrameList.GetFrameByHierarchyIndex(boneIndex); aiBone.Name = boneFrame.HasHAnimExtension ? "_" + boneFrame.HAnimFrameExtensionNode.NameId : "RootNode"; aiBone.VertexWeights.Add(new Assimp.VertexWeight(realVertexIndex, boneWeight)); Matrix4x4.Invert(frame.WorldTransform, out Matrix4x4 invertedFrameWorldTransform); Matrix4x4.Invert(boneFrame.WorldTransform * invertedFrameWorldTransform, out Matrix4x4 offsetMatrix); aiBone.OffsetMatrix = new Assimp.Matrix4x4(offsetMatrix.M11, offsetMatrix.M21, offsetMatrix.M31, offsetMatrix.M41, offsetMatrix.M12, offsetMatrix.M22, offsetMatrix.M32, offsetMatrix.M42, offsetMatrix.M13, offsetMatrix.M23, offsetMatrix.M33, offsetMatrix.M43, offsetMatrix.M14, offsetMatrix.M24, offsetMatrix.M34, offsetMatrix.M44); aiBoneMap[boneIndex] = aiBone; } if (!aiBoneMap[boneIndex].VertexWeights.Any(x => x.VertexID == realVertexIndex)) { aiBoneMap[boneIndex].VertexWeights.Add(new Assimp.VertexWeight(realVertexIndex, boneWeight)); } } } aiMesh.Bones.AddRange(aiBoneMap.Values); } else { var aiBone = new Assimp.Bone(); // Name aiBone.Name = frame.HasHAnimExtension ? "_" + frame.HAnimFrameExtensionNode.NameId : "RootNode"; // VertexWeights for (int i = 0; i < aiMesh.Vertices.Count; i++) { var aiVertexWeight = new Assimp.VertexWeight(i, 1f); aiBone.VertexWeights.Add(aiVertexWeight); } // OffsetMatrix /* * Matrix4x4.Invert( frame.WorldTransform, out Matrix4x4 offsetMatrix ); * aiBone.OffsetMatrix = new Assimp.Matrix4x4( offsetMatrix.M11, offsetMatrix.M21, offsetMatrix.M31, offsetMatrix.M41, * offsetMatrix.M12, offsetMatrix.M22, offsetMatrix.M32, offsetMatrix.M42, * offsetMatrix.M13, offsetMatrix.M23, offsetMatrix.M33, offsetMatrix.M43, * offsetMatrix.M14, offsetMatrix.M24, offsetMatrix.M34, offsetMatrix.M44 ); */ aiBone.OffsetMatrix = Assimp.Matrix4x4.Identity; aiMesh.Bones.Add(aiBone); } var material = geometry.Materials[mesh.MaterialIndex]; var aiMaterial = new Assimp.Material(); if (material.IsTextured) { // TextureDiffuse var texture = material.TextureReferenceNode; aiMaterial.TextureDiffuse = new Assimp.TextureSlot( texture.Name + ".png", Assimp.TextureType.Diffuse, 0, Assimp.TextureMapping.FromUV, 0, 0, Assimp.TextureOperation.Add, Assimp.TextureWrapMode.Wrap, Assimp.TextureWrapMode.Wrap, 0); } // Name aiMaterial.Name = material.Name ?? $"Geometry{atomic.GeometryIndex}_Material{mesh.MaterialIndex}"; if (material.IsTextured && material.Name == null) { aiMaterial.Name = material.TextureReferenceNode.Name; } aiMaterial.ShadingMode = Assimp.ShadingMode.Phong; // Add mesh to meshes aiScene.Meshes.Add(aiMesh); // Add material to materials aiScene.Materials.Add(aiMaterial); // MaterialIndex aiMesh.MaterialIndex = aiScene.Materials.Count - 1; // Add mesh index to node aiNode.MeshIndices.Add(aiScene.Meshes.Count - 1); } } return(aiScene); }
RayHitDescriptor?traceRayInternal(SpatialVectorDouble rayOrigin, SpatialVectorDouble rayDirection, out bool hit, double maxT = double.MaxValue) { CollisionDescriptor collisionDescriptor = new CollisionDescriptor(); foreach (PhysicsComponentAndCollidersPair iPhysicsComponentAndColliders in physicsAndMeshPairs) { if (ConvexHullRayIntersection.checkRayCollision(rayOrigin, rayDirection, iPhysicsComponentAndColliders.physicsComponent.boundingVolume.convexHull)) { // iterate over all ColliderComponents and check for collision foreach (ColliderComponent iCollider in iPhysicsComponentAndColliders.colliders) { if (iCollider.isConvex) { SpatialVectorDouble[] convexHullPlanes = MeshUtilities.calcAllPlanes(iCollider.faces, iCollider.transformedVertices); SpatialVectorDouble?hitNormal; double hitTResult; int? hitFaceNumber; bool isHit = ConvexHullRayIntersection.calcRayCollision(rayOrigin, rayDirection, convexHullPlanes, out hitNormal, out hitTResult, out hitFaceNumber); if (!isHit) { continue; } if (hitTResult < 0.0) { continue; } if (hitTResult > maxT) { continue; } if (collisionDescriptor.rayDistance < hitTResult) { continue; } // store collision information collisionDescriptor.rayDistance = hitTResult; collisionDescriptor.faceIndex = (uint)hitFaceNumber.Value; collisionDescriptor.faceNormal = hitNormal.Value; collisionDescriptor.physicsComponentAndCollider = new PhysicsComponentAndCollidersPair(iPhysicsComponentAndColliders.physicsComponent, iCollider); collisionDescriptor.hit = true; } else { throw new NotImplementedException(); } } } } hit = collisionDescriptor.hit; if (hit) { // translate hit informations RayHitDescriptor hitDescriptor = new RayHitDescriptor(); hitDescriptor.hitNormal = collisionDescriptor.faceNormal; hitDescriptor.hitPhysicsComponentAndCollider = collisionDescriptor.physicsComponentAndCollider; hitDescriptor.hitPosition = rayOrigin + rayDirection.scale(collisionDescriptor.rayDistance); return(hitDescriptor); } else { return(null); } }
public virtual void DoUpdate() { enabled = false; MeshUtilities.MakeTessellatable(moveDistance, subdivideCount, maxPairsToMove); }