Как загрузить 3D-объект в Android?

#android #opengl-es

#Android #opengl-es

Вопрос:

У меня есть файлы .obj и .mtl, но я не знаю, как их импортировать. Я пробовал учебные пособия, они не работают.

Комментарии:

1. Разбейте это на этапы. Не начинайте с попыток повернуть «сложный 3D-объект» — начните с того, что убедитесь, что вы можете импортировать объект, предпочтительно что-то простое, например куб или сферу. Тогда побеспокойтесь о его отображении. Тогда побеспокойтесь о его вращении. И вы можете задавать вопросы о каждом элементе по отдельности, и у вас будет кто-то, кто с гораздо большей вероятностью поможет вам, чем этот вопрос, который требует от нас слишком многого.

2. Это впервые в Android, хммм, и вы сразу переходите к 3D-объектам… ОТЛИЧНО! Я бы предпочел стать ребенком и учиться на таких основах, как просмотры, активность и то, как работают все фундаментальные вещи, но, эй, это я… может быть, вы намного умнее! удачи…

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

Ответ №1:

Один из способов загрузить объект из obj-файла — это сначала получить inputstream из файла, затем вы просматриваете каждую строку, поскольку одна строка состоит из одной вершины. Часть, в которой вы затем используете свои данные из файла .obj, чтобы фактически нарисовать его, — это то, о чем вы легко можете найти множество руководств в Интернете, один пример:http://www.droidnova.com/android-3d-game-tutorial-part-i ,312.html . Если вы хотите глубже разобраться в Opengl и многому научиться, вы можете воспользоваться онлайн-руководством allmightys, которое охватывает очень многое и довольно глубоко проникает в программирование на OpenGL: http://nehe.gamedev.net / .

В любом случае, загрузка файла .obj может начинаться с чего-то вроде этого:

         while ((line = reader.readLine()) != null)
    {
        if (line.startsWith("f"))
        {
            faces  ;
            processFLine(line);
        } else if (line.startsWith("vn"))
        {
            normals  ;
            processVNLine(line);
        } else if (line.startsWith("vt"))
        {
            UVCoords  ;
            processVTLine(line);
        } else if (line.startsWith("v"))
        {
            vertices  ;
            processVLine(line);
        }
    }
  

Для всего, за исключением случаев, когда строка начинается с ‘f’, это довольно просто, вы просто сохраняете два или три значения во что-то, я предпочел вектор:

     private void processVNLine(String line)
{
    String[] tokens = line.split("[ ] ");
    int c = tokens.length;
    for (int i = 1; i < c; i  )
    { // add the normals to the normal vector
        _vn.add(Float.valueOf(tokens[i]));
    }
}
  

Для части граней (где строка начинается с ‘f’, желательно сначала проверить, из скольких ‘/’ состоит каждая вершина:

     private void processFLine(String line)
{
    String[] tokens = line.split("[ ] ");
    int c = tokens.length;

    if (tokens[1].matches("[0-9] "))
    {
        caseFEqOne(tokens, c);
    }
    if (tokens[1].matches("[0-9] /[0-9] "))
    {
        caseFEqTwo(tokens, c);
    }
    if (tokens[1].matches("[0-9] //[0-9] "))
    {
        caseFEqOneAndThree(tokens, c);
    }
    if (tokens[1].matches("[0-9] /[0-9] /[0-9] "))
    {
        caseFEqThree(tokens, c);
    }
}  
  

Каждая грань состоит из трех вершин, где индексы каждой вершины равны v / vt / vn.

Это то, что может произойти, если у вас v / vt. Он хранит индексы в отдельных векторах.

     private void caseFEqTwo(String[] tokens, int c)
{
    for (int i = 1; i < c; i  )
    {
        Short s = Short.valueOf(tokens[i].split("/")[0]);
        s--;
        _vPointer.add(s);

        s = Short.valueOf(tokens[i].split("/")[1]);
        s--;
        _vtPointer.add(s);
    }
}
  

Теперь вы справились с этим, добавив индексы в отдельные векторы или массивы.

Теперь у вас должны быть векторы, состоящие из координат, и вектор, состоящий из индексов для каждого типа (v, vt или vn). У вас также должно быть количество граней. Зная количество граней, теперь вы можете запустить цикл, который переходит от 0 к количеству граней.

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

Возможно, для этого потребуется некоторое объяснение, поэтому вот простой пример:

 private void reArrange()
{
    Iterator<Short> i;
    short s;

    i = _vPointer.iterator();
    while (i.hasNext())
    {
        s = (short) (i.next() * 3);
        for (int k = 0; k < 3; k  )
        {
            _vResult.add(_v.get(s   k));
        }
    }

    i = _vnPointer.iterator();
    while (i.hasNext())
    {
        s = (short) (i.next() * 3);
        for (int k = 0; k < 3; k  )
        {
            _vnResult.add(_vn.get(s   k));
        }
    }

    i = _vtPointer.iterator();
    while (i.hasNext())
    {
        s = (short) (i.next() * 2);
        for (int k = 0; k < 2; k  )
        {
            _vtResult.add(1f - _vt.get(s   k));
        }
    }

    _indices = new short[faces * 3];
    for (short k = 0; k < faces * 3; k  )
    {
        _indices[k] = k;
    }
}
  

Теперь все фактически готово, и у вас есть необходимая информация из файла .obj. Итак, путем преобразования этих векторов в буферы с плавающей запятой и путем создания буфера коротких значений, который так же прост, как 0,1,2,3,4,5 … и так далее, вы можете использовать thoose с OpenGL-ES для рисования своего объекта.

(Это написано не мной полностью, я использовал базовую концепцию, которую нашел где-то в Интернете, но сейчас не могу найти, а затем привел ее в соответствие с тем, что я хотел, и немного скорректировал, чтобы было легче понять)

Чего это не касается, так это той части, где вы также загружаете файл .mtl, который вы часто также получаете при экспорте объекта из программы. Если вы хотите реализовать и это, вы могли бы взглянуть на это:http://people.sc.fsu.edu /~jburkardt/data/mtl/mtl.html

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

Если у вас есть какие-либо вопросы, не стесняйтесь задавать их.

(Я знаю, что это может быть не оптимальный способ загрузки файла .obj, поскольку мы используем до 9 разных векторов, но если вы также используете сериализацию, это может фактически произойти довольно быстро.)

Комментарии:

1. Ссылка недоступна (первая ссылка)

Ответ №2:

OpenGL не является библиотекой графов сцен. Он предоставляет вам набор сложных инструментов для рисования, но не более того. Загрузка 3D-моделей, управление сценой и т.д. — все это остается за вами для реализации или использования библиотеки.

Комментарии:

1. Спасибо. я работаю над импортом объекта, все еще можете ли вы предложить мне какой-либо учебник или пример кода для того же?

2. @Abishek: Прежде чем приступить к загрузке моделей, я предлагаю вам освоить базовые знания OpenGL. Как только вы освоите это, остальное обретет гораздо больше смысла. В противном случае вы бы заблудились между вершинами, массивами индексов и состоянием OpenGL.

Ответ №3:

сейчас уже далеко поздно…но все же полезное решение: движок min3D помогает загрузить 3D-модель в Android

Ниже приведены варианты:

1) Загрузите Rajawali lib.

2) Создайте RenderActivity

частный Объект3dContainer faceObject3D; частный Объект3dContainer objModel;

     @Override 
    public void initScene() {
        scene.lights().add(new Light());
        scene.lights().add(new Light());

        Light myLight = new Light();
        myLight.position.setZ(150);
        scene.lights().add(myLight);

        IParser parser = Parser.createParser(Parser.Type.OBJ,
                getResources(), "com.azoi.opengltutor:raw/monster_high", true);
        parser.parse();

        objModel = parser.getParsedObject();
        objModel.scale().x = objModel.scale().y = objModel.scale().z = .7f;
        scene.addChild(objModel);
    }
  

добавьте obj-файл вашей 3D-модели в каталог res / raw…здесь это monster_high

Вот и все … зарегистрируйте активность в манифесте и запустите 🙂 .

если вы хотите переместить 3D-модель, переопределите updateScene (..):

 public void updateScene() {
    super.updateScene();

    objModel.rotation().x  ;
    objModel.rotation().y--;
    objModel.rotation().z  ;
}
  

подробнее здесь http://code.google.com/p/min3d/wiki/HowToLoadObjFile Наслаждайтесь 🙂

Комментарии:

1. @LunarWatcher, как ты этого добился?