Вычисление текстурных координат

Доброго времени суток.
Возникла потребность в создании генератора текстурных координат. Предположим, существует набор вершин произвольного трёхмерного объекта, сложной формы. Так при загрузке или создании подобного объекта, а быть может прямо во время его отрисовки, было бы здорово рассчитать текстурные координаты. Основной проблемой является определение коэффициента масштабирования.


У меня есть некоторые идеи на это счёт:
/*http://esate.ru, GLarus*/


      /// <summary>
      /// Вычисление текстурных координат полигона
      /// </summary>
      /// <param name="v1"> мировые координаты вершин треугольной грани,   </param>
      /// <param name="v2"> перечисленные в порядке </param>
      /// <param name="v3"> против часовой стрелки </param>
      /// <param name="scaleCoeff"> коэффициент масштабирования </param>
      /// <param name="t1"> текстурные </param>
      /// <param name="t2"> координаты </param>
      /// <param name="t3"> грани</param>
      public static void CalculatePolygonTextureCoordinates(
        Vector v1, Vector v2, Vector v3,
        float scaleCoeff,
        out Vector t1, out Vector t2, out Vector t3)
      {

        //Вычисляем нормаль треугольника:
        Vector n = Vector.NormalVector(v1, v2, v3);
        n = Vector.NormalizeVector(n);

        //Матрица масштабирования
        //|1|0|0|
        //|0|1|0|
        //|0|0|1|
        Matrix3 scale = new Matrix3();
        //-------------------------------------------------------------------------------------
        //Вычислим углы между плоскостью полигона и плоскостями XY,XZ,YZ
        //-------------------------------------------------------------------------------------

        float angX = (float)Vector.CalculateAngle(n, new Vector(1, 0, 0));
        float angY = (float)Vector.CalculateAngle(n, new Vector(0, 1, 0));
        float angZ = (float)Vector.CalculateAngle(n, new Vector(0, 0, 1));

        //Вычисляем матрицу поворота
        Matrix3 rotate = Matrix3.CreateRotateMatrix(angX, angY, angZ);

        //Инициализируем масштабирующую матрицу
        scale.R[0, 0] = scaleCoeff;
        scale.R[1, 1] = scaleCoeff;
        scale.R[2, 2] = scaleCoeff;  

        //-------------------------------------------------------------------------------------
        //Вычисляем ТК:
        //-------------------------------------------------------------------------------------
        Vector vt; //Трансформированная вершина
        vt = Matrix3.Transform(rotate, v1);
        vt = Matrix3.Transform(scale, vt);
        t1 = new Vector(vt.x, vt.y, 0);

        vt = Matrix3.Transform(rotate, v2);
        vt = Matrix3.Transform(scale, vt);
        t2 = new Vector(vt.x, vt.y, 0);

        vt = Matrix3.Transform(rotate, v3);
        vt = Matrix3.Transform(scale, vt);
        t3 = new Vector(vt.x, vt.y, 0);



Собственно причём тут координаты вершин. Так вот, предположим, что текстурные координаты - это особенным образом трансформированные мировые координаты вершин. И чтобы связать их с мировыми координатами, я сначала связываю их с локальными координатами объекта, а потом, используя афинные преобразования, привожу тк к мировым.

Пример объекта, масштабированного после поворота, с текстурой наложенной приведённым способом, но без масштабирующего коэффициента:


Рисуем:
/*http://esate.ru, GLarus*/


for (int i = 0; i < listBarriers.Count; i++)
{
Gl.glBindTexture(Gl.GL_TEXTURE_2D, listBarriers[i].cover[0].texObj);
Gl.glBegin(Gl.GL_TRIANGLES);
for (int j = 0; j < listBarriers[i].facesCount; j++)
                {
float x1, x2, x3, y1, y2, y3, z1, z2, z3;
                   // вытакскиваем координаты треугольника (полигона)
                   x1 = listBarriers[i].vertex[0, listBarriers[i].faces[0, j]];
                   x2 = listBarriers[i].vertex[0, listBarriers[i].faces[1, j]];
                   x3 = listBarriers[i].vertex[0, listBarriers[i].faces[2, j]];
                   y1 = listBarriers[i].vertex[1, listBarriers[i].faces[0, j]];
                   y2 = listBarriers[i].vertex[1, listBarriers[i].faces[1, j]];
                   y3 = listBarriers[i].vertex[1, listBarriers[i].faces[2, j]];
                   z1 = listBarriers[i].vertex[2, listBarriers[i].faces[0, j]];
                   z2 = listBarriers[i].vertex[2, listBarriers[i].faces[1, j]];
                   z3 = listBarriers[i].vertex[2, listBarriers[i].faces[2, j]];

                      Vector v1 = new Vector(x1, y1, z1);
                      Vector v2 = new Vector(x2, y2, z2);
                      Vector v3 = new Vector(x3, y3, z3);

TextureScaling.CalculatePolygonTextureCoordinates(
                        v1,
                        v2,
                        v3,
                        scaleCoeff,//Как рассчитать?
                        out t1, out t2, out t3);

                        Gl.glTexCoord2f(t1.x, t1.y);
                        Gl.glVertex3f(x1, y1, z1);
 
                        Gl.glTexCoord2f(t2.x, t2.y);
                        Gl.glVertex3f(x2, y2, z2);

                        Gl.glTexCoord2f(t3.x, t3.y);
                        Gl.glVertex3f(x3, y3, z3);

}
Gl.glEnd();
}


Есть ли какой - нибудь алгоритм вычисления масштабирующего коэффициента?
И быть может кто-нибудь пыталсь реализовать или реализовал эту задачу?

Буду благодарен за внимание.

</cut>
0       2688        11.03.2011        13

0  
11.03.2011 00:00:00
В opengl можно не мучатся с матрицами, просто сделай текущей матрицу текстурирования и применяй к текстурам glScaled glRotated итд
0  
12.03.2011 00:00:00
Например так, да:

Gl.glMatrixMode(Gl.GL_TEXTURE);
Gl.glLoadIdentity();
Gl.glScalef(0.5f, 0.5f, 0.5f);
Gl.glMatrixMode(Gl.GL_MODELVIEW);

Но опять тот же вопрос, как вычислить параметры для glScalef(d)? Они не соответствуют параметрам, которые я применяю для масштабирования самого объекта.
0  
12.03.2011 00:00:00
Ты хочешь, что бы при изменении размера объекта, изменялся размер текстуры? Можно в матрице modelview привязать текстурные координаты к объекту и при изменении его размера, текстура сама должна изменять изменять размер.

glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);

Возможно, я не так понял вопрос…
0  
12.03.2011 00:00:00
К сожалению всё не так просто, попробую объяснить как следует к чему я стремлюсь. Программа, которую я делаю включает в себя что-то вроде редактора. Мне захотелось собственноручно написать генератор текстурных координат. Потому что создав сложную поверхность или загрузив модель, имея только вершины, нужно привязать к объектам текстуры. Я знаю о встроенной gl функции для генерации тк, да и модель можно загрузить уже с тк, поэтому сейчас меня интересует только одна вещь, которая, если я правильно разобрался, необходима в любом случае. Это сохранение пропорций текстуры. Я хочу, чтобы кирпичики на текстуре всегда были одного размера на всех гранях не зависимо от их размера, ориентации.
Например для параллепипеда очень просто можно сохранять пропорции текстуры — домножить текстурные координаты на половину длины данной грани. Но это не работает в том случае, который на скриншоте(1), когда после поворота, осуществляется масштабирование объекта. Вопрос как сохранить пропорции текстуры для объекта? Как добиться того, чтобы например на цилиндре всегда были кирпичи одинакового размера?


0  
12.03.2011 00:00:00
я в текстурированнии не очень сильно понимаю, не хотел вникать в это из за ненадобности, но попробуй узнать отношение от первоначального размера до полученого и умножить это на соответствующую ось на координатах, по идее она трансфармируется с таким же отнашением и получится корректное изображение

простите за ошибки))
0  
12.03.2011 00:00:00
Спасибо) Думал о чём-то подобном. Получается, что нужно хранить информацию о каждом полигоне до и после масштабирования объекта, либо хранить только отношение размеров, а потом учитывать при наложении текстуры?
0  
13.03.2011 00:00:00
попробуй так и так
я вобще не знаю получится ли, хотя вроде должно
эт я так прочитал и сразу такой вот выход придумал
0  
13.03.2011 00:00:00
А что, если привязать текстуру только к верхним вершинам? Я не пробовал, но по идеи, она не должна сплющиться. Так же можно попробовать вообще не создавать текстурных координат.

Или вот ещё идея пришла: Когда ты scale делаешь, то всё происходит в modelviev, а если после этого открыть матрицу текстуры и изменить scale на предыдущий размер? Но это бредово, но можно попробовать…
0  
13.03.2011 00:00:00
Но одно я предполагаю точно, что масштабы тут не нужны, нужно генерировать текстурные координаты. Или в конце концов перейти к кубической карте.
0  
13.03.2011 00:00:00
масштабы как раз токи нада
как ты узнаешь как у тебя изменился полигон?? вот ты его отскалил а получится что текстурка такаяя же осталось

кстати я тут подумал, не надо хранить скал каждого полигона
ы что их менять будешь?? или всю модель??
0  
13.03.2011 00:00:00
Мне надо сконструировать помещение, а потом делать кое-какие расчёты. Т.е. надобно постоянно трансформировать объекты в процессе планировки.
0  
14.03.2011 00:00:00
делай так:

если трансформируешь модель то как я писал выше, если полигон то считай уже только относительно полигона, хотя я думаю что это не надо так как там должно быть и так нормально
0  
29.04.2011 00:00:00
Пожалуй, стоит однозначно завершить тему, обозначив результат. В итоге я делал так:
для всех объектов сохранял масштабирующие коэффициенты, которые я просто накапливал в процессе трансформации, а затем

Gl.glMatrixMode(Gl.GL_TEXTURE);
Gl.glLoadIdentity();
Gl.glScalef(object.scaleX, object.scaleY, object.scaleZ);
Gl.glMatrixMode(Gl.GL_MODELVIEW);

(Как мне предлагал amid в 1 комментарие)
Плюс использовал бесшовные текстуры, хорошего разрешения. Сделал их покрупнее, поделив текстурные координаты на некоторую величину.
Мне этого оказалось вполне достаточно для приличного отображения объектов на сцене))
^