如何上下移动物体并使其碰到屋顶和底部时变形?
我创建了一个球体,该球体通过沿y轴平移而无限旋转并向上移动,但是现在我必须向下移动它,并且当它上下碰撞时我希望它变形。现在我的问题是:
(1)如何使球体在y轴上上下移动?
(2)触摸顶部时如何变形?并在上下移动的同时完成顶部或底部的接触,以恢复相同的形状。
我的旋转球体代码是(我在此链接https://github.com/gpjt/webgl-lessons/blob/master/lesson11/index.html上遵循了Git Hub教程的第11课):
var newRotationMatrix = mat4.create();
mat4.identity(newRotationMatrix);
mat4.rotate(newRotationMatrix, degToRad(2 / 10), [0, 1, 0]);
mat4.multiply(newRotationMatrix, [1,0,0], moonRotationMatrix);
gl.drawElements(gl.TRIANGLES, moonVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
完整功能是:
function tick()
{
requestAnimFrame(tick);
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
gl.uniform1i(shaderProgram.useLightingUniform, false);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, [0, 0, -6]);
mat4.multiply(mvMatrix, moonRotationMatrix);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, moonTexture);
gl.uniform1i(shaderProgram.samplerUniform, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, moonVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, moonVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, moonVertexTextureCoordBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, moonVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, moonVertexNormalBuffer);
gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, moonVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, moonVertexIndexBuffer);
setMatrixUniforms();
/*rotation part is below*/
var newRotationMatrix = mat4.create();
mat4.identity(newRotationMatrix);
mat4.rotate(newRotationMatrix, degToRad(2 / 10), [0, 1, 0]);
mat4.multiply(newRotationMatrix, [1,0,0], moonRotationMatrix);
gl.drawElements(gl.TRIANGLES, moonVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
}
在此代码中添加什么内容,使其旋转并必须触摸顶部和底部(下面说,它们沿y轴与中心的距离为250和-250,因为运动必须沿y轴)
以及当球体在上升过程中接触250并在-250下降时仍会变形并随着球体与顶部或底部之间的接触完成而立即恢复的过程,此过程应无限重复。
编辑:
在此问题中,moonVertexIndexBuffer在tick函数中包含正方形的顶点。
这是我的initfuffer函数
function initBuffers(latitudeBands, longitudeBands)
{
var radius = 1;
var vertexPositionData = [];
var normalData = [];
var textureCoordData = [];
for (var latNumber = 0; latNumber <= latitudeBands; latNumber++)
{
var theta = latNumber * Math.PI / latitudeBands;
var sinTheta = Math.sin(theta);
var cosTheta = Math.cos(theta);
for (var longNumber = 0; longNumber <= longitudeBands; longNumber++)
{
var phi = longNumber * 2 * Math.PI / longitudeBands;
var sinPhi = Math.sin(phi);
var cosPhi = Math.cos(phi);
var x = cosPhi * sinTheta;
var y = cosTheta;
var z = sinPhi * sinTheta;
var u = 1 - (longNumber / longitudeBands);
var v = 1 - (latNumber / latitudeBands);
normalData.push(x);
normalData.push(y);
normalData.push(z);
textureCoordData.push(u);
textureCoordData.push(v);
vertexPositionData.push(radius * x);
vertexPositionData.push(radius * y);
vertexPositionData.push(radius * z);
}
}
alert("vertexPositionData:" + vertexPositionData);
var indexData = [];
for (var latNumber = 0; latNumber < latitudeBands; latNumber++) {
for (var longNumber = 0; longNumber < longitudeBands; longNumber++) {
var first = (latNumber * (longitudeBands + 1)) + longNumber;
var second = first + longitudeBands + 1;
indexData.push(first);
indexData.push(second);
indexData.push(first + 1);
indexData.push(second);
indexData.push(second + 1);
indexData.push(first + 1);
//console.log("four points for iteration" + latNumber, +longNumber + " are " + "1: " + first + "2 :" + (first + 1) + "3: " + (second) + "4 :" + (second + 1));
}
}
moonVertexNormalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, moonVertexNormalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normalData), gl.STATIC_DRAW);
moonVertexNormalBuffer.itemSize = 3;
moonVertexNormalBuffer.numItems = normalData.length / 3;
moonVertexTextureCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, moonVertexTextureCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordData), gl.STATIC_DRAW);
moonVertexTextureCoordBuffer.itemSize = 2;
moonVertexTextureCoordBuffer.numItems = textureCoordData.length / 2;
///
moonVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, moonVertexPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositionData), gl.STATIC_DRAW);
moonVertexPositionBuffer.itemSize = 3;
moonVertexPositionBuffer.numItems = vertexPositionData.length / 3;
moonVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, moonVertexIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), gl.DYNAMIC_DRAW);
moonVertexIndexBuffer.itemSize = 1;
moonVertexIndexBuffer.numItems = indexData.length;
}
function tick()
{
requestAnimFrame(tick);
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
// var lighting = false;
gl.uniform1i(shaderProgram.useLightingUniform, false);
/*I removed some part here */
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, [0, 0, -6]);
mat4.multiply(mvMatrix, moonRotationMatrix);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, moonTexture);
gl.uniform1i(shaderProgram.samplerUniform, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, moonVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, moonVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, moonVertexTextureCoordBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, moonVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, moonVertexNormalBuffer);
gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, moonVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, moonVertexIndexBuffer);
setMatrixUniforms();
var newRotationMatrix = mat4.create();
mat4.identity(newRotationMatrix);
mat4.rotate(newRotationMatrix, degToRad(2 / 10), [0, 1, 0], newRotationMatrix);
mat4.multiply(newRotationMatrix, moonRotationMatrix, moonRotationMatrix);
gl.drawElements(gl.TRIANGLES, moonVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
}
这是我的顶点着色器:
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoord;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform mat3 uNMatrix;
uniform vec3 uAmbientColor;
uniform vec3 uLightingDirection;
uniform vec3 uDirectionalColor;
uniform bool uUseLighting;
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aTextureCoord;
if (!uUseLighting) {
vLightWeighting = vec3(1.0, 1.0, 1.0);
} else {
vec3 transformedNormal = uNMatrix * aVertexNormal;
float directionalLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0);
vLightWeighting = uAmbientColor + uDirectionalColor * directionalLightWeighting;
}
}
</script>
这是initshaders功能
function initShaders()
{
var fragmentShader = getShader(gl, "shader-fs");
var vertexShader = getShader(gl, "shader-vs");
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
shaderProgram.vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");
gl.enableVertexAttribArray(shaderProgram.vertexNormalAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
shaderProgram.nMatrixUniform = gl.getUniformLocation(shaderProgram, "uNMatrix");
shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
shaderProgram.useLightingUniform = gl.getUniformLocation(shaderProgram, "uUseLighting");
shaderProgram.ambientColorUniform = gl.getUniformLocation(shaderProgram, "uAmbientColor");
shaderProgram.lightingDirectionUniform = gl.getUniformLocation(shaderProgram, "uLightingDirection");
shaderProgram.directionalColorUniform = gl.getUniformLocation(shaderProgram, "uDirectionalColor");
}
**我无法理解如何无限地上下移动它(沿y轴平移),因为我们将所有正方形都放置在数组中,因为球体是正方形(取决于initBuffers()中传递的纬度和经度)功能)**
我的尝试是这样(但是球体会无限上升,再也不会下降,如何降低它)?
var translation = [0, 0.5,0];
function tick()
{
....//I am elminating the code which was shown previously
var translationMatrix = makeTranslation(translation[0], translation[1], translation[2]);
mat4.multiply(moonRotationMatrix, translationMatrix, moonRotationMatrix);
}
function makeTranslation(tx, ty, tz) {
return [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
tx, ty, tz, 1
];
}
EDIT2:在第一个答案之后,我尝试缩放变形:
在顶点着色器中,我按照以下建议保持一致:
<script id="shader-vs" type="x-shader/x-vertex">
uniform vec4 uScaleY;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
}
}
</script>
在initshader()中,我这样做:
shaderProgram.uScaleYAttribute = gl.getUniformLocation(shaderProgram, "uScaleY");
在setuniform中,我这样做:
var yScale =[0,1,0];
function setMatrixUniforms()
{
gl.uniformMatrix4fv(shaderProgram.uScaleYAttribute, false, yScale);
}
在我的tick()中,我尝试这样做:
var newRotationMatrix = mat4.create();
mat4.identity(newRotationMatrix);
mat4.rotate(newRotationMatrix, degToRad(2 / 10), [0, 1, 0]);
mat4.multiply(newRotationMatrix, moonRotationMatrix, moonRotationMatrix);
translateMatrix = translation(translate[0], translate[1], translate[2]);
mat4.multiply(moonRotationMatrix, translateMatrix,moonRotationMatrix);
var maxY =1.5;
var moonPosY = moonRotationMatrix[3 * 4 +1];
if (moonPosY > maxY || moonPosY < (-maxY))
{
translate[1] *= -1;
}
var maxDiff = 0.05;
var minDiff = 0.01;
var diff = Math.abs(moonPosY - maxY);
if (diff < maxDiff)//sphere when go up
{
yScale = 1 - (minDiff - diff) * 0.1;
}
/*
else if (moonPosY > (-maxDiff)) // scaling when sphere come down
{
yScale = 1 - (minDiff - diff) * 0.1;
}
*/
gl.drawElements(gl.TRIANGLES, moonVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
而且缩放在上下接触球体时沿y轴变形不起作用,我的代码有什么问题?
最佳答案
更改您的tick
以便跟踪总翻译量,并在达到阈值时反转使用的翻译向量。
就像这样:
var maxY = 100;
var moonPosY = moonRotationMatrix[/*row*/ 3 * 4 + /*col*/ 1];
if (moonPosY < maxY || moonPosY < (-maxY)) {
translation = translation.map(a => -a);
// or simply
// translation[1] *= -1;
// if you want to reverse it just on Y axis
}
要使它变形,取决于您想要的变形,但是如果您只想沿Y轴对其进行挤压,则可以为您的顶点着色器添加一个统一的Y缩放比例,并用类似以下内容填充它:
var yScale = 1;
var maxDiff = 10;
var diff = Math.abs(moonPosY - maxY);
if (diff < maxDiff) {
yScale = 1 - (minDiff - diff) * 0.1;
}
关于javascript - 如何沿y轴平移球体(它只是上升,所以平移不会下降),以及如何变形,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33148865/