将vec3与模型矩阵相乘的问题缩放问题

问题描述

在我的3D应用程序中,我有一个Object3D类,该类在创建时就是边界框,该边界框是一个简单的长方体,具有最小和最大点:

simple cuboid bounding box

但是,当我翻译Object3D时,我想使用对象的模型矩阵来更新边界框:

     BoundingBox& TransformBy(const glm::mat4& modelMatrice){
        //extract position of my model matrix
        glm::vec3 pos( modelMatrice[3] );
        
        //extract scale of my model matrix
        glm::vec3 scale( glm::length(glm::vec3(modelMatrice[0])),glm::length(glm::vec3(modelMatrice[1])),glm::length(glm::vec3(modelMatrice[2])));
        
        //Creating vec4 min/max from vec3
        glm::vec4 min_(min.x,min.y,min.z,1.0f);
        glm::vec4 max_(max.x,max.y,max.z,1.0f);
        
        //Inverting the matrice to multiply my vec4 with it in order to rotate my min max
        glm::mat4 inverse = glm::inverse(modelMatrice);
        min_ = min_ * inverse;
        max_ = max_ * inverse;
        
        //Scale my min_ max_
        min_ *= glm::vec4(scale,1.0f);
        max_ *= glm::vec4(scale,1.0f);
        
        //adding model matrice translation to min_ and max_
        min_ += glm::vec4(pos,0.0f);
        max_ += glm::vec4(pos,0.0f);
    
        //Redefining max and min
        max = glm::vec3( (min_.x > max_.x)? min_.x:max_.x,(min_.y > max_.y)? min_.y: max_.y,(min_.z > max_.z)? min_.z : max_.z);
        min = glm::vec3( (min_.x < max_.x)? min_.x:max_.x,(min_.y < max_.y)? min_.y: max_.y,(min_.z < max_.z)? min_.z : max_.z);
        return *this;
    }

这是我调用TransformBy函数的方式:

box.TransformBy(transform.GetModelMatrix());

由于某种原因,它会使我的最小点和最大点正确旋转,也会平移它,但是我的缩放比例未正确应用,这使我的边界框的缩放比例大于3D对象。

为什么我的缩放无法正常工作? 也许有一种不太复杂的方式来做我想做的事?

解决方法

如果我正确理解了GetModelMatrix()的结果,即它只是一个普通的4x4转换矩阵,那么我想我可以猜到问题出在哪里。我发现用示例进行可视化/解释最容易,所以希望没事。

假设您的GetModelMatrix()的结果如下,是一个简单的变换矩阵,没有旋转分量,只有[5 6 7]的平移。

| 1 0 0 5 |
| 0 1 0 6 |
| 0 0 1 7 |
| 0 0 0 1 |

modelMatrice的形式传递的倒数就是:

| 1 0 0 -5 |
| 0 1 0 -6 |
| 0 0 1 -7 |
| 0 0 0  1 |

调用glm::vec4 min_(min.x,min.y,min.z,1.0f);后,让我们用向量min_表示[x y z 1]。然后min_ * modelMatrice如下:

            | 1 0 0 -5 |   
            | 0 1 0 -6 |
[x y z 1] * | 0 0 1 -7 | = [x y z (-5x-6y-7z+1)]
            | 0 0 0  1 |   

也就是说,x,y和z分量不会更改,因为在乘法中是应用于它们的|0 0 0 1|行,而不是包含转换分量的列。

我想问一下,您是否有特定的原因(a)将GetModelMatrix()求逆,并且(b)将矩阵乘以矢量而不是相反?我猜想也许您的代码应该如下所示:

BoundingBox& TransformBy(const glm::mat4 modelMatrice){
        ...
        min_ = modelMatrice * min_;
        max_ = modelMatrice * max_;
        ...
        return *this;
    } 

box.TransformBy(transform.GetModelMatrix());呼叫

更新

关于您的新代码,我质疑是否需要反转转换矩阵以进行旋转,是否需要将缩放/平移/旋转分解为三个单独的步骤,依此类推。在其他地方,该过程应该像获取对象的转换向量一样简单,将min_和max_乘以它,然后测试是否在函数末尾交换了当前已交换的最小/最大分量:

     BoundingBox& TransformBy(const glm::mat4& modelMatrice){
        min_ = modelMatrice * min_;
        max_ = modelMatrice * max_;
        max = glm::vec3( (min_.x > max_.x)? min_.x:max_.x,(min_.y > max_.y)? min_.y: max_.y,(min_.z > max_.z)? min_.z : max_.z);
        min = glm::vec3( (min_.x < max_.x)? min_.x:max_.x,(min_.y < max_.y)? min_.y: max_.y,(min_.z < max_.z)? min_.z : max_.z);
        return *this;
    }

如果上述五行功能不起作用,请告诉我它是如何失败的;如果它不起作用,我认为问题可能出在代码的其他地方。

但是,要回答有关缩放为什么不起作用的最新问题:反转转换矩阵时,您也在反转缩放。因此,当您乘以inverse时,您不仅旋转,而且还应用了反向比例。尽管您可以通过再次乘以比例来解决此问题,但似乎更简单的解决方案似乎正在尝试使上述五行解决方案正常工作。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...