Программное создание простого UV-сопоставления для моделей

Исходя из этот вопрос. Я пытаюсь сгенерировать UV-отображения программно с помощью Three.js для некоторых моделей, мне это нужно, потому что мои модели тоже генерируются программно, и мне нужно применить к ним простую текстуру. Я прочитал здесь и успешно сгенерировал UV-отображение для некоторого простого 3D-текста, но при применении такое же сопоставление с более сложными моделями просто не работает.

Текстура, которую я пытаюсь применить, выглядит примерно так:

введите здесь описание изображения

Черный фон просто прозрачен в изображении PNG. Мне нужно применить это к моим моделям, это просто эффект блеска, поэтому меня не волнует точное положение в модели, есть ли способ программно создать простую УФ-карту для этих случаев?

Я использую этот код из связанного вопроса, который отлично работает для плоских моделей, но не работает для неплоских моделей:

assignUVs = function( geometry ){

    geometry.computeBoundingBox();

    var max     = geometry.boundingBox.max;
    var min     = geometry.boundingBox.min;

    var offset  = new THREE.Vector2(0 - min.x, 0 - min.y);
    var range   = new THREE.Vector2(max.x - min.x, max.y - min.y);

    geometry.faceVertexUvs[0] = [];
    var faces = geometry.faces;

    for (i = 0; i < geometry.faces.length ; i++) {

      var v1 = geometry.vertices[faces[i].a];
      var v2 = geometry.vertices[faces[i].b];
      var v3 = geometry.vertices[faces[i].c];

      geometry.faceVertexUvs[0].push([
        new THREE.Vector2( ( v1.x + offset.x ) / range.x , ( v1.y + offset.y ) / range.y ),
        new THREE.Vector2( ( v2.x + offset.x ) / range.x , ( v2.y + offset.y ) / range.y ),
        new THREE.Vector2( ( v3.x + offset.x ) / range.x , ( v3.y + offset.y ) / range.y )
      ]);

    }

    geometry.uvsNeedUpdate = true;
}

person Andres    schedule 23.01.2016    source источник
comment
Если это просто эффект блеска, не лучше ли просто создать шейдер? что-то вроде ЭТО   -  person 2pha    schedule 25.01.2016


Ответы (1)


Вам нужно быть более конкретным. Здесь я применю UV-отображение программно.

for (i = 0; i < geometry.faces.length ; i++) {
   geometry.faceVertexUvs[0].push([
     new THREE.Vector2( 0, 0 ),
     new THREE.Vector2( 0, 0 ),
     new THREE.Vector2( 0, 0 ),
   ]);
}

Счастливый?

Существует бесконечное множество способов применения UV-координат. Как насчет этого

for (i = 0; i < geometry.faces.length ; i++) {
   geometry.faceVertexUvs[0].push([
     new THREE.Vector2( Math.random(), Math.random() ),
     new THREE.Vector2( Math.random(), Math.random() ),
     new THREE.Vector2( Math.random(), Math.random() ),
   ]);
}

Нет ПРАВИЛЬНОГО ответа. Просто все, что вы хотите сделать, зависит от вас. Это как спрашивать, как я наношу карандаш на бумагу.

Извините за язвительность, просто указать на вопрос в каком-то смысле бессмысленно.

В любом случае, есть несколько распространенных способов нанесения текстуры.

  • Сферическое отображение

    Представьте, что ваша модель полупрозрачна, внутри есть сфера, сделанная из пленки, а внутри сферы находится точечный источник света, так что он проецируется (как кинопроектор) из сферы во всех направлениях. Таким образом, вы делаете математику, чтобы вычислить правильные UV для этой ситуации.

    Чтобы получить точку на сфере, умножьте свои точки на обратную мировую матрицу для сферы, а затем нормализуйте результат. После этого, однако, все еще остается проблема того, как сама текстура отображается на воображаемую сферу, для чего снова существует бесконечное количество способов.

    Самый простой способ, я думаю, называется проекцией Меркатора, как работает большинство 2D-карт мира. у них проблема в том, что много места на северном и южном полюсах тратится впустую. Предполагая, что x, y, z являются нормализованными координатами, упомянутыми в предыдущем абзаце, тогда

    U = Math.atan2(z, x) / Math.PI * 0.5 - 0.5;
    V = 0.5 - Math.asin(y) / Math.PI;
    
  • Отображение проекции

    Это как в кино. У вас есть 2D-изображение, проецируемое из точки. Представьте, что вы направили кинопроектор (или проекционный телевизор) на стул. Вычислите эти точки

    Вычисление этих точек точно такое же, как вычисление 2D-изображения из 3D-данных, что делают почти все приложения WebGL. Обычно у них есть такая строка в вершинном шейдере

    gl_Position = matrix * position;
    

    Где matrix = worldViewProjection. Затем вы можете сделать

    clipSpace = gl_Position.xy / gl_Position.w
    

    Теперь у вас есть значения x,y от -1 до +1. Затем вы конвертируете их от 0 до 1 для координат UV.

    uv = clipSpace * 0.5 + 0.5;
    

    Конечно, обычно вы вычисляете UV-координаты во время инициализации в JavaScript, но концепция та же.

  • Планарное отображение

    Это почти то же самое, что и проекционное отображение, за исключением того, что проектор не является точкой, а имеет тот же размер, который вы хотите проецировать. Другими словами, при проекционном отображении по мере приближения модели к проектору проецируемое изображение будет уменьшаться, а при планарном — нет.

    Следуя примеру отображения проекции, единственная разница здесь заключается в использовании ортогональной проекции вместо проекции перспективы.

  • Кубическое отображение?

    Это эффективно плоское отображение с 6 направлений. Вам решать, какие UV-координаты получат какую из 6 плоскостей. Я предполагаю, что в большинстве случаев вы берете нормаль треугольника, чтобы увидеть, к какой плоскости он больше всего обращен, а затем выполняете планарное отображение из этой плоскости.

    На самом деле, я, возможно, путаю свои термины. Вы также можете сделать реальное отображение куба, где у вас есть текстура куба, но для этого требуются U, V, W вместо только U, V. Для этого это то же самое, что и пример со сферой, за исключением того, что вы просто используете нормализованные координаты непосредственно как U, V, W.

  • Цилиндрическое отображение

    Это похоже на отображение сферы, за исключением того, что на вашу модель проецируется крошечный цилиндр. В отличие от сферы, цилиндр имеет ориентацию, но в основном вы можете перемещать точки модели в соответствии с ориентацией цилиндра, а затем предположить, что x, y, z теперь относятся к цилиндру (другими словами, вы умножили их на обратную матрицу матрицы который представляет ориентацию цилиндра), затем .

    U = Math.atan2(x, z) / Math.PI * 0.5 + 0.5
    V = y
    

еще 2 решения

  1. Может быть, вы хотите, чтобы Environment Mapping?

    Вот один пример и Вот еще.

  2. Возможно, вам следует подумать об использовании пакета моделирования, такого как Maya или Blender, в котором есть UV-редакторы и Встроенные УФ-проекторы.

person gman    schedule 23.01.2016