Wavefront OBJ File


Wavefront .obj file

An *.obj file is a file format to store 3D geometry. It is a text file that stores the position of each vertex and the UV position of each texture. The vertices are stored in counter-clockwise order by default.
Un archivo *.obj es un formato de archivo para almacenar geometría de 3D. Este es un archivo de texto que almacena la posición de cada vértice y la position UV de cada textura. Los vértices están almacenados en dirección contraria a las manecillas del reloj por defecto.

Geometric vertices

The example below shows a simple OBJ file. The first example has a list with four vertices. Each vertex begins with the letter v and has three parameters (x, y, z). Each vertex in the second example has four parameters: x, y, z and the weight. If the weight of the vertex is not specified, it is assumed to be 1.
El ejemplo de abajo muestra un archivo OBJ simple. El primer ejemplo tiene una lista con cuatro vértices. Cada vértice comienza con la letra v y tiene tres parámetros (x, y, z). Cada vértice en el segundo ejemplo tiene cuatro parámetros: x, y, z y el peso. Si el peso del vértice no se específica, se asume que uno.

vertex

Texture coordinates

The example below shows a simple OBJ file. The first example has a list with three texture coordinates. Each texture coordinate begins with vt and has two parameters (u, v). Each texture coordinate in the second example has three parameters: u, v and the weight. If the weight of the texture coordinate is not specified, it is assumed to be 1.
El ejemplo de abajo muestra un archivo OBJ simple. El primer ejemplo tiene una lista con tres coordenadas de textura. Cada coordenada de textura comienza con vt y tiene dos parámetros (u, v). Cada coordenada de la textura en el segundo ejemplo tiene tres parámetros: u, v y el peso. Si el peso de la coordenada de la textura no se específica, se asume que es uno.

texture

OBJ format

The figure below shows the structure of an OBJ document.
  1. The document has a set of nodes
  2. Each node has a name, a set of vertexes, a set of normal vectors, a set of vector textures and a set of face groups
  3. Each face group has a usemtl and a set of polygons
  4. Each polygon has three sets of indexes
  • El documento tiene un conjunto de nodos
  • Cada nodo tiene un nombre, un conjunto de vértices, un conjunto de vectores normales, un conjunto de vectores de texturas y un conjunto de face groups
  • Cada grupo de face tiene un usemtl y un conjunto de poligonos
  • Cada polígono tiene tres conjuntos de índices

  • format

    OBJ Example

    The example below shows a simple OBJ file. The file has five parts: vertices, texture, vertex normal, parameter space and face. A polygonal face begins with f and may have a several groups of numbers. Each triple has three numbers: a vertex index, a texture index and a normal index. The first face has three triples: 1/2/3, 2/2/1 and 3/2/3. In the last triple, the first number, 3, is the vertex index; the second number, 2, is the texture index and the last number, 3, is the normal index. When the texture index is not provided, it is possible to denote a triple as 3//2. When both, the texture index and the normal index are not provided, it is possible to denote a triple by only the vertex index.
    El ejemplo de abajo muestra un archivo OBJ sencillo. El archivo tiene cinco partes: vertices, texture, vertex normal, parameter space and face. Un cara poligonal comienza con f y puede tener varios triples. Cada triple tiene tres números: un índice para el vértice, un índice para la textura y un índice para la normal. La primera cara tiene tres triples: 1/2/3, 2/2/1 y 3/2/3. En el último triple, el primer número, 3, es el índice del vértice; el segundo número, 2, es el índice la textura y el último número, 3, es el índice de la normal. Cuando no se proporciona el índice la textura, es posible denotar un triple cómo 3//2. Cuando los dos, el índice de la textura y el índice la normal no se proporcionan, es posible denotar el triple solamente por el índice del vértice.

    example

    Other elements

    The OBJ file also has the following elements:
    1. Line elements, they start with l
    2. Point elements, they start with p
    3. Object name, denoted by o
    4. Polygon group, denoted by g
    5. Smooth shading, denoted by s
    6. Curve, denoted by curv
    7. Surface, denoted by surf

    El archivo OBJ también los siguientes elementos:
    1. Elementos de línea, estos comienzan con l
    2. Elementos de puntos, estos comienzan con p
    3. Nombres de objetos, indicados por una letra o
    4. Grupos de polígonos, indicados por una letra g
    5. Sombreado suave, denotado por una letra s
    6. Curva, denotado por curv
    7. Superficie, denotado por surf

    Tip
    You may download the OBJ specification from http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf
    Usted puede descargar la especificación OBJ desde http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf

    Material Template Library (*.MTL)

    It is an ASCII file format that works together with one or more *.OBJ files. An *.MTL file stores material properties and is typically called a material library. This file includes properties of a surface, such as light reflection.
    Este es un formato ASCII para archivos que trabaja en conjunto con uno o varios archivos as *.OBJ. Un archivo *.MTL almacena propiedades de materiales y es típicamente llamado una librería de materiales. Este archivo incluye propiedades de una superficie, tales como la reflexión de la luz.

    Problem 1
    Cree a dialog application called ObjReader to read an OBJ file and display the vertexes of the faces in the file (note that this is NOT a DirectX application). After creating the project insert textbox called tbxOutput to show the vertexes values. Then, use notepad to create the file shown below, you may download a simple OBJ file from the Internet. If the file is too big, it will be impossible to display all the vertexes in a textbox.
    Cree una aplicación de diálogo llamada ObjReader para leer un archivo OBJ y mostrar los vértices de las caras en el archivo (note que esta NO es una aplicación de DirectX). Después de crear el proyecto inserte una caja de texto llamada tbxOutput para mostrar los valores de los vértices. Entonces, use el block de notas para crear el archivo mostrado debajo, usted puede descargar un archivo OBJ sencillo desde la Internet. Si el archivo es demasiado grande, será imposible mostrar todos los vértices en una caja de texto.

    cube.obj
    # This file uses centimeters as units for non-parametric coordinates.

    mtllib cube.mtl
    g default
    v -0.500000 -0.500000 0.500000
    v 0.500000 -0.500000 0.500000
    v -0.500000 0.500000 0.500000
    v 0.500000 0.500000 0.500000
    v -0.500000 0.500000 -0.500000
    v 0.500000 0.500000 -0.500000
    v -0.500000 -0.500000 -0.500000
    v 0.500000 -0.500000 -0.500000
    vt 0.001992 0.001992
    vt 0.998008 0.001992
    vt 0.001992 0.998008
    vt 0.998008 0.998008
    vt 0.001992 0.001992
    vt 0.998008 0.001992
    vt 0.001992 0.998008
    vt 0.998008 0.998008
    vt 0.001992 0.001992
    vt 0.998008 0.001992
    vt 0.001992 0.998008
    vt 0.998008 0.998008
    vt 0.001992 0.001992
    vt 0.998008 0.001992
    vt 0.001992 0.998008
    vt 0.998008 0.998008
    vt 0.001992 0.001992
    vt 0.998008 0.001992
    vt 0.001992 0.998008
    vt 0.998008 0.998008
    vt 0.998008 0.998008
    vt 0.001992 0.998008
    vt 0.998008 0.001992
    vt 0.001992 0.001992
    vn 0.000000 0.000000 1.000000
    vn 0.000000 0.000000 1.000000
    vn 0.000000 0.000000 1.000000
    vn 0.000000 0.000000 1.000000
    vn 0.000000 1.000000 0.000000
    vn 0.000000 1.000000 0.000000
    vn 0.000000 1.000000 0.000000
    vn 0.000000 1.000000 0.000000
    vn 0.000000 0.000000 -1.000000
    vn 0.000000 0.000000 -1.000000
    vn 0.000000 0.000000 -1.000000
    vn 0.000000 0.000000 -1.000000
    vn 0.000000 -1.000000 0.000000
    vn 0.000000 -1.000000 0.000000
    vn 0.000000 -1.000000 0.000000
    vn 0.000000 -1.000000 0.000000
    vn 1.000000 0.000000 0.000000
    vn 1.000000 0.000000 0.000000
    vn 1.000000 0.000000 0.000000
    vn 1.000000 0.000000 0.000000
    vn -1.000000 0.000000 0.000000
    vn -1.000000 0.000000 0.000000
    vn -1.000000 0.000000 0.000000
    vn -1.000000 0.000000 0.000000
    s 1
    g pCube1
    usemtl file1SG
    f 1/1/1 2/2/2 3/3/3
    f 3/3/3 2/2/2 4/4/4
    s 2
    f 3/13/5 4/14/6 5/15/7
    f 5/15/7 4/14/6 6/16/8
    s 3
    f 5/21/9 6/22/10 7/23/11
    f 7/23/11 6/22/10 8/24/12
    s 4
    f 7/17/13 8/18/14 1/19/15
    f 1/19/15 8/18/14 2/20/16
    s 5
    f 2/5/17 8/6/18 4/7/19
    f 4/7/19 8/6/18 6/8/20
    s 6
    f 7/9/21 1/10/22 5/11/23
    f 5/11/23 1/10/22 3/12/24


    ObjReader.h
    #pragma once //______________________________________ ObjReader.h
    #include "Resource.h"
    class ObjReader: public Win::Dialog
    {
    public:
         ObjReader()
         {
         }
         ~ObjReader()
         {
         }
         void DisplayObject(Sys::ObjDocument& document, Sys::ObjNode& node);
         void DisplayFaceGroup(Sys::ObjFaceGroup& faceGroup, vector<Sys::Point3DF>& v);
    protected:
         . . .
    };


    ObjReader.cpp
    . . .
    void ObjReader::Window_Open(Win::Event& e)
    {
         Sys::ObjDocument document;
         const wchar_t* error = document.Load(L"cube.obj");
         if (error != NULL)
         {
              this->MessageBox(error, L"ObjReader", MB_OK | MB_ICONERROR);
              return;
         }
         const size_t nodeCount = document.o.size();
         for (size_t i = 0; i < nodeCount; i++) DisplayObject(document, document.o[i]);
    }

    void ObjReader::DisplayObject(Sys::ObjDocument& document, Sys::ObjNode& node)
    {
         const size_t faceGroupCount = node.f.size();
         for (size_t i = 0; i < faceGroupCount; i++) DisplayFaceGroup(node.f[i], document.v);
    }

    void ObjReader::DisplayFaceGroup(Sys::ObjFaceGroup& faceGroup, vector<Sys::Point3DF>& v)
    {
         const size_t rowCount = faceGroup.polygon.size();
         size_t colCount;
         wchar_t text[128];
         size_t index, i, j;
         for (i = 0; i < rowCount; i++)
         {
              colCount = faceGroup.polygon[i].size();
              tbxOutput.Text += L"________________________ Face\r\n";
              for (j = 0; j < colCount; j++)
              {
                   index = faceGroup.polygon[i][j].vertexIndex - 1; // C++ indexes begins at zero
                   _snwprintf_s(text, 128, _TRUNCATE, L"%.6f, %.6f, %.6f\r\n", v[index].x, v[index].y, v[index].z);
                   tbxOutput.Text += text;
              }
         }
    }

    ObjReaderRun

    Problem 2
    Create a DirextX application called MyView to display some of the faces in an OBJ file. After creating the project, add a new class called Body. You will need an OBJ file for this exercise.
    Cree una aplicación DirectX llamada MyView para mostrar algunas de las caras de un archivo OBJ. Después de crear el proyecto, agregue una clase nueva llamada Body.

    Step A
    Use notepad to open the OBJ file and see what is inside the file.
    Use el block de notas para abrir el archivo OBJ y vea el contenido del archivo.

    Step B
    Edit the MyView.h file as shown.
    Edite el archivo MyView.h cómo se muestra.

    MyView.h
    #pragma once //______________________________________ MyView.h
    #include "Resource.h"
    #include "Body.h"

    class MyView: public . . .
    {
    public:
         . . .
         //____________________________________________________ 1. Application
         Body body;
         Sys::ObjDocument document;
         . . .
    };

    Step C
    Edit the MyView.cpp file as shown. We will using: D3D11_CULL_NONE, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP and a color vertex buffer (DX11::ColorVertexBuffer). You should use D3D11_CULL_NONE to test your program, once it is working you can switch to D3D11_CULL_BACK. You can also move the camera, if the object is out of view. Remember that some shaders require normal vectors, if your OBJ file does not have normal vectors, you must use a color shader; in this case you cannot use the lighting shaders. Likewise, you should select the required vertex buffer, see table below. Additionally, you must select an appropriate primitive topology. There are many factors than can prevent the OBJ file to be displayed properly. For instance, some files may have the Y axis pointing down, or use clock wise coordinates. All these problems can be solved, once you understand what is happening.
    Edite el archivo MyView.cpp cómo se muestra. Nosotros usaremos: D3D11_CULL_NONE, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP y un buffer de vértices de color (DX11::ColorVertexBuffer). Usted debe usar D3D11_CULL_NONE para probar su programa, una vez que este operando usted puede cambiar a D3D11_CULL_BACK. Uste puede también mover la cámara, si el objecto está fuera de la vista. Recuerde que algunos shaders requieren los vectores normales, si su archivo OBJ no tiene vectores normales, usted debe usar el shader de color; en este caso los shaders de iluminación no se pueden usar. De la misma forma, usted debe seleccionar el tipo de buffers de vértices requerido, vea la tabla de abajo. Adicionalmente, usted debe seleccionar una topología de primitivos apropiada. Hay muchos factores que pueden prevenir que el archivo OBJ se muestre correctamente. Por ejemplo, algunos archivos pueden tener el eje Y apuntando hacia abajo, o usan un sistema de coordenadas en la dirección de las manecillas del reloj. Todos estos problemas pueden resolverse, una vez que se entiende lo que está pasando.

    Vertex Buffer       Normal vector       Lighting       color       texture  
    DX10::ColorVertexBuffer       no       no       required       no
    DX10::ColorNormVertexBuffer       required       yes       required       no
    DX10::TextureVertexBuffer       no       no       no       required
    DX10::TextureNormVertexBuffer       required       yes       no       required

    MyViewRun1

    MyViewRun2

    MyView.cpp
    void MyView::Window_Open(Win::Event& e)
    {
         const wchar_t* error = NULL;
         //________________________________________________________________ 1. Initialize device (D3D10_CULL_NONE, D3D10_CULL_FRONT)
         if (InitDevice(D3D10_CULL_NONE) == false) return this->Destroy();
         . . .
         //________________________________________________________________ 5. Setup the application objects
         error = document.Load(L"cube.obj");
         if (error != NULL) this->MessageBox(error, L"Loading OBJ", MB_OK | MB_ICONERROR);
         body.Set(document);
         if (body.buffer.Create(hWnd, device) == false) return this->Destroy();
    }

    void MyView::RenderScene()
    {
         //________________________________________________ 1. Clear screen and camera update
         Clear(0.0f, 0.0f, 0.2f, 1.0f);
         //________________________________________________ 2. Move the camera with the up and down with the keyboard arrows
         if (keyboard[VK_UP]) camera.position.y += (FLOAT)(1.0*stopWatch.GetSeconds());
         if (keyboard[VK_DOWN]) camera.position.y -= (FLOAT)(1.0*stopWatch.GetSeconds());
         camera.Update();
         //________________________________________________ 2. Application objects
         body.Update(keyboard, stopWatch);
         body.buffer.Render(deviceContext);
         colorShader.Render(deviceContext, body.buffer.GetIndexCount(), body.world, camera);
    }


    Step E
    Edit the files Body.h and Body.cpp as shown.
    Edite los archivos Body.h y Body.cpp cómo se muestra.

    Body.h
    #pragma once

    class Body
    {
    public:
         Body();
         ~Body();
         DX11::ColorVertexBuffer buffer;
         //DX11::ColorNormVertexBuffer buffer;
         //DX11::TextureVertexBuffer buffer;
         //DX11::TextureNormVertexBuffer buffer;
         FLOAT x;
         FLOAT y;
         FLOAT z;
         FLOAT angleY;
         DirectX::XMMATRIX world;
         DirectX::XMMATRIX scale;
         void Set(Sys::ObjDocument& document);
         void Update( bool * keyboard, Sys::Stopwatch& stopWatch);     
    };


    Body.cpp
    #include "stdafx.h"
    #include "Body.h"

    Body::Body()
    {
         //_______________________________________________________________________ 1. Initialize member variables
         world = DirectX::XMMatrixIdentity();
         scale = DirectX::XMMatrixScaling(1.2f, 1.2f, 1.2f);
         x = 0.0f;
         y = 0.0f;
         y = 0.0f;
         angleY = 0.0f;
         angleY = 0.0f;
    }

    Body::~Body()
    {
    }

    void Body::Set(Sys::ObjDocument& document)
    {
         unsigned int i;
         //_________________________________________ 1. Get the first the faceGroup in the first node
         const int nodeIndex = 0;
         const int faceGroupIndex = 0;
         const unsigned int indexCount = document.GetIndexArrayCount(nodeIndex, faceGroupIndex);
         const unsigned int vertexCount = document.GetVertexCount(nodeIndex, faceGroupIndex);
         if (buffer.Setup(indexCount, vertexCount, D3D11_USAGE_DEFAULT, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP) == false) return;
         //_________________________________________ 2. Process the vertexes (perform transformations, if necessary)
         vector<Sys::Vertex> v;
         document.GetVertexArray(nodeIndex, faceGroupIndex, v);
         for (i = 0; i < vertexCount; i++)
         {
              buffer.vertex[i].position.x = v[i].position.x;
              buffer.vertex[i].position.y = v[i].position.y;
              buffer.vertex[i].position.z = v[i].position.z;
              buffer.vertex[i].color = DirectX::XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f); // Red
              if (v[i].normal.IsNull() == false)
              {
                   //buffer.vertex[i].normal.x = v[i].normal.x;
                   //buffer.vertex[i].normal.y = v[i].normal.y;
                   //buffer.vertex[i].normal.z = v[i].normal.z;
              }
         }
         //_________________________________________ 3. Process the vertex indexes
         vector<unsigned int> index;
         document.GetIndexArray(nodeIndex, faceGroupIndex, index);
         for (i = 0; i < indexCount; i++)
         {
              buffer.index[i] = index[i];
         }
    }

    void Body::Update(bool * keyboard, Sys::Stopwatch& stopWatch)
    {
         const FLOAT delta = (FLOAT)stopWatch.GetSeconds();
         //________________________________________________________ 1. Rotate, translate and scale
         angleY += (0.5f*delta);
         world = DirectX::XMMatrixRotationY(angleY);
         DirectX::XMMATRIX translation = DirectX::XMMatrixTranslation(x, y, z);
         world = DirectX::XMMatrixMultiply(world, translation);
         world = DirectX::XMMatrixMultiply(scale, world);
         if (angleY > DirectX::XM_2PI) angleY -= DirectX::XM_2PI;
    }


    Problem 3
    Incorporate lighting to program of the previous problem. You will need an OBJ file with normal vectors.
    Incorpore iluminación al programa del problema previo. Usted necesitará un archivo OBJ con vectores normales.

    MyViewRunLigth1

    MyViewRunLigth2

    Step A
    Edit the files Body.h and Body.cpp as shown. We will use an color vertex buffer with normal vectors (DX11::ColorNormVertexBuffer).
    Edite los archivos Body.h y Body.cpp cómo se muestra. Usaremos un buffer de vértices de color con vectores normales (DX11::ColorNormVertexBuffer).

    Body.h
    #pragma once

    class Body
    {
    public:
         Body();
         ~Body();
         //DX11::ColorVertexBuffer buffer;
         DX11::ColorNormVertexBuffer buffer;
         //DX11::TextureVertexBuffer buffer;
         //DX11::TextureNormVertexBuffer buffer;
         FLOAT x;
         FLOAT y;
         FLOAT z;
         FLOAT angleY;
         DirectX::XMMATRIX world;
         DirectX::XMMATRIX scale;
         void Set(Sys::ObjDocument& document);
         void Update( bool * keyboard, Sys::Stopwatch& stopWatch);     
    };
    CODE Body.cpp
    . . .
    void Body::Set(Sys::ObjDocument& document)
    {
         . . .
         for (i = 0; i < vertexCount; i++)
         {
              buffer.vertex[i].position.x = v[i].position.x;
              buffer.vertex[i].position.y = v[i].position.y;
              buffer.vertex[i].position.z = v[i].position.z;
              buffer.vertex[i].color = DirectX::XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f); // Red
              if (v[i].normal.IsNull() == false)
              {
                   buffer.vertex[i].normal.x = v[i].normal.x;
                   buffer.vertex[i].normal.y = v[i].normal.y;
                   buffer.vertex[i].normal.z = v[i].normal.z;
              }
         }
         //_________________________________________ 3. Process the vertex indexes
         . . .
    }


    Step B
    Edit the files MyView.cpp as shown. We will use a shader color with ambient lighting.
    Edite los archivos MyView.cpp cómo se muestra. Usaremos un shader de color con luz ambiental.

    MyView.cpp
    . . .
    void MyView::RenderScene()
    {
         . . .
         //________________________________________________ 2. Application objects
         body.Update(keyboard, stopWatch);
         body.buffer.Render(deviceContext);
         colorALShader.Render(deviceContext, body.buffer.GetIndexCount(), body.world, camera, light);
    }


    Triangle Tessellation

    As the triangle is the simplest surface in 3D, a triangle strip can be used to create more complex surfaces. The figure below show how to create a quadrilateral, a pentagon, a hexagon, and the general case for any polygon (or a circle). The process of creating 3D surfaces using triangles is called triangle tesellation.
    Como el triángulo es la superficie más simple en 3D, una banda de triángulos puede usarse para crear superficies más complejas. La figura de abajo muestra cómo crear un cuadrilátero, un pentágono, un hexágono, y en forma general para cualquier polígono (y un círculo). El proceso de crear superficies en 3D usando triángulos es llamado teselación triangular.

    tessellation

    Problem 4
    Create a DirectX program called Surface to draw a pentagon and a circle. After creating the project, add a new class called PolygonX to draw the pentagon and the circle. Both shapes must turn around the Y axis.
    Cree un programa de DirectX llamado Surface para dibujar un pentágono y un círculo. Después de crear el proyecto, agregue una nueva clase llamada PolygonX para dibujar el pentágono y el círculo. Ambas figuras deben girar alrededor del eje Y.

    SurfaceRun1

    SurfaceRun2

    Problem 5
    Create a DirectX program called DisplayX to draw the content of an OBJ file After creating the project, add a new class called ObjectData to draw the faces in the OBJ file. The objects in the file must turn around Y axis.
    Cree un programa de DirectX llamado DisplayX para dibujar el contenido de un archivo OBJ. Después de crear el proyecto, agregue una nueva clase llamada ObjectData para dibujar las caras en el archivo OBJ. Los objetos en el archivo deben girar alrededor del eje Y.

    DisplayXRun1

    DisplayXRun2

    Step A
    Edit the DisplayX.h file as shown.
    Edite el archivo DisplayX.h cómo se muestra.

    DisplayX.h
    #pragma once //______________________________________ DisplayX.h
    #include "Resource.h"
    #include "ObjectData.h"

    class DisplayX: public . . .
    {
    public:
         . . .
         //____________________________________________________ 1. Application
         ObjectData objData;
         . . .
    };

    Step B
    Edit the DisplayX.cpp file as shown.
    Edite el archivo DisplayX.cpp cómo se muestra.

    DisplayX.cpp
    void DisplayX::Window_Open(Win::Event& e)
    {
         . . .
         //________________________________________________________________ 4. Setup the camera
         camera.position.x = 0.0f;
         camera.position.y = 10.0f;
         camera.position.z = -50.0f;
         //
         camera.lookAt.x = 0.0f;
         camera.lookAt.y = 0.0f;
         camera.lookAt.z = 1.0f;
         //
         camera.SetViewSize(modeDesc.Width, modeDesc.Height);
         //________________________________________________________________ 5. Setup the application objects
         if (objData.Open(hWnd, L"cottage.obj") == false) return this->Destroy();
         if (objData.Create(hWnd, device) == false) return this->Destroy();
    }

    void DisplayX::RenderScene()
    {
         . . .
         //________________________________________________ 2. Application objects
         objData.Update(keyboard, stopWatch);
         const size_t count = objData.buffer.size();
         for (size_t i = 0; i < count; i++)
         {
              objData.buffer[i].Render(deviceContext);
              colorALShader.Render(deviceContext, objData.buffer[i].GetIndexCount(), objData.world, camera, light);
         }
    }


    Step C
    Edit the files ObjectData.h and ObjectData.cpp as shown.
    Edite los archivos ObjectData.h y ObjectData.cpp cómo se muestra.

    ObjectData.h
    #pragma once

    class ObjectData
    {
    public:
         ObjectData();
         ~ObjectData();
         //vector<DX11::ColorVertexBuffer> buffer;
         vector<DX11::ColorNormVertexBuffer> buffer;
         FLOAT x;
         FLOAT y;
         FLOAT z;
         FLOAT angleY;
         DirectX::XMMATRIX world;
         DirectX::XMMATRIX scale;
         bool Open(HWND hWnd, const wchar_t* filename);
         bool Create(HWND hWnd, ID3D11Device* device);
         void Update( bool * keyboard, Sys::Stopwatch& stopWatch);     
    };


    ObjectData.cpp
    #include "stdafx.h"
    #include "ObjectData.h"

    ObjectData::ObjectData()
    {
         //_______________________________________________________________________ 1. Initialize member variables
         world = DirectX::XMMatrixIdentity();
         scale = DirectX::XMMatrixScaling(1.2f, 1.2f, 1.2f);
         x = 0.0f;
         y = 0.0f;
         y = 0.0f;
         angleY = 0.0f;
         angleY = 0.0f;
    }

    ObjectData::~ObjectData()
    {
    }

    bool ObjectData::Open(HWND hWnd, const wchar_t* filename)
    {
         buffer.clear();
         //_________________________________________ 1. Get the first the faceGroup in the first node
         Sys::ObjDocument document;
         const wchar_t* error = document.Load(filename);
         if (error != NULL)
         {
              ::MessageBox(hWnd, error, L"File", MB_OK | MB_ICONERROR);
              return false;
         }
         //_________________________________________ 3. Memory allocation
         const unsigned int bufferCount = document.GetFaceGroupCount();
         buffer.resize(bufferCount);
         //_________________________________________ 2. For each nodeIndex and each faceGroupIndex
         unsigned int nodeCount = (unsigned int)document.o.size();
         unsigned int nodeIndex = 0;
         unsigned int faceGroupIndex = 0;
         unsigned int faceGroupCount = 0;
         unsigned int bufferIndex = 0;
         unsigned int indexCount = 0;
         unsigned int vertexCount = 0;
         vector<Sys::Vertex> v;
         vector<unsigned int> index;
         unsigned int i;
         for (nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
         {
              faceGroupCount = (unsigned int)document.o[nodeIndex].f.size();
              for (faceGroupIndex = 0; faceGroupIndex < faceGroupCount; faceGroupIndex++, bufferIndex++)
              {
                   //_________________________________________ 3. Create a buffer
                   indexCount = document.GetIndexArrayCount(nodeIndex, faceGroupIndex);
                   vertexCount = document.GetVertexCount(nodeIndex, faceGroupIndex);
                   if (buffer[bufferIndex].Setup(indexCount, vertexCount, D3D11_USAGE_DEFAULT, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP) == false) return false;
                   //________________________________________ 4. Process the vertexes
                   document.GetVertexArray(nodeIndex, faceGroupIndex, v);
                   if ((unsigned int)v.size() == vertexCount)
                   {
                        for (i = 0; i < vertexCount; i++)
                        {
                             buffer[bufferIndex].vertex[i].position.x = v[i].position.x;
                             buffer[bufferIndex].vertex[i].position.y = v[i].position.y;
                             buffer[bufferIndex].vertex[i].position.z = v[i].position.z;
                             buffer[bufferIndex].vertex[i].color = DirectX::XMFLOAT4(0.8f, 0.8f, 1.0f, 1.0f); // Light blue
                             buffer[bufferIndex].vertex[i].normal.x = v[i].normal.x;
                             buffer[bufferIndex].vertex[i].normal.y = v[i].normal.y;
                             buffer[bufferIndex].vertex[i].normal.z = v[i].normal.z;
                        }
                   }
                   //_________________________________________ 5. Process the vertex indexes          
                   document.GetIndexArray(nodeIndex, faceGroupIndex, index);
                   for (i = 0; i < indexCount; i++)
                   {
                        buffer[bufferIndex].index[i] = index[i];
                   }
              }
         }
         return true;
    }

    bool ObjectData::Create(HWND hWnd, ID3D11Device* device)
    {
         const size_t count = buffer.size();
         for (size_t i = 0; i < count; i++)
         {
              if (buffer[i].Create(hWnd, device) == false) return false;
         }
         return true;
    }

    void ObjectData::Update(bool * keyboard, Sys::Stopwatch& stopWatch)
    {
         const FLOAT delta = (FLOAT)stopWatch.GetSeconds();
         //________________________________________________________ 1. Rotate, translate and scale
         angleY += (0.5f*delta);
         world = DirectX::XMMatrixRotationY(angleY);
         DirectX::XMMATRIX translation = DirectX::XMMatrixTranslation(x, y, z);
         world = DirectX::XMMatrixMultiply(world, translation);
         world = DirectX::XMMatrixMultiply(scale, world);
         if (angleY > DirectX::XM_2PI) angleY -= DirectX::XM_2PI;
    }

    © Copyright 2000-2019 Wintempla selo. All Rights Reserved. Sep 05 2019. Home