如何沿其自身原点旋转缓冲区几何体的各个平面

发布于 2025-01-11 08:12:47 字数 2288 浏览 0 评论 0原文

缓冲区几何体由球体上的许多平面组成。我试图沿着每个平面的原点单独旋转,因此整体动画看起来更像爆炸。但这个平面不是沿着自己的轴旋转,而是漂浮在球体上。

以下是顶点着色器代码和包含所有代码的 codepen,以及触发动画的按钮。

uniform float uTime;
uniform float uProgress;
uniform float uGravity;

attribute vec3 attributePositionDest;
attribute vec3 attributeCentroid;
attribute vec3 attributeAxis;
attribute float attributeGravityVelocity;

varying vec3 vEye;
varying vec3 vNormal;
varying vec3 vReflect;

// http://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/
vec4 quat_from_axis_angle(vec3 axis, float angle) {
  vec4 qr;
  float half_angle = (angle * 0.5) * 3.14159 / 180.0;
  qr.x = axis.x * sin(half_angle);
  qr.y = axis.y * sin(half_angle);
  qr.z = axis.z * sin(half_angle);
  qr.w = cos(half_angle);
  return qr;
}
vec3 rotate_vertex_position(vec3 position, vec3 axis, float angle) { 
  vec4 q = quat_from_axis_angle(axis, angle);
  vec3 v = position.xyz;
  return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);
}

// main
void main() {
  vec3 positionAdjusted = position;
  float vTemp =  1. - ((attributeCentroid.x + attributeCentroid.y)*0.5 + 1.)/2.;

  float tProgress = max(0.0, (uProgress - vTemp*0.5) / 0.25) * uProgress;
  float vectorLength = length(position);
  float gravityAdjustment = (uGravity + attributeGravityVelocity) * uTime * vectorLength * 0.25;

  positionAdjusted = mix(positionAdjusted, attributePositionDest, tProgress); // translate to destination
  positionAdjusted = rotate_vertex_position(positionAdjusted, attributeAxis, max(1., uTime * 0.5)); // rotate plane
  positionAdjusted = vec3(positionAdjusted.x, positionAdjusted.y + gravityAdjustment, positionAdjusted.z); // add gravity

  vec4 worldPosition = modelMatrix * vec4(positionAdjusted, 1.0);
  vec3 worldNormal = normalize(mat3(modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz) * normal);
  vec3 I = worldPosition.xyz - cameraPosition;

  // set varying vars
  vNormal = normal;
  vEye = normalize(vec3(modelViewMatrix * vec4(positionAdjusted, 1.0)));
  vReflect = reflect(I, worldNormal);

  gl_Position = projectionMatrix * modelViewMatrix * vec4(positionAdjusted, 1.);
}

https://codepen.io/olhapi/pen/vYWrXMK?editors=0010

There's buffer geometry that consists of many planes on sphere. I'm trying to rotate each plane indidividually along its own origin, so overall animation will look more like explosion. But instead of rotating along their own axis this planes is kind of floating on a sphere.

Here are vertex shader code and codepen with all code, and button to trigger animation.

uniform float uTime;
uniform float uProgress;
uniform float uGravity;

attribute vec3 attributePositionDest;
attribute vec3 attributeCentroid;
attribute vec3 attributeAxis;
attribute float attributeGravityVelocity;

varying vec3 vEye;
varying vec3 vNormal;
varying vec3 vReflect;

// http://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/
vec4 quat_from_axis_angle(vec3 axis, float angle) {
  vec4 qr;
  float half_angle = (angle * 0.5) * 3.14159 / 180.0;
  qr.x = axis.x * sin(half_angle);
  qr.y = axis.y * sin(half_angle);
  qr.z = axis.z * sin(half_angle);
  qr.w = cos(half_angle);
  return qr;
}
vec3 rotate_vertex_position(vec3 position, vec3 axis, float angle) { 
  vec4 q = quat_from_axis_angle(axis, angle);
  vec3 v = position.xyz;
  return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);
}

// main
void main() {
  vec3 positionAdjusted = position;
  float vTemp =  1. - ((attributeCentroid.x + attributeCentroid.y)*0.5 + 1.)/2.;

  float tProgress = max(0.0, (uProgress - vTemp*0.5) / 0.25) * uProgress;
  float vectorLength = length(position);
  float gravityAdjustment = (uGravity + attributeGravityVelocity) * uTime * vectorLength * 0.25;

  positionAdjusted = mix(positionAdjusted, attributePositionDest, tProgress); // translate to destination
  positionAdjusted = rotate_vertex_position(positionAdjusted, attributeAxis, max(1., uTime * 0.5)); // rotate plane
  positionAdjusted = vec3(positionAdjusted.x, positionAdjusted.y + gravityAdjustment, positionAdjusted.z); // add gravity

  vec4 worldPosition = modelMatrix * vec4(positionAdjusted, 1.0);
  vec3 worldNormal = normalize(mat3(modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz) * normal);
  vec3 I = worldPosition.xyz - cameraPosition;

  // set varying vars
  vNormal = normal;
  vEye = normalize(vec3(modelViewMatrix * vec4(positionAdjusted, 1.0)));
  vReflect = reflect(I, worldNormal);

  gl_Position = projectionMatrix * modelViewMatrix * vec4(positionAdjusted, 1.);
}

https://codepen.io/olhapi/pen/vYWrXMK?editors=0010

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

開玄 2025-01-18 08:12:47

您在 quat_from_axis_angle() 中的 half_angle 单位有问题,

删除 rad 转换,当 utime > 时,它会变成 。 1 秒:

vec4 quat_from_axis_angle(vec3 axis, float angle) {
  vec4 qr;
  float half_angle = (angle * 0.5); // * 3.14159 / 180.0;
  qr.x = axis.x * sin(half_angle);
  qr.y = axis.y * sin(half_angle);
  qr.z = axis.z * sin(half_angle);
  qr.w = cos(half_angle);
  return qr;
}

You have a problem with half_angle unit in quat_from_axis_angle()

remove the rad conversion and it will turn , when utime > 1 second :

vec4 quat_from_axis_angle(vec3 axis, float angle) {
  vec4 qr;
  float half_angle = (angle * 0.5); // * 3.14159 / 180.0;
  qr.x = axis.x * sin(half_angle);
  qr.y = axis.y * sin(half_angle);
  qr.z = axis.z * sin(half_angle);
  qr.w = cos(half_angle);
  return qr;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文