Estoy en el proceso de desarrollar un editor 3D básico. Utiliza OpenGL para renderizar un mundo 3D. En este momento, mi escena es solo unas pocas cajas de diferentes tamaños y estoy en la etapa en la que quiero poder seleccionar cada caja y luego moverla / escalarla / rotarla para lograr cualquier transformación que desee.
¿Cómo puedo resolver el problema de implementar tanto el renderizado de los artilugios de estas herramientas (o identificadores, o cómo las personas generalmente los llaman) y también elegirlos en cada eje para realizar el cambio en la transformación con mi mouse? Para mayor claridad:
Mi investigación hasta ahora sugirió que el enfoque más limpio es tener un cuadro delimitador alineado por eje por flecha en el gizmo y otro por cuadrado (los que mueven el objeto en un plano en lugar de un solo eje) y luego emitir un rayo desde el mouse posición y ver con qué choca. Pero esto todavía es demasiado abstracto para mí, agradecería más orientación sobre cómo funcionaría este algoritmo (el pseudocódigo es más que suficiente)
Respuestas:
En algún momento de mi tiempo en e-on, he mantenido los artilugios de la línea de productos Vue .
Puedo decirte que te llevará varios días, a tiempo completo.
A menos que encuentre alguna biblioteca o una forma súper inteligente, la forma clásica es obtener la coordenada del mouse en la ventana cuando hace clic, si es una coordenada relativa a la ventana gráfica, simplemente puede dividir x e y por ancho y alto, usted obtener un vector (flotante 2d) en el rango [0,1]. reste (0.5,0.5) para obtener el rango [-0.5, 0.5] para x e y.
Luego, haces un rayo a partir de esta coordenada usando las x e y simplemente como el rayo x e y, y configuras z a la distancia focal. a veces la relación de aspecto es un dolor en el culo en esta operación. Un poco de violín y error de prueba lo solucionarán.
Luego, debe verificar la intersección con sus elementos de gizmos, ya sea que tenga una malla que generó, o que esté modelada en una licuadora u otro DCC, o partes de malla que puedan articularse entre sí ... Solo use esas partes de malla como un rayo / consulta de intersección triangular.
O si lo tiene, rayo / cilindro, rayo / esfera de acuerdo con su apariencia de gizmo y partes.
Debe tener rutinas de intersección que sean capaces de aplicar una matriz de transformación en la primitiva que colisionan . Extremadamente importante porque su artilugio se traducirá con el objeto que sirve para moverse, rotará y se escalará con el inverso de la distancia a la cámara, de modo que mantenga un tamaño proyectado fijo en la pantalla.
Luego tiene la parte de interacción, la más fácil es tomar el delta del punto en que el mouse fue el primer evento de "mouse down" y la posición actual de "Mouse mover", en 2D puro, y usar este delta como el movimiento actual del eje en el espacio mundial, multiplicado por algunos
k
que tú decides empíricamente. De acuerdo con sus unidades internas versus píxel versus escala actual de zoom, etc.El paso final es simplemente aplicar la matriz del gizmo al objeto manipulado, para que lo siga.
Te digo que implementarlo es todo un viaje al infierno, y si lo estás haciendo en tu tiempo libre, espera más de una semana. Varias semanas si estás descubriendo completamente el campo. Más de un mes si sus fines de semana están ocupados con otras actividades :)
Le sugiero que descargue Embree 2.0 de Intel para hacer la consulta de intersección de rayos / triángulos por usted, para que no tenga que preocuparse por codificar eso. O podría copiar / pegar sin piedad y adaptar el código de Blender ... ¿Creo que se mudaron a la licencia de Apache? Debería ser posible legalmente.
fuente
Para manipulador-traductor, uso el siguiente algoritmo:
1) Cuando el mouse está presionado, necesitamos verificar si el rayo se cruza con la flecha. Por ejemplo, consideramos la flecha X. Construimos Ray en el espacio mundial (basado en el frustum de la cámara y la posición del mouse). Construimos un plano en el que se encuentra el eje x: su normal es igual V cruz X cruz V, donde V - vector desde el centro a la cámara, X - representa el eje x. Luego intersectamos el rayo con el plano y, por lo tanto, encontramos el punto de intersección en coordenadas mundiales. Luego proyectamos el segmento del eje xy el punto resultante nuevamente en la pantalla, buscamos la distancia entre el segmento proyectado y el punto proyectado en la pantalla. Si tiene menos de unos pocos píxeles, el mouse introduce el eje. También calculamos el vector delta del espacio mundial entre el centro de selección y nuestra intersección.
Este procedimiento lo hacemos para 3 ejes, por lo que encontramos distancias a todos los ejes. Encuentra la distancia mínima. así que encontramos con qué eje se cruza el mouse.
2) Cuando el mouse se mueve. sabemos por qué eje se mueve el objeto (de 1). encontramos la intersección espacial mundial del rayo con el plano (como en 1). además, proyectamos el punto de intersección en la línea a lo largo de la cual se mueve el objeto. posición final del manipulador = intersección + delta.
fuente