Программно генерировать простое УФ-картирование для моделей

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

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

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

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

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

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;

}

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 ),
   ]);
}

Счастливый?

Есть бесконечные способы применения УФ-координат. Как насчет этого

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 для этой ситуации

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

    Самый простой способ, я думаю, называется проекция Меркатора, именно так работают большинство двухмерных карт мира. у них проблема в том, что много места теряется на северном и южном полюсах. Предполагая, что 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, но концепция та же.

  • Планарное картографирование

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

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

  • Cube Mapping?

    Это эффективно плоское картирование с 6 направлений. Вам решать, какие координаты УФ получить, какая из 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. Может быть, вы хотите картографирование окружающей среды?

    Вот 1 пример, а вот еще один.

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

Другие вопросы по тегам