Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by boddole · Nov 15, 2014 at 09:00 AM · c#meshprocedural

Trouble Creating a Procedural Mesh on a Rotated Game Object

Hello everyone, I'm having trouble creating a procedural mesh on any Game Object that has a rotation other than global (0,0,0).

What is Supposed to Happen:

The script is essentially building a FOV/AOI mesh for detecting objects within that zone. It takes 4 Vector3 points (which essentially becomes a near clip plane). From there, the script makes a raycast from that point (with additional parameters), then gets a point along the raycast and then that data is turned into vertices for the mesh (the Far Clip Plane).

The Problem:

The script seems to work fine when the GO rotation is (0,0,0), but as soon as as the object is rotated (which would happen before the script is run), the mesh begins to skew in the direction of the rotation (ex. rotating the GO to the right (+Y) causes the mesh to skew in that direction). Eventually at 180 degrees, the mesh skews so much it points in the opposite direction of the GO.

Ideas on what is going wrong:

1) Maybe (probably) incorrectly using AngleAxis in a way that manifests itself when a global rotation is not (0,0,0).

2) Since I'm just feeding in Vector3 points, I'm actually not sure how the base points end up in the correct place regardless of GO position or rotation. Perhaps I need to make them local?

Any ideas are greatly appreciated.

*UPDATE:

I think I've got it working by changing the following 2 lines from transform.forward to Vector3.forward: (everything seems to work now)

         tempRay.direction = Quaternion.AngleAxis(desiredLeftRightAngle, Vector3.up) * (Vector3.forward);
         tempRay.direction += Quaternion.AngleAxis(desiredUpDownAngle, Vector3.right) * (Vector3.forward);


 using UnityEngine;
 using System.Collections;
 using System.Linq;
 
 public class Ship_GunFOVBuilder: MonoBehaviour {
     //responisble for creating the mesh the gun will use to determine what targets it cares about
     //placed on some EMPTY??? base hierarchy object
 
     //10 16 2014, this script has been combined with another scipt found on Unity Wiki for making procedural cubes...
 
     public Material mat1; //debugging, used to render object.
 
     private Ship_GunGroup gunGroup; //need to take some values for each gun from the gun group
     private GameObject gunFOVGO; //child GO on which the components are added to.
 
 
     void Start()
     {
         gunGroup = gameObject.GetComponentInParent<Ship_GunGroup>();
         gunFOVGO = transform.GetChild(0).gameObject;
         gunFOVGO.layer = 2; //ignore raycast layer.
         Debug.Log("gunFOVGO.name is: " + gunFOVGO.name);
         
         MeshFilter meshFilter = gunFOVGO.AddComponent<MeshFilter>();
         meshFilter.mesh = MeshBuilder();
         
         MeshRenderer meshRenderer = gunFOVGO.AddComponent<MeshRenderer>();
         meshRenderer.material = mat1;
         meshRenderer.enabled = true; //as long as it works, it does not need to be drawn (collider box will show its position).
     
         //for actual deployment:
         meshRenderer.enabled = false; //as long as it works, it does not need to be drawn (collider box will show its position).
 
         MeshCollider meshCollider = gunFOVGO.AddComponent<MeshCollider>();
         meshCollider.isTrigger = true;
 
         Rigidbody rigidbody = gunFOVGO.AddComponent<Rigidbody>();
         rigidbody.isKinematic = true;
         rigidbody.useGravity = false;
 
         //gunFOVGO.AddComponent<Ship_DeriveAIGunTarget>(); //don't need a reference to it
 
         //moving the created GO and mesh to a parent GO (in this case the GO that created the new GO), then making the local pos and rot (0,0,0).
 
         //11 6 2014 no longer needed because the child GO already has these settings by default///
         //gunFOVGO.transform.parent = gameObject.transform;
         //gunFOVGO.transform.localPosition = Vector3.zero;
         //gunFOVGO.transform.localRotation = Quaternion.identity;
         //
     }
     
     
     private Mesh MeshBuilder()
     {
         Mesh newMesh = new Mesh();
         newMesh.name = "FOV mesh";
         newMesh.Clear();
         
         //float length = 1f;
         //float width = 1f;
         //float height = 1f;
         
         #region Vertices
         //FRONT ->  input from gunGroup
         //top left
         //Vector3 p0 = new Vector3( -length * .5f,    -width * .5f, height * .5f );
         Vector3 p0 = gunGroup.fovTopLeftBase;
         
         //top right
         //Vector3 p1 = new Vector3( length * .5f,     -width * .5f, height * .5f );
         Vector3 p1 = gunGroup.fovTopRightBase;
         
         //bottom right
         //Vector3 p2 = new Vector3( length * .5f,     -width * .5f, -height * .5f );
         Vector3 p2 = gunGroup.fovBotRightBase;
         
         //bottom left
         //Vector3 p3 = new Vector3( -length * .5f,    -width * .5f, -height * .5f );
         Vector3 p3 = gunGroup.fovBotLeftBase;
         
         //BACK -> calculated(not sure if should look at back from through front, or only back...So I'm not sure how to name these points...
         //top left
         //Vector3 p4 = new Vector3( -length * .5f,    width * .5f,  height * .5f );
         Vector3 p4 = CalculateNextVertice(p0, gunGroup.fovUpAngle, gunGroup.fovLeftAngle, gunGroup.fovDistance);
         
         //top right
         //Vector3 p5 = new Vector3( length * .5f,     width * .5f,  height * .5f );
         Vector3 p5 = CalculateNextVertice(p1, gunGroup.fovUpAngle, gunGroup.fovRightAngle, gunGroup.fovDistance);
         
         //bottom right
         //Vector3 p6 = new Vector3( length * .5f,     width * .5f,  -height * .5f );
         Vector3 p6 = CalculateNextVertice(p2, gunGroup.fovDownAngle, gunGroup.fovRightAngle, gunGroup.fovDistance);
         
         //bottom left
         //Vector3 p7 = new Vector3( -length * .5f,    width * .5f,  -height * .5f );
         Vector3 p7 = CalculateNextVertice(p3, gunGroup.fovDownAngle, gunGroup.fovLeftAngle, gunGroup.fovDistance);
         
         
         Vector3[] vertices = new Vector3[]
         {
             // Bottom
             p0, p1, p2, p3,
             
             // Left
             p7, p4, p0, p3,
             
             // Front
             p4, p5, p1, p0,
             
             // Back
             p6, p7, p3, p2,
             
             // Right
             p5, p6, p2, p1,
             
             // Top
             p7, p6, p5, p4
         };
         #endregion
         
         #region Normales
         Vector3 up     = Vector3.up;
         Vector3 down     = Vector3.down;
         Vector3 front     = Vector3.forward;
         Vector3 back     = Vector3.back;
         Vector3 left     = Vector3.left;
         Vector3 right     = Vector3.right;
         
         Vector3[] normales = new Vector3[]
         {
             // Bottom
             down, down, down, down,
             
             // Left
             left, left, left, left,
             
             // Front
             front, front, front, front,
             
             // Back
             back, back, back, back,
             
             // Right
             right, right, right, right,
             
             // Top
             up, up, up, up
         };
         #endregion    
         
         #region UVs
         Vector2 _00 = new Vector2( 0f, 0f );
         Vector2 _10 = new Vector2( 1f, 0f );
         Vector2 _01 = new Vector2( 0f, 1f );
         Vector2 _11 = new Vector2( 1f, 1f );
         
         Vector2[] uvs = new Vector2[]
         {
             // Bottom
             _11, _01, _00, _10,
             
             // Left
             _11, _01, _00, _10,
             
             // Front
             _11, _01, _00, _10,
             
             // Back
             _11, _01, _00, _10,
             
             // Right
             _11, _01, _00, _10,
             
             // Top
             _11, _01, _00, _10,
         };
         #endregion
         
         #region Triangles
         int[] triangles = new int[]
         {
             // Bottom
             3, 1, 0,
             3, 2, 1,            
             
             // Left
             3 + 4 * 1, 1 + 4 * 1, 0 + 4 * 1,
             3 + 4 * 1, 2 + 4 * 1, 1 + 4 * 1,
             
             // Front
             3 + 4 * 2, 1 + 4 * 2, 0 + 4 * 2,
             3 + 4 * 2, 2 + 4 * 2, 1 + 4 * 2,
             
             // Back
             3 + 4 * 3, 1 + 4 * 3, 0 + 4 * 3,
             3 + 4 * 3, 2 + 4 * 3, 1 + 4 * 3,
             
             // Right
             3 + 4 * 4, 1 + 4 * 4, 0 + 4 * 4,
             3 + 4 * 4, 2 + 4 * 4, 1 + 4 * 4,
             
             // Top
             3 + 4 * 5, 1 + 4 * 5, 0 + 4 * 5,
             3 + 4 * 5, 2 + 4 * 5, 1 + 4 * 5,
             
         };
         #endregion
         
         newMesh.vertices = vertices;
         
         newMesh.normals = normales;
         
         newMesh.uv = uvs;
         
         newMesh.triangles = triangles;
         //reverse them to invert normals (which fixes an issue where all normals are inverted for an unkown reason)...
         newMesh.triangles = newMesh.triangles.Reverse().ToArray();
         
         newMesh.RecalculateBounds();
         
         newMesh.Optimize();
         
         return newMesh;
     }
     
     //using parameters, calculate where the desired point will be:
     private Vector3 CalculateNextVertice(Vector3 startingPoint, float desiredUpDownAngle,  float desiredLeftRightAngle, float desiredDistance)
     {
         Vector3 createdVec3 = new Vector3();
         
         Ray tempRay = new Ray();
         tempRay.origin = startingPoint;
         tempRay.direction = Quaternion.AngleAxis(desiredLeftRightAngle, gunFOVGO.transform.up) * (gunFOVGO.transform.forward);
         tempRay.direction += Quaternion.AngleAxis(desiredUpDownAngle, gunFOVGO.transform.right) * (gunFOVGO.transform.forward);
         
         Physics.Raycast (tempRay.origin, tempRay.direction, desiredDistance);
         Debug.DrawRay (tempRay.origin, tempRay.direction * desiredDistance, Color.red, 5f);
         
         //get the point at the end of the ray:
         createdVec3 = tempRay.GetPoint (desiredDistance);
         
         Debug.Log ("createdVec3 is: " + createdVec3);
         return createdVec3;
     }
 }

alt text

alt text

withrotationbigtrouble.jpg (108.3 kB)
norotationseemsfine.jpg (128.3 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by richyrich · Nov 15, 2014 at 04:39 PM

Couple of ideas:

1) I can't see where you are converting the vertices into local space (i.e. InverseTransformPoint). Are you doing this?

2) If you are doing a conversion, then have you tried disabling the mesh render and drawn debug lines point to point from/to the bounding vertices as a sanity check?

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image boddole · Nov 16, 2014 at 02:58 AM 0
Share

Hey richyrich,

1) Currently no (see below).

2) I attached a mesh collider to the created mesh which shows the edges, which in turn reveals the vertices (does that create comparable result to your suggestion?).

What I'm seeing is that a mesh seems to be created "in worldspace" meaning that the mesh gets created, then moved to where you want it through the $$anonymous$$esh Filter component (so I don't think that making something local is necessarily a good idea).

I think I've got it fixed (it seems okay so far), by changing the following 2 lines to Vector3.forward ins$$anonymous$$d of transform.forward (again, getting rid of local references and just making everything global):

         tempRay.direction = Quaternion.AngleAxis(desiredLeftRightAngle, Vector3.up) * (Vector3.forward);
         tempRay.direction += Quaternion.AngleAxis(desiredUpDownAngle, Vector3.right) * (Vector3.forward);

Thank you for the ideas though, hopefully everything continues to work....

avatar image _dns_ boddole · Nov 17, 2014 at 05:07 PM 0
Share

Hi, the mesh you create is defined in the gameObject's local space. That is, the (0,0,0) point of the mesh is the pivot of the object. Any transformations you apply to the Gameobject will be "applied" to the mesh by the vertex shader just before rendering: rotation and scale will be computed for each vertex to get the world coordinates.

When you first used mygameobject.transform.forward : this is an "already transformed to world coordinate" forward vector. That's why using it made strange behaviors when rotating. Now, with Vector3.forward, you work in the object's space and the rotations are computed later by the GPU.

You can do those transformations yourself (with the CPU) using what richyrich mentioned: Transform.TransformPoint (object to world) or InverseTransformPoint to do the opposite operation (world to object).

If you need to test if an object is inside the "FOV" volume you defined, you may need to transform those points in world space to do so.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

27 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Trouble with Procedural Mesh Normals (normals are inverted) 1 Answer

How to Change an Object's Mesh to another Object's Mesh via Code C# 1 Answer

C# Preserving GameObjects' Previous Meshes 1 Answer

Procedural array of meshes problem / solved 1 Answer

C# Array of OtherArray's Meshes 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges