在给定方向上缩放网格的一部分

时间:2015-05-05 19:29:14

标签: opengl math glsl

我有很多立方体(ex 100)都是同一个网格的一部分,在顶点着色器中我想沿着给定的轴缩放每个立方体,所以它的顶部被移动并且立方体像这样被拉伸:

enter image description here enter image description here

每个立方体都有一个ID,每个顶点都有一个对应的ID,因此每个顶点都知道它所属的立方体。一个统一的vec3规范化cubeUps数组(多维数据集应该扩展的方向)和一个统一的vec3 cubeOrigins数组(每个多维数据集的基数)也传递给着色器。这些统一数组的索引与多维数据集的ID匹配。

知道立方体的cubeOrigins位于每个立方体底部的中心,就像白点一样,因为我认为这是需要的,但不确定:

enter image description here

我可以很容易地沿着给定的normal翻译立方体,如下所示:

layout (location = 0) in vec3 vertexPos;
layout (location = 1) in vec3 vertexNor;
layout (location = 2) in float vertexCubeId;

uniform mat4 mvp;

uniform vec3 cubeUps[100];
uniform vec3 cubeOrigins[100];

void main()
{
    int cubeIndex = int(vertexCubeId);
    vec3 cubeUp = cubeUps[cubeIndex];
    vec3 cubeOrigin = cubeOrigins[cubeIndex];

    vec3 transformedPos = vertexPos;

    transformedPos.x += cubeUp.x;
    transformedPos.y += cubeUp.y;
    transformedPos.z += cubeUp.z;

    gl_Position = mvp * vec4(transformedPos, 1.0);
}

但是我的扩展计划没有成功。我认为我需要做的是:

  1. 从顶点减去原点,使用公共基数 缩放。
  2. 以某种方式沿着'cubeUp'向量进行缩放。
  3. 将原点添加到顶点以再次远离基座。
  4. 这样的事情:

    ...
    
    float scaleFactor = 1.5f;
    vec3 scale = cubeUp * scaleFactor;
    
    transformedPos.x -= cubeOrigin.x;
    transformedPos.y -= cubeOrigin.y;
    transformedPos.z -= cubeOrigin.z;
    
    transformedPos.x *= scale.x;
    transformedPos.y *= scale.y;
    transformedPos.z *= scale.z;
    
    transformedPos.x += cubeOrigin.x;
    transformedPos.y += cubeOrigin.y;
    transformedPos.z += cubeOrigin.z;
    
    gl_Position = mvp * vec4(transformedPos, 1.0);
    
    ...
    

    但这会将立方体移动到不希望的位置,并且不会正确缩放它们。

    我是否需要在应用比例之前旋转顶点坐标,才能正确使用原点?

    如何从给定的cubeUp向量中获取用于缩放的正确值?

1 个答案:

答案 0 :(得分:1)

cubeUp的方向上取顶点的点积(在减去原点之后),然后缩放它并添加到顶点位置。这将确保顶点仅朝cubeUp方向移动。像这样:

float scaleFactor = 1.5f;

transformedPos.x -= cubeOrigin.x;
transformedPos.y -= cubeOrigin.y;
transformedPos.z -= cubeOrigin.z;

float dotProduct = dot(cubeUp, transformedPos);
dotProduct *= (scaleFactor - 1.0f);   // or just set scaleFactor
                                      // to 0.5f in the first place
vec3 offset = cubeUp * dotProduct;

transformedPos.x += offset.x;
transformedPos.y += offset.y;
transformedPos.z += offset.z;

transformedPos.x += cubeOrigin.x;
transformedPos.y += cubeOrigin.y;
transformedPos.z += cubeOrigin.z;

为了想象为什么简单地乘以比例矢量不起作用,想象一下由cubeOrigincubeUp定义的平面上的顶点(即立方体的底部)。它根本不应该移动。但是,每个角顶点都将具有非零transformedPos向量,这意味着在乘以scale之后值将不相同,除非在cubeUp的特殊情况下}精确地指向XY或Z轴。

您需要专门乘以transformedPos向量的cubeUp方向的那一部分,该部分等于dot(cubeUp, transformedPos) * cubeUp。而不是减去该部分然后再乘以1.5然后重新添加它,只需乘以0.5并添加它就更有效。