Координаты текстуры для программно сгенерированного TriangleMesh в JavaFX

Моя программа читает файл .stl в кодировке ASCII и анализирует его в TriangleMesh, чтобы отобразить его на экране. Он отлично работает, пока мне нужен только один цвет для всей геометрии. Но теперь я хочу иметь возможность назначать разные цвета разным полигонам сетки. Позже мы узнаем, какому лицу нужно будет придать какой цвет, но сейчас достаточно проверки концепции. К сожалению, я не могу заставить его работать. Вот что у меня есть до сих пор:

public static MeshView parseSTLwithColor(String stlString){
    TriangleMesh mesh = new TriangleMesh();

    PhongMaterial textureMaterial = new PhongMaterial();
    Image texture = new Image("http://nikijacob.com/wp-content/uploads/2011/01/Mosaic.jpg");
    textureMaterial.setDiffuseMap(texture);

Просто настройте быструю тестовую текстуру с разными цветами.

    String withoutHeader = stlString.substring(12);
    String[] facetsArray = withoutHeader.split("endfacet");
    for(int h=0;h<facetsArray.length;h++){
        if(facetsArray[h].contains("endloop")){
        facetsArray[h] = facetsArray[h].substring(0,facetsArray[h].indexOf("endloop"));
        }
    }
    for(int i= 0 ; i<facetsArray.length;i++){
        int facetOffset = i*3; 
        String[] verticesArray = facetsArray[i].split("vertex");
        if(verticesArray.length != 4) break;
        for(int j=1;j<4;j++){
            String[] vectorArray = verticesArray[j].split(" ");
            for(int k=1;k<4;k++) mesh.getPoints().addAll(Float.parseFloat(vectorArray[k]));    

Да, не лучший способ сделать это, но это была только первая попытка. По сути, строка данных сетки, закодированных в ASCII, разбивается на грани сетки, затем каждая грань разбивается на 3 точки, затем каждая точка разбивается на 3 вектора, как в 3d. Каждый из них преобразуется в число с плавающей запятой и добавляется в массив точек TriangleMesh.

            mesh.getTexCoords().addAll(1/(100+j),1/(100+j));
        }

Затем я назначаю каждой точке текстурную координату. Я попытался дать каждой точке немного разные координаты, потому что подумал, что это может помочь. (Но этого не произошло.)

        mesh.getFaces().addAll((facetOffset), (facetOffset),(1+facetOffset), (1+facetOffset),(2+facetOffset), (2+facetOffset));  
    }

    MeshView meshView = new MeshView(mesh);
    meshView.setMaterial(textureMaterial);
    return meshView;
}

И немного домашнего хозяйства. Создайте грани из точек и координат текстуры, создайте экземпляр MeshView и дайте ему текстуру, чтобы можно было вернуть текстурированное Meshview.

Теперь проблема проявляется в том, что вместо того, чтобы назначать разные цвета граням, кажется, что вся поверхность 3D-объекта представляет собой смесь всей текстуры. Когда я тестировал текстуру, наполовину красную и наполовину синюю, вся геометрия стала фиолетовой.


person Aljoscha Fernández    schedule 24.02.2014    source источник


Ответы (2)


Э... оказывается, это работает, когда я использую .png, расположенный на моем компьютере, вместо .gif из Интернета.

person Aljoscha Fernández    schedule 25.02.2014

Отвечаю здесь на очень старый вопрос, но сам только что упал в эту кроличью нору.

Короче говоря, обернуть текстуру вокруг файла STL невозможно с помощью внешних программ.

Причина в том, что файл STL не обеспечивает правильного отображения координат текстуры (например, для .getTexCoords()).

Тем не менее, карты нормалей примерно уникальны, поэтому я немного поработал, удалив вектор нормалей из фасета (например, [1]), вычислив количество фасетов и извлекая из этого числа квадратный корень (при условии, что мы заполним квадратное изображение):

int facets = (int)Math.sqrt((lines.size() - 2) / 7);

Где: lines - это String[] длины файла, верхний и нижний колонтитулы STL составляют 2 строки, а для описания каждого аспекта есть 7 строк.

Затем берем вектор нормали и злоупотребляем им:

mesh.getTexCoords().addAll(((Float.parseFloat(n) + 1) / -2));

Где: n — это значение в векторе нормали, а + 1// -2 — это нормализация вектора нормали от -1 -> 0 до 0 -> 1 (допустимый диапазон для .getTexCoords()).

Это хаки, но это немного более работоспособно. Вы можете по крайней мере сделать головы и хвосты текстуры.


Реальным решением здесь является использование объекта (например, значений экспорта vt obj), который фактически выводит UV-отображение из такой программы, как Blender: https://blender.stackexchange.com/a/18428

[1]:

facet normal -0 0 1
  outer loop
    vertex -10 12 9
    vertex 10 0 9
    vertex 10 12 9
  endloop
endfacet
person Dan    schedule 06.05.2018