Hallo 
Ich befürchte, ich habe dieses mal ein Problem, das sich gar nicht lösen lässt.
Es geht nämlich um https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Math/pow und zwar um den speziellen Fall: Math.pow(-7, 0.5);
Solche Werte habe ich leider bei meinem Superellipsoid. http://regular-polygon.com/plugins/superellipsoid/images/superellipsoid-3-xlarge.png
Lässt sich dieses Problem irgendwie auf mathematischen Weg umgehen?
Hier der Code, wo ich mit pow arbeite:
Für alle, die sich das Problem anschauen wollen (nur als Background-Info gedacht):
Problem im initBuffers.
Meine Notlösung wäre es, die Punkte nicht alle zu berechnen, sondern sie zu duplizieren und zu manipulieren. 1/8 des Objekts lässt sich nämlich berechnen. Die restlichen 7/8 könnte ich dann mit einem Hilfsprogramm ermitteln.
Aber es würde mir viel besser gefallen, wenn ich diesen Workaround vermeiden, und statt dessen auf eine mathematische Lösung zurückgreifen könnte.
- - - Aktualisiert - - -
Problem gelöst
Einfach 2 Hilfsfunktionen definiert.
Ich befürchte, ich habe dieses mal ein Problem, das sich gar nicht lösen lässt.
Es geht nämlich um https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Math/pow und zwar um den speziellen Fall: Math.pow(-7, 0.5);
Solche Werte habe ich leider bei meinem Superellipsoid. http://regular-polygon.com/plugins/superellipsoid/images/superellipsoid-3-xlarge.png
Lässt sich dieses Problem irgendwie auf mathematischen Weg umgehen?
Hier der Code, wo ich mit pow arbeite:
Code:
let s1 = 1.1; // superellipse-Parameter
let s2 = 1.1;
let rX = 1;
let rY = 1;
let rZ = 1;
let count = 4; // Anzahl der Vertices in width und depth
let f1 = 180 / count; // Schrittweite in Grad für kappa1
let f2 = 360 / count; // Schrittweite in Grad für kappa2
for(let i = 0; i < count; ++i) { // für kappa2
let kappa2 = (-count / 2 + i) * f2; // von -PI bis +PI
for(let j = 0; j < count; ++j) { // für kappa1
let kappa1 = (-count / 2 + j) * f1;
let cosKappa1S1 = Math.pow(Math.cos(deg2Rad(kappa1)), s1);
let x = rX * cosKappa1S1 * Math.pow(Math.cos(deg2Rad(kappa2)), s2);
let y = rY * cosKappa1S1 * Math.pow(Math.sin(deg2Rad(kappa2)), s2);
let z = rZ * Math.pow(Math.sin(deg2Rad(kappa1)), s1);
}
}
Für alle, die sich das Problem anschauen wollen (nur als Background-Info gedacht):
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://cdn.rawgit.com/toji/gl-matrix/v1.3.7/gl-matrix-min.js" type="text/javascript"></script>
<script src="webgl.js" type="text/javascript"></script>
</head>
<body onload="webGLStart();">
<canvas id="webgl-canvas" width="500" height="500">
Your browser is not supported
</canvas>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying float d;
void main(void) {
float c = 1.0 - d / 8.0;
gl_FragColor = vec4(c, c, c, 1.0);
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying float d;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
d = length(gl_Position);
gl_PointSize = 8.0 - d;
}
</script>
</body>
</html>
Code:
"use strict";
var gl;
var shaderProgram;
var cylinderVertexPositionBuffer;
var pMatrix = mat4.create();
var mvMatrix = mat4.create();
function webGLStart() {
var canvas = document.getElementById( "webgl-canvas" );
initGL( canvas );
initShaders();
initBuffers();
gl.clearColor( 0.0, 0.0, 0.0, 1.0 );
gl.enable( gl.DEPTH_TEST );
drawScene();
}
function initGL( canvas ) {
try {
gl = canvas.getContext( "experimental-webgl" );
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
} catch( e ) {
}
if ( !gl ) {
alert("Could not initialise WebGL");
}
}
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.pMatrixUniform = gl.getUniformLocation( shaderProgram, "uPMatrix" );
shaderProgram.mvMatrixUniform = gl.getUniformLocation( shaderProgram, "uMVMatrix" );
}
function getShader( gl, id ) {
var shaderScript = document.getElementById( id );
if( !shaderScript ) {
return null;
}
var str = "";
var k = shaderScript.firstChild;
while( k ) {
if( k.nodeType == 3 ) {
str += k.textContent;
}
k = k.nextSibling;
}
var shader;
if( shaderScript.type == "x-shader/x-fragment" ) {
shader = gl.createShader( gl.FRAGMENT_SHADER );
} else if ( shaderScript.type == "x-shader/x-vertex" ) {
shader = gl.createShader( gl.VERTEX_SHADER );
} else {
return null;
}
gl.shaderSource( shader, str );
gl.compileShader( shader );
if( !gl.getShaderParameter( shader, gl.COMPILE_STATUS )) {
alert( gl.getShaderInfoLog( shader ));
return null;
}
return shader;
}
var vertices = [];
function initBuffers() {
// Punkte:
// Hiermit gibt es Probleme mit pow:
let s1 = 1.1; // superellipse-Parameter
let s2 = 1.1;
// Hiermit funktioniert alles:
//let s1 = 1; // superellipse-Parameter
//let s2 = 1;
let rX = 1;
let rY = 1;
let rZ = 1;
let count = 4; // Anzahl der Vertices in width und depth
let f1 = 180 / count; // Schrittweite in Grad für kappa1
let f2 = 360 / count; // Schrittweite in Grad für kappa2
for(let i = 0; i < count; ++i) { // für kappa2
let kappa2 = (-count / 2 + i) * f2; // von -PI bis +PI
for(let j = 0; j < count; ++j) { // für kappa1
let kappa1 = (-count / 2 + j) * f1;
let cosKappa1S1 = Math.pow(Math.cos(deg2Rad(kappa1)), s1);
// nur zum Testen eingefügt:
alert(Math.cos(deg2Rad(kappa2)));
alert(s2);
alert(Math.pow(Math.cos(deg2Rad(kappa2)), s2));
alert(Math.pow(-1, 1.1));
let x = rX * cosKappa1S1 * Math.pow(Math.cos(deg2Rad(kappa2)), s2);
let y = rY * cosKappa1S1 * Math.pow(Math.sin(deg2Rad(kappa2)), s2);
let z = rZ * Math.pow(Math.sin(deg2Rad(kappa1)), s1);
vertices = vertices.concat([x, y, z]);
// nur zum Testen eingefügt:
break;
}
// nur zum Testen eingefügt:
break;
}
console.log(vertices);
cylinderVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, cylinderVertexPositionBuffer );
gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( vertices ), gl.STATIC_DRAW );
cylinderVertexPositionBuffer.itemSize = 3;
cylinderVertexPositionBuffer.numItems = vertices.length / cylinderVertexPositionBuffer.itemSize;
}
function drawScene() {
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, 20.0, pMatrix );
mat4.identity( mvMatrix );
mat4.translate( mvMatrix, [ 0.0, 0.0, -3.0 ] );
//mat4.rotateY( mvMatrix, deg2Rad( -20 ) );
mat4.rotateX( mvMatrix, deg2Rad( 25 ) );
gl.bindBuffer( gl.ARRAY_BUFFER, cylinderVertexPositionBuffer );
gl.vertexAttribPointer( shaderProgram.vertexPositionAttribute, cylinderVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0 );
setMatrixUniforms();
gl.drawArrays(gl.POINTS, 0, vertices.length / 3);
//gl.drawArrays( gl.LINES, 0, cylinderVertexPositionBuffer.numItems );
}
function setMatrixUniforms() {
gl.uniformMatrix4fv( shaderProgram.pMatrixUniform, false, pMatrix );
gl.uniformMatrix4fv( shaderProgram.mvMatrixUniform, false, mvMatrix );
}
function deg2Rad( x ) {
return x * Math.PI / 180;
}
Meine Notlösung wäre es, die Punkte nicht alle zu berechnen, sondern sie zu duplizieren und zu manipulieren. 1/8 des Objekts lässt sich nämlich berechnen. Die restlichen 7/8 könnte ich dann mit einem Hilfsprogramm ermitteln.
Aber es würde mir viel besser gefallen, wenn ich diesen Workaround vermeiden, und statt dessen auf eine mathematische Lösung zurückgreifen könnte.
- - - Aktualisiert - - -
Problem gelöst
Code:
function powSin(rad, exp) {
let v = Math.sin(rad);
return (v < 0) ? -Math.pow(-v, exp) : Math.pow(v, exp);
}
function powCos(rad, exp) {
let v = Math.cos(rad);
return (v < 0) ? -Math.pow(-v, exp) : Math.pow(v, exp);
}
Zuletzt bearbeitet von einem Moderator: