Roman Cortes trajo rosas rojas escritas en scripts de JavaScript. ¡Rose Made with Code es el mejor regalo de San Valentín que se le da a tu novia por programadores increíbles! (Consejo: el efecto de visualización y la velocidad serán muy diferentes bajo diferentes navegadores)
La imagen se genera por código, y el usuario puede actualizar la página y repetir el proceso de presentación de observar la rosa.
El código de implementación de 3D Rose es el siguiente:
La copia del código es la siguiente: con (m = matemáticas) c = cos, s = sin, p = pow, r = aleator; c.width = c.height = f = 500; h = -250; función p (a, b, c) {if (c> 60) return [s (a*7)*(13+5/(. 2+p (b*4,4)))-s (b)*50, b*f+50,625+c (a*7)*(13+ 5/(. 2+P (B*4,4)))+B*400, A*1-B/2, A]; A = A*2-1; B = B*2-1; if (A*A+B*B <1) {if (C> 37) {N = (J = C & 1) ? 6: 4; o = .5/(a+.01)+c (b*125)*3-a*300; w = b*h; return [o*c (n)+w*s (n)+j*610-390, o*s (n) -w*c (n)+550-J*350,1180+C (b+a)*99-j*300, .4-a*.1+p (1-b*b, -h*6)*. 15-a*b*.4+c (a+b)/5+p (c (((((((((((((( o*(a+1)+(b> 0? W: -w))/25), 30)*. 1*(1-b*b), o/1e3+.7-o*w*3e-6]} if (c> 32) {c = c*1.16 -.15; o = A*45-20; w = b*b*h; z = o*s (c)+w*c (c) +620; return [o*c (c) -w*s (c), 28+c (b*.5)*99-b*b*b*60-z/ 2-H, Z, (B*B*.3+P ((1- (A*a)), 7)*. 15+.3)*B, B*.7]} O = A*(2-B)*(80-C*2); W = 99-C (a)*120-C (b)*(-HC*4.9)+C (P (1-B, 7))*50+C*2; Z = O*S (C)+W*C (C) +700; return [o*c (c) -w*s (c), b*99-c (p (b, 7))*50-c/3-z/1.35+450, z, (1-b/1.2)*. 9+a*.1, P ((1-b), 20) /4+.05]}} setinterval ('for (i = 0; i <1e4; i ++) if (s = p (r (), r (), i%46/.74)) {z = s [2]; x = ~~ (s [0]*f/zh); y = ~~ (s [1]*f/zh); )
Por supuesto, las personas interesadas pueden comprender el siguiente proceso de implementación y teorías relacionadas:
El efecto de presentación de este código tridimensional Rose usa el método Monte Carlo, y el Creador elogió al día elogió el método Monte Carlo. Dijo que el método Monte Carlo es una "herramienta increíblemente poderosa" en términos de optimización funcional y muestreo. Para el método Monte Carlo, consulte: Método Monte Carlo.
Operaciones específicas:
Dibujo de efecto de renderizado de muestreo de apariencia
Utilicé múltiples diagramas de forma diferentes para formar este código Rose. Se usaron un total de 31 formas: 24 pétalos, 4 sépalos, 2 hojas y 1 tallo de flores, y cada diagrama de forma se representaba en el código.
Primero, defina un rango de muestreo:
superficie de función (a, b) {// Estoy usando A y B como parámetros que varían de 0 a 1.return {x: a*50, y: b*50}; // Esta superficie será un cuadrado de 50x50 unidades de tamaño}Luego, escriba el código de delineación de la forma:
var canvas = document.body.appendChild (document.createElement ("Canvas")), context = canvas.getContext ("2d"), a, b, posición; // Ahora voy a probar la superficie a intervalos .1 para A y B parámetros: para (a = 0; a <1; a += .1) {para (b = 0; b <1; b += .1) b); context.fillrect (posicion.x, posicion.y, 1, 1);}}Ahora, intente un intervalo de muestreo más denso:
Como puede ver ahora, debido a que los intervalos de muestreo se están volviendo más densos y más cercanos, los puntos se están acercando cada vez más a la densidad más alta, la distancia entre los puntos adyacentes es inferior a un píxel y el intervalo no puede verse a simple vista (ver 0.01). Para no causar demasiada diferencia visual, el intervalo de muestreo se reduce aún más. En este momento, se ha llenado el área de dibujo (los resultados de comparación son 0.01 y 0.001).
A continuación, uso esta fórmula para dibujar un círculo: (x-x0)^2 + (y-y0)^2 <radio^2, donde (x0, y0) es el centro del círculo:
superficie de función (a, b) {var x = a * 100, y = b * 100, radius = 50, x0 = 50, y0 = 50; if ((x - x0) * (x - x0) + (y - y0) * (y - y0) <radius * radius) {// dentro del circlereturn {x: x, y: y};} más nulo;}}Para evitar el desbordamiento, se debe agregar una condición de muestreo:
if (posición = superficie (a, b)) {context.fillrect (posicion.x, posicion.y, 1, 1);}Hay diferentes formas de definir un círculo, algunas de las cuales no requieren rechazo del muestreo. No tengo que usar cuál definir un círculo, por lo que uso otro método para definir un círculo:
superficie de la función (a, b) {// círculo usando coordenadas polares de ángulo = a * math.pi * 2, radio = 50, x0 = 50, y0 = 50; return {x: math.cos (ángulo) * radio * b + x0, y: math.sin (ángulo) * radio * b + y0};}(Este método requiere un muestreo denso para el llenado en comparación con el método anterior).
Ok, ahora deja que el círculo se deforma para que se vea más como un pétalo:
function surface(a, b) {var x = a * 100,y = b * 100,radius = 50,x0 = 50,y0 = 50;if ((x - x0) * (x - x0) + (y - y0) * (y - y0) < radius * radius) {return {x: x,y: y * (1 + b) / 2 // deformation};} else {return null;}}Esto parece un pétalo de rosa. Aquí también puede intentar modificar algunos valores de función, y aparecerán muchas formas interesantes.
A continuación, agregue color:
superficie de la función (a, b) {var x = a * 100, y = b * 100, radio = 50, x0 = 50, y0 = 50; if ((x - x0) * (x - x0) + (y - y0) * (y - y0) <radius * radius) {return {x: x, y: y * (1 + b) / 2, r: 100 + math.floor ((1 - 1 - Burn {x: x, y: y * (1 + b) / 2, r: 100 + math.floor ((1 - 1 - burn {x: x, y: y * (1 + b) / 2, r: 100 + math.floor ((1 - 1 - b), ///////. Agregue un gradiente: 50, b: 50};} else {return null;}} para (a = 0; a <1; a + = .01) {para (b = 0; b <1; b + = .001) {if (punto = superficie (a, b) {context.fill.fillyle = "rgb (" + punto. ")"; context.fillrect (Point.x, Point.y, 1, 1);}}}Aparece un pétalo de color.
Proyección de superficie y perspectiva 3D
Definir una superficie tridimensional es simple, por ejemplo, para definir un objeto tubular:
function surface(a, b) {var angle = a * Math.PI * 2,radius = 100,length = 400;return {x: Math.cos(angle) * radius,y: Math.sin(angle) * radius,z: b * length - length / 2, // by subtracting length/2 I have centered the tube at (0, 0, 0)r: 0,g: Math.floor(b * 255),b: 0};}Luego agregue una perspectiva de proyección. Primero necesitamos definir una cámara:
Como se muestra arriba, coloque la cámara en la posición (0, 0, z) y el lienzo en el plano X/Y. Los puntos de muestreo proyectados en el lienzo son:
var px, py, // proyectado en el lienzo x e y coordenatesperspective = 350, halfheight = canvas.height / 2, halfwidth = canvas.width / 2, cameraz = -700; for (a = 0; a <1; a += .001) {para (b = 0; b <1; b += .01) {px = (punto.x * perspectiva) / (punto.z - cámara) + halfwidth; py = (point.y * perspectiva) / (punto.z - cameraz) + halfHeight; context.fillStyle = "rgb (" + punto.r + "," + punto.g + "," + punto.b + ")"; context.fillrect (px, py, 1, 1, 1);El efecto es:
Buffer Z
Z-Buffer es una técnica muy común en los gráficos por computadora. Al sombrear los objetos, el trabajo de "eliminación de la superficie oculta" se realiza para que no se muestre la parte detrás de los objetos ocultos.
La imagen de arriba es una rosa procesada con tecnología Z-Buffer. (Puedes ver que ya tiene tridimensionalidad)
El código es el siguiente:
var zbuffer = [], zBufferIndex; for (a = 0; a <1; a += .001) {for (b = 0; b <1; b += .01) {if (punto = superficie (a, b)) {px = math.floor ((punto.x * perspectiva) / (punto.z - camilaz) +mediowidth); px.floor ((Point * perspectiva). (Point.z - Cameraz) + HalfHeight); ZBufferIndex = Py * Canvas.Width + Px; if ((typeOf ZBuffer [ZBufferIndex] === "Undefinado") || (Point.z <ZBuffer [ZBufferIndex]) {ZBuffer [ZBUffinEx] = Point.z; contexty. Point.r + "," + Point.g + "," + Point.b + ")"; context.FillRect (Px, Py, 1, 1);}}}}Girar
Puede usar cualquier método de rotación vectorial. En la creación del código Rose, uso la rotación de Euler. Ahora gire el objeto tubular previamente escrito para rotar sobre el eje Y:
superficie de función (a, b) {var ángulo = a * math.pi * 2, radio = 100, longitud = 400, x = math.cos (ángulo) * radio, y = math.sin (ángulo) * radio, z = b * longitud - longitud / 2, yaxisrotationAngle = -.4, // en radians! rotadox = x * math.cos (cyaxisrotangle) + c * * c * * c * * c * * c. * Math.sin (YaxisRotationAngle), rotedz = x * -math.sin (yaxisrotationAngle) + z * math.cos (yaxisrotationAngle); return {x: rotatedx, y: y, z: rotedz, r: 0, g: math.floor (b * 255), b: 0};}Efecto:
Método de Monte Carlo
Con respecto al tiempo de muestreo, demasiado grande y demasiado pequeño causará una experiencia visual extremadamente pobre, por lo que se debe establecer un intervalo de muestreo razonable, y aquí se usa el método Monte Carlo.
var i; window.setInterval (function () {for (i = 0; i <10000; i ++) {if (punto = superficie (math.random (), math.random ())) {px = math.floor ((punto.x * perspectiva) / (punto.z - camera) +mediowidth); py = math.floor ((punto * perspectiva) / (cámara) halfHeight);zBufferIndex = pY * canvas.width + pX;if ((typeof zBuffer[zBufferIndex] === "undefined") || (point.z < zBuffer[zBufferIndex])) {zBuffer[zBufferIndex] = point.z;context.fillStyle = "rgb(" + point.r + "," + point.g + "," + punto.b + ")"; context.fillrect (px, py, 1, 1);}}}}, 0);Establezca A y B como parámetros aleatorios y complete el relleno de superficie con suficiente muestreo. Dibujo 10000 puntos cada vez y espero que la pantalla complete la actualización.
También se debe tener en cuenta que si un número aleatorio es incorrecto, el efecto de llenado de superficie será incorrecto. En algunos navegadores, la ejecución de matemáticas. En este momento, debe usar algo como Mersenne Twister (un algoritmo de número aleatorio) para realizar un muestreo PRNG de alta calidad para evitar errores.
Finalizar
Para que cada parte de la rosa se complete y renderice al mismo tiempo, se debe agregar una característica para establecer un parámetro para cada parte para devolver el valor para la sincronización. Y use una función de segmento para representar las diversas partes de la rosa. Por ejemplo, en la parte del pétalo, uso la rotación y la deformación para crearlos.
Aunque el método de muestreo de superficie es uno de los métodos más famosos y más antiguos para crear gráficos tridimensionales, este método para agregar Monte Carlo y Z-Buffer al muestreo de superficie no es común. Esto puede no ser muy creativo para la producción de escenarios de la vida real, pero su implementación de código simple y su tamaño pequeño aún son satisfactorios.
Esperemos que este artículo inspire a los entusiastas de los gráficos por computadora para que prueben diferentes métodos de presentación y se divierta de él. (Cortés romano)
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.