Align faces of 2 blocks by moving and rotating

topicinsert image description here

train of thought

  1. One block with multiple colors: it can be realized by modeling and pasting materials of different colors, or shader
  2. Random position and angle: use random numbers to generate random vectors and assign them to position and eulerAngles
  3. Position error: the difference between the positions of the midpoints of the two faces
  4. Rotation error: expressed by the angle between each axis and the plane to be aligned. The rotation sequence should be to turn the X axis to the plane to be aligned, and then turn the Y axis to the plane to be aligned so that the two faces are in the same plane; then rotate the Z axis to make the two faces coincide completely.

my answer

insert image description here

  1. Use the square as a subclass of Quad, move the Quad to absorb the surface to be aligned, and get the pose of the surface
    insert image description here

  2. Set two interactive modes of translation and rotation. After the switch is checked, the translation and rotation can be operated through the keyboard, and the buttons can be reused to reduce the complexity of the operation

  3. The interaction order is enforced, first translate and then rotate

  4. The green square rotates and translates according to its own axis, and it can be aligned only by adjusting the error to the specified number.

the code

  1. random position and angle
    public GameObject Cube;
    public float RandomRadius; //限制随机出现的范围,使红色方块一定出现在摄像机视野内

    void Start()
    {
    
    
        Cube.transform.position = RandomPosi(RandomRadius);
        Cube.transform.eulerAngles = RandomRot();
    }

    private Vector3 RandomPosi(float radius)//随机位置
    {
    
    
        Vector3 pos;
        float x= Random.Range(-radius, radius);
        float y= Random.Range(-radius, radius);
        float z= Random.Range(-radius, radius);
        return pos;
    }

    private Vector3 RandomRot()//随机角度
    {
    
    
        Vector3 rot;
        float x = Random.Range(0.0f, 360.0f);
        float y= Random.Range(0.0f, 360.0f);
        float z= Random.Range(0.0f, 360.0f);
        return rot;
    }

insert image description here

  1. Translation, rotation, display error
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MoveCube : MonoBehaviour
{
    
    
    public bool IsMove = false ;//移动模式
    public bool IsRot = false ;//旋转模式
    //移动、旋转的速度
    private  float MoveXspeed;
    private float MoveYspeed;
    private float MoveZspeed;
    private float RotXspeed;
    private float RotYspeed;
    private float RotZspeed;
    //设置最快速度和最慢速度,接近对齐时使用慢速微调
    public float FastMoveSpeed;
    public float SlowMoveSpeed;
    public float FastRotSpeed;
    public float SlowRotSpeed;
    //显示误差
    public GameObject RedQuad;
    public GameObject GreenQuad;
    public Text TextBoard;


    void Update()
    {
    
    
        TextBoard.text = showError();
        if (IsMove) Move();
        if (IsRot) Rot();       
    }

    //平移方法
    private void Move()
    {
    
    
        //Y轴,上下移动
        if (Input.GetKey(KeyCode.W)
            this.transform.Translate(Vector3.up * Time.fixedTime * MoveYspeed);
        
        if (Input.GetKey(KeyCode.S) )  
            this.transform.Translate(-Vector3.up * Time.fixedTime * MoveYspeed);
        

        //X轴,左右移动
        if (Input.GetKey(KeyCode.A) )        
            this.transform.Translate(Vector3.left * Time.fixedTime * MoveXspeed);
        
        if (Input.GetKey(KeyCode.D) )        
            this.transform.Translate(-Vector3.left * Time.fixedTime * MoveXspeed);
       

        //Z轴,前后移动
        if (Input.GetKey(KeyCode.Q) )      
            this.transform.Translate(Vector3.back * Time.fixedTime *MoveZspeed);
 
        if (Input.GetKey(KeyCode.E) )
            this.transform.Translate(-Vector3.back * Time.fixedTime * MoveZspeed);
        
    }

    //旋转方法
    private void Rot()
    {
    
    
        //绕Y轴
        if (Input.GetKey(KeyCode.W))       
            this.transform.Rotate(Vector3.down * Time.fixedTime * RotYspeed);     
        if (Input.GetKey(KeyCode.S))
            this.transform.Rotate(-Vector3.down * Time.fixedTime * RotYspeed);
            
        //绕X轴
        if (Input.GetKey(KeyCode.A))        
            this.transform.Rotate(Vector3.left * Time.fixedTime * RotXspeed);        
        if (Input.GetKey(KeyCode.D))        
            this.transform.Rotate(-Vector3.left * Time.fixedTime * RotXspeed);
            
        //绕Z轴
        if (Input.GetKey(KeyCode.Q))
            this.transform.Rotate(Vector3.back * Time.fixedTime * RotZspeed);      
        if (Input.GetKey(KeyCode.E))        
            this.transform.Rotate(-Vector3.back * Time.fixedTime * RotZspeed);
    }


    //是否平移
    public void MoveGo()
    {
    
    
        IsMove = true;
        IsRot = false;
    }

    //是否旋转
    public void RotGo()
    {
    
    
        IsRot = true;
        IsMove = false;
    }

    
    //显示误差
    private string showError()
    {
    
    
        string posError = PosError();
        string rotError = RotError();
        return "先平移:"+"\r\n" + posError 
            + "\r\n" + "后旋转:" + "\r\n" + rotError;
    }


    //位置误差
    private string PosError()
    {
    
            
        float GreenX = GreenQuad.transform.position.x;
        float GreenY = GreenQuad.transform.position.y;
        float GreenZ = GreenQuad.transform.position.z;

        float x = RedQuad.transform.position.x - GreenX;
        float y = RedQuad.transform.position.y - GreenY;
        float z = RedQuad.transform.position.z - GreenZ;


        //根据误差大小控制速度
        if (Mathf.Abs(y) > 1.0f)
            MoveYspeed = FastMoveSpeed;
        else MoveYspeed = SlowMoveSpeed;
        if (Mathf.Abs(x) > 1.0f)
            MoveXspeed = FastMoveSpeed;
        else MoveXspeed = SlowMoveSpeed;
        if (Mathf.Abs(z) > 1.0f) 
            MoveZspeed = FastMoveSpeed;
        else MoveZspeed = SlowMoveSpeed;

        return "X轴方向误差(操作AD使误差归0):"+x+"\r\n"
            + "Y轴方向误差(操作WS使误差归0):" + y+"\r\n"
            + "Z轴方向误差(操作QE使误差归0):" + z+"\r\n";
    }

    //角度误差
    private string RotError()
    {
    
           
        float XZ = Angle(GreenQuad.transform.right,RedQuad.transform.forward);
        float YZ = Angle(GreenQuad.transform.up, RedQuad.transform.forward);
        float ZZ = Angle(GreenQuad.transform.forward, RedQuad.transform.forward);
        float XX = Angle(GreenQuad.transform.right, RedQuad.transform.right);        

        根据误差大小控制速度
        if (YZ > 95.0f || YZ < 85.0f)
            RotXspeed = FastRotSpeed;
        else RotXspeed = SlowRotSpeed;
        if (XZ > 95.0f || XZ < 85.0f)
            RotYspeed = FastRotSpeed;
        else RotYspeed = SlowRotSpeed;
        if (0.0f <= XX && XX < 5.0f)
            RotZspeed = SlowRotSpeed;
        else if (175.0f <= XX && XX < 185.0f)
            RotZspeed = SlowRotSpeed;
        else RotZspeed = FastRotSpeed;


        return "操作WS按钮,使误差接近90\r\n"
            + "绿方块x轴与红方块xy平面的夹角(操作WS):" +XZ+ "\r\n" + "\r\n"
            + "操作AD按钮,使误差接近90\r\n"
            + "绿方块y轴与红方块xy平面的夹角(操作AD):" + YZ + "\r\n" + "\r\n"
            + "180代表相对,0代表重合\r\n"
            + "绿方块z轴与红方块z轴的夹角:" + ZZ + "\r\n" + "\r\n"
            + "操作QE按钮,使误差接近0或180\r\n"
            + "绿方块x轴与红方块x轴的夹角(操作QE):" + XX + "\r\n";
    }

    //求两向量夹角
    private float Angle(Vector3 red, Vector3 green)
    {
    
           
        float dot = Vector3.Dot(red.normalized, green.normalized);
        float angle = Mathf.Acos(dot) * Mathf.Rad2Deg; 
        return angle;
    }
}

insert image description here

Guess you like

Origin blog.csdn.net/yxy171229/article/details/129729674