Tengo algo de geometría 2D. Quiero tomar un rectángulo delimitador alrededor de mi geometría, y luego presentar una versión más pequeña de ella en otro lugar del avión. Aquí es más o menos el código que tengo que hacer escala y la traducción:OpenGL: escalar y traducir? ¿y cómo?
// source and dest are arbitrary rectangles.
float scaleX = dest.width/source.width;
float scaleY = dest.height/source.height;
float translateX = dest.x - source.x;
float translateY = dest.y - source.y;
glScalef(scaleX, scaleY, 0.0);
glTranslatef(translateX, translateY, 0.0);
// Draw geometry in question with its normal verts.
Esto funciona exactamente como se esperaba para una dimensión dada cuando el origen dest es 0. Pero si el origen para, por ejemplo, x, es distinto de cero, el resultado sigue siendo escalado correctamente pero parece (?) se traduce a algo cercano a cero en ese eje de todos modos ... resulta que no es exactamente lo mismo que si dest.x fuera cero.
¿Alguien puede indicar algo obvio que me falta?
Gracias!
ACTUALIZACIÓN FINAL Según las respuestas de Bahbar y Marcus a continuación, hice más experimentación y resolví esto. El comentario de Adam Bowen fue el consejo. Me faltaban dos hechos críticos:
- Necesitaba escalar el centro de la geometría que me importaba.
- Necesitaba aplicar las transformaciones en el orden opuesto a la intuición (para mí).
El primero es obvio en retrospectiva. Pero para este último, para otros buenos programadores/malos matemáticos como yo: Resulta que mi intuición estaba operando en lo que el Red Book llama un "Gran Sistema de Coordenadas Fijas", en el cual hay un plano absoluto, y su geometría se mueve en ese plano usando transformaciones. Esto está bien, pero dada la naturaleza de las matemáticas detrás de apilar transformaciones múltiples en una matriz, es lo opuesto a cómo funcionan realmente las cosas (ver respuestas a continuación o Libro Rojo para obtener más información). Básicamente, las transformaciones se "aplican" en "orden inverso" a la forma en que aparecen en el código. Aquí está la solución de trabajo final:
// source and dest are arbitrary rectangles.
float scaleX = dest.width/source.width;
float scaleY = dest.height/source.height;
Point sourceCenter = centerPointOfRect(source);
Point destCenter = centerPointOfRect(dest);
glTranslatef(destCenter.x, destCenter.y, 0.0);
glScalef(scaleX, scaleY, 0.0);
glTranslatef(sourceCenter.x * -1.0, sourceCenter.y * -1.0, 0.0);
// Draw geometry in question with its normal verts.
En resumen, cambie el orden a glTranslate (dest); glScale (escala); glTranslate (fuente); –
Adam: Esto no parece funcionar como sugieres, aunque estoy intrigado. ¿Puedes explicar por qué el orden sería así y quizás ofrecer una idea más explícita de cómo se vería en relación con el código existente? ? Tal vez estoy malinterpretando tu pseudocódigo. ¡Gracias! –
Nevermind: el "no funciona" fue un valor engined en este caso. Después de arreglar eso, estamos en el negocio. Vea la pregunta actualizada para más. ¡Gracias! –