void ModelLoader::CreateIndexBuffer() {
	aiMesh* mesh = scene->mMeshes[0];
	aiMesh* otherMesh = scene->mMeshes[1];
	UINT count = mesh->mNumFaces;
	const aiFace* faces = mesh->mFaces;
	indexCount = mesh->mNumFaces*3;
	std::vector<USHORT> indexData( indexCount );
	for( UINT faceIndex = 0, dataIndex = 0; faceIndex<count; ++faceIndex, dataIndex += 3 ) {
		assert( faces[faceIndex].mNumIndices==3 ); //mesh should be triangulated
		indexData[dataIndex] = (USHORT)faces[faceIndex].mIndices[0];
		indexData[dataIndex+1] = (USHORT)faces[faceIndex].mIndices[1];
		indexData[dataIndex+2] = (USHORT)faces[faceIndex].mIndices[2];
	}

	D3D11_BUFFER_DESC ibd;
	ibd.Usage = D3D11_USAGE_IMMUTABLE;
	ibd.ByteWidth = sizeof( USHORT ) * indexData.size();
	ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
	ibd.CPUAccessFlags = 0;
	ibd.MiscFlags = 0;
	ibd.StructureByteStride = 0;

	D3D11_SUBRESOURCE_DATA initData;
	initData.pSysMem = indexData.data();
	HR( device->CreateBuffer( &ibd, &initData, &ib ) );
}
Exemplo n.º 2
0
Mesh* CreateSolidPlane(float xSize, float zSize, int xSegments, int zSegments, const glm::mat4& transform)
{
    int numVertices = (xSegments + 1) * (zSegments + 1);

    std::vector<VertexPositionNormal> vertexData(numVertices);

    float xStep = xSize / xSegments;
    float zStep = zSize / zSegments;

    VertexPositionNormal* vertexPtr = &vertexData[0];

    float z = -0.5f * zSize;
    for (int j = 0; j <= zSegments; j++) {
        float x = -0.5f * xSize;
        for (int i = 0; i <= xSegments; i++) {
            vertexPtr->pos.x = x;
            vertexPtr->pos.y = 0;
            vertexPtr->pos.z = z;
            vertexPtr->normal.x = 0;
            vertexPtr->normal.y = 1;
            vertexPtr->normal.z = 0;
            ++vertexPtr;
            x += xStep;
        }
        z += zStep;
    }

    int numTriangles = 2 * xSegments * zSegments;

    int numElements = 3 * numTriangles;
    std::vector<unsigned> indexData(numElements);   // use 32-bit indices for large planes!!!11!!!

    unsigned* indexPtr = &indexData[0];
    unsigned e = 0;
    for (int j = 0; j < zSegments; j++) {
        for (int i = 0; i < xSegments; i++) {
            // the four corners of this "square"
            unsigned e = (xSegments + 1) * j + i;
            unsigned e1 = e;
            unsigned e2 = e + 1;
            unsigned e3 = e + xSegments + 1;
            unsigned e4 = e + xSegments + 2;
            // triangle 1
            *indexPtr++ = e1;
            *indexPtr++ = e3;
            *indexPtr++ = e4;
            // triangle 2
            *indexPtr++ = e1;
            *indexPtr++ = e4;
            *indexPtr++ = e2;
            ++e;
        }
        ++e;
    }

    return CreateMesh(GL_TRIANGLES, vertexData, indexData);
}
Exemplo n.º 3
0
void Quads::uploadIndices() const
{
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
    glBufferData(
        GL_ELEMENT_ARRAY_BUFFER,
        indexDataByteCount(),
        indexData(),
        GL_STATIC_DRAW);
}
Exemplo n.º 4
0
Quad::Quad(RenderDevice* renderDevice)
	: Mesh(renderDevice)
{
	VertexFloat verticeArray[] = {
        VertexFloat(-1.0f, 1.0f, 0.0f, 0.0, 0.0, 1.0, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f),
        VertexFloat(-1.0f, -1.0f, 0.0f, 0.0, 0.0, 1.0, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
        VertexFloat(1.0f, -1.0f, 0.0f, 0.0, 0.0, 1.0, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f),
        VertexFloat(1.0f, 1.0f, 0.0f, 0.0, 0.0, 1.0, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f)
	};
	std::vector<VertexFloat> vertexData(verticeArray, verticeArray + sizeof(verticeArray) / sizeof(verticeArray[0]));
    
    unsigned int indexArray[] = {
        0, 1, 2,
        0, 2, 3,
    };
    std::vector<unsigned int> indexData(indexArray, indexArray + sizeof(indexArray) / sizeof(indexArray[0]));
    
    m_Buffer->setVertices(vertexData.size(), &vertexData[0]);
    m_Buffer->setIndices(indexData.size(), &indexData[0]);
}
int main()
{
    int width = 640;
    int height = 480;
    
    if(glfwInit() == GL_FALSE)
    {
        std::cerr << "failed to init GLFW" << std::endl;
        return 1;
    }

    // select opengl version 
    glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
 
    // create a window
    if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE)
    {
        std::cerr << "failed to open window" << std::endl;
        glfwTerminate();
        return 1;
    }
    
    // setup windows close callback
    glfwSetWindowCloseCallback(closedWindow);
    
    // this time we disable the mouse cursor since we want differential
    // mouse input
    glfwDisable(GLFW_MOUSE_CURSOR);
    
    
    
    if (gl3wInit())
    {
        std::cerr << "failed to init GL3W" << std::endl;
        glfwCloseWindow();
        glfwTerminate();
        return 1;
    }

    // draw shader
    std::string vertex_source =
        "#version 330\n"
        "uniform mat4 ViewProjection;\n"
        "layout(location = 0) in vec4 vposition;\n"
        "layout(location = 1) in vec3 normal;\n"
        "out vec4 fcolor;\n"
        "void main() {\n"
        "   float brightness = dot(normal,normalize(vec3(1,2,3)));\n"
        "   brightness = 0.3+((brightness>0)?0.7*brightness:0.3*brightness);\n"
        "   fcolor = vec4(brightness,brightness,brightness,1);\n"
        "   gl_Position = ViewProjection*vposition;\n"
        "}\n";
        
    std::string fragment_source =
        "#version 330\n"
        "in vec4 fcolor;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   FragColor = abs(fcolor);\n"
        "}\n";
    
    // program and shader handles
    GLuint shader_program, vertex_shader, fragment_shader;
    
    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);   
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
        return 1;
    }
    
    // create program
    shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);
    
    // link the program and check for errors
    glLinkProgram(shader_program);
    check_program_link_status(shader_program);
    
    // obtain location of projection uniform
    GLint DrawViewProjection_location = glGetUniformLocation(shader_program, "ViewProjection");
 

    // trivial shader for occlusion queries
    std::string query_vertex_source =
        "#version 330\n"
        "uniform mat4 ViewProjection;\n"
        "layout(location = 0) in vec4 vposition;\n"
        "void main() {\n"
        "   gl_Position = ViewProjection*vposition;\n"
        "}\n";
        
    std::string query_fragment_source =
        "#version 330\n"
        "void main() {\n"
        "}\n";
    
    // program and shader handles
    GLuint query_shader_program, query_vertex_shader, query_fragment_shader;

    // create and compiler vertex shader
    query_vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = query_vertex_source.c_str();
    length = query_vertex_source.size();
    glShaderSource(query_vertex_shader, 1, &source, &length); 
    glCompileShader(query_vertex_shader);
    if(!check_shader_compile_status(query_vertex_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    query_fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = query_fragment_source.c_str();
    length = query_fragment_source.size();
    glShaderSource(query_fragment_shader, 1, &source, &length);   
    glCompileShader(query_fragment_shader);
    if(!check_shader_compile_status(query_fragment_shader))
    {
        return 1;
    }
    
    // create program
    query_shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(query_shader_program, query_vertex_shader);
    glAttachShader(query_shader_program, query_fragment_shader);
    
    // link the program and check for errors
    glLinkProgram(query_shader_program);
    check_program_link_status(query_shader_program);
    
    // obtain location of projection uniform
    GLint QueryViewProjection_location = glGetUniformLocation(query_shader_program, "ViewProjection");


    // chunk container and chunk parameters
    std::vector<Chunk> chunks;
    int chunkrange = 4;
    int chunksize = 32;
    
    // chunk extraction
    std::cout << "generating chunks, this may take a while." << std::endl;
    
    // iterate over all chunks we want to extract        
    for(int i = -chunkrange;i<chunkrange;++i)
        for(int j = -chunkrange;j<chunkrange;++j)
            for(int k = -chunkrange;k<chunkrange;++k)
    {
        
        Chunk chunk;
        
        // chunk data
        
        // generate and bind the vao
        glGenVertexArrays(1, &chunk.vao);
        glBindVertexArray(chunk.vao);
        
        // generate and bind the vertex buffer object
        glGenBuffers(1, &chunk.vbo);
        glBindBuffer(GL_ARRAY_BUFFER, chunk.vbo);
        
        std::vector<glm::vec3> vertexData;
        glm::vec3 offset = static_cast<float>(chunksize) * glm::vec3(i,j,k);
        float threshold = 0.0f;
        // iterate over all blocks within the chunk
        for(int x = 0;x<chunksize;++x)
            for(int y = 0;y<chunksize;++y)
                for(int z = 0;z<chunksize;++z)
                {
                    glm::vec3 pos = glm::vec3(x,y,z) + offset;
                    // insert quads if current block is solid and neighbors are not
                    if(world_function(pos)<threshold)
                    {
                        if(world_function(pos+glm::vec3(1,0,0))>=threshold)
                        {
                            vertexData.push_back(pos+0.5f*glm::vec3( 1, 1, 1));
                            vertexData.push_back(glm::vec3( 1, 0, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3( 1,-1, 1));
                            vertexData.push_back(glm::vec3( 1, 0, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3( 1, 1,-1));
                            vertexData.push_back(glm::vec3( 1, 0, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3( 1,-1,-1));
                            vertexData.push_back(glm::vec3( 1, 0, 0));
                        }
                        if(world_function(pos+glm::vec3(0,1,0))>=threshold)
                        {
                            vertexData.push_back(pos+0.5f*glm::vec3( 1, 1, 1));
                            vertexData.push_back(glm::vec3( 0, 1, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3( 1, 1,-1));
                            vertexData.push_back(glm::vec3( 0, 1, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1, 1, 1));
                            vertexData.push_back(glm::vec3( 0, 1, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1, 1,-1));
                            vertexData.push_back(glm::vec3( 0, 1, 0));
                        }
                        if(world_function(pos+glm::vec3(0,0,1))>=threshold)
                        {
                            vertexData.push_back(pos+0.5f*glm::vec3( 1, 1, 1));
                            vertexData.push_back(glm::vec3( 0, 0, 1));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1, 1, 1));
                            vertexData.push_back(glm::vec3( 0, 0, 1));
                            vertexData.push_back(pos+0.5f*glm::vec3( 1,-1, 1));
                            vertexData.push_back(glm::vec3( 0, 0, 1));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1,-1, 1));
                            vertexData.push_back(glm::vec3( 0, 0, 1));
                        }
                        if(world_function(pos-glm::vec3(1,0,0))>=threshold)
                        {
                            vertexData.push_back(pos+0.5f*glm::vec3(-1, 1, 1));
                            vertexData.push_back(glm::vec3(-1, 0, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1, 1,-1));
                            vertexData.push_back(glm::vec3(-1, 0, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1,-1, 1));
                            vertexData.push_back(glm::vec3(-1, 0, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1,-1,-1));
                            vertexData.push_back(glm::vec3(-1, 0, 0));
                        }
                        if(world_function(pos-glm::vec3(0,1,0))>=threshold)
                        {
                            vertexData.push_back(pos+0.5f*glm::vec3( 1,-1, 1));
                            vertexData.push_back(glm::vec3( 0,-1, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1,-1, 1));
                            vertexData.push_back(glm::vec3( 0,-1, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3( 1,-1,-1));
                            vertexData.push_back(glm::vec3( 0,-1, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1,-1,-1));
                            vertexData.push_back(glm::vec3( 0,-1, 0));
                        }
                        if(world_function(pos-glm::vec3(0,0,1))>=threshold)
                        {
                            vertexData.push_back(pos+0.5f*glm::vec3( 1, 1,-1));
                            vertexData.push_back(glm::vec3( 0, 0,-1));
                            vertexData.push_back(pos+0.5f*glm::vec3( 1,-1,-1));
                            vertexData.push_back(glm::vec3( 0, 0,-1));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1, 1,-1));
                            vertexData.push_back(glm::vec3( 0, 0,-1));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1,-1,-1));
                            vertexData.push_back(glm::vec3( 0, 0,-1));
                        }
                    }
                }
        // upload
        glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*vertexData.size(), &vertexData[0], GL_STATIC_DRAW);
                        
               
        // set up generic attrib pointers
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
     
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));
        
        
        // generate and bind the index buffer object
        glGenBuffers(1, &chunk.ibo);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, chunk.ibo);
        
        chunk.quadcount = vertexData.size()/8;
        std::vector<GLuint> indexData(6*chunk.quadcount);
        for(int i = 0;i<chunk.quadcount;++i)
        {
            indexData[6*i + 0] = 4*i + 0;
            indexData[6*i + 1] = 4*i + 1;
            indexData[6*i + 2] = 4*i + 2;
            indexData[6*i + 3] = 4*i + 2;
            indexData[6*i + 4] = 4*i + 1;
            indexData[6*i + 5] = 4*i + 3;
        }
        
        // upload
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*indexData.size(), &indexData[0], GL_STATIC_DRAW);


        // chunk bounding box

        // generate and bind the vao
        glGenVertexArrays(1, &chunk.bounding_vao);
        glBindVertexArray(chunk.bounding_vao);
        
        // generate and bind the vertex buffer object
        glGenBuffers(1, &chunk.bounding_vbo);
        glBindBuffer(GL_ARRAY_BUFFER, chunk.bounding_vbo);
                
        // data for the bounding cube
        GLfloat boundingVertexData[] = {
        //  X                           Y                           Z 
        // face 0:
            offset.x+chunksize-0.5f,    offset.y+chunksize-0.5f,    offset.z+chunksize-0.5f,
            offset.x-0.5f,              offset.y+chunksize-0.5f,    offset.z+chunksize-0.5f,
            offset.x+chunksize-0.5f,    offset.y-0.5f,              offset.z+chunksize-0.5f,
            offset.x-0.5f,              offset.y-0.5f,              offset.z+chunksize-0.5f,

        // face 1:
            offset.x+chunksize-0.5f,    offset.y+chunksize-0.5f,    offset.z+chunksize-0.5f,
            offset.x+chunksize-0.5f,    offset.y-0.5f,              offset.z+chunksize-0.5f,
            offset.x+chunksize-0.5f,    offset.y+chunksize-0.5f,    offset.z-0.5f,
            offset.x+chunksize-0.5f,    offset.y-0.5f,              offset.z-0.5f,

        // face 2:
            offset.x+chunksize-0.5f,    offset.y+chunksize-0.5f,    offset.z+chunksize-0.5f,
            offset.x+chunksize-0.5f,    offset.y+chunksize-0.5f,    offset.z-0.5f,
            offset.x-0.5f,              offset.y+chunksize-0.5f,    offset.z+chunksize-0.5f,
            offset.x-0.5f,              offset.y+chunksize-0.5f,    offset.z-0.5f,
          
        // face 3:
            offset.x+chunksize-0.5f,    offset.y+chunksize-0.5f,    offset.z-0.5f,
            offset.x+chunksize-0.5f,    offset.y-0.5f,              offset.z-0.5f,
            offset.x-0.5f,              offset.y+chunksize-0.5f,    offset.z-0.5f,
            offset.x-0.5f,              offset.y-0.5f,              offset.z-0.5f,

        // face 4:
            offset.x-0.5f,              offset.y+chunksize-0.5f,    offset.z+chunksize-0.5f,
            offset.x-0.5f,              offset.y+chunksize-0.5f,    offset.z-0.5f,
            offset.x-0.5f,              offset.y-0.5f,              offset.z+chunksize-0.5f,
            offset.x-0.5f,              offset.y-0.5f,              offset.z-0.5f,

        // face 5:
            offset.x+chunksize-0.5f,    offset.y-0.5f,              offset.z+chunksize-0.5f,
            offset.x-0.5f,              offset.y-0.5f,              offset.z+chunksize-0.5f,
            offset.x+chunksize-0.5f,    offset.y-0.5f,              offset.z-0.5f,
            offset.x-0.5f,              offset.y-0.5f,              offset.z-0.5f,
        }; // 6 faces with 4 vertices with 6 components (floats)

        // fill with data
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*3, boundingVertexData, GL_STATIC_DRAW);
                        
               
        // set up generic attrib pointers
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
        
        // generate and bind the index buffer object
        glGenBuffers(1, &chunk.bounding_ibo);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, chunk.bounding_ibo);
                
        GLuint boundingIndexData[] = {
             0, 1, 2, 2, 1, 3, 4, 5, 6, 6, 5, 7, 8, 9,10,10, 9,11,
            12,13,14,14,13,15,16,17,18,18,17,19,20,21,22,22,21,23,
        };

        // fill with data
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, boundingIndexData, GL_STATIC_DRAW);
        
        // generate the query object for the occlusion query
        glGenQueries(1, &chunk.query);
        
        // set the center location of the chunk
        chunk.center = offset + 0.5f*chunksize;
        
        // add to container
        chunks.push_back(chunk);
    }
    
    // "unbind" vao
    glBindVertexArray(0);

    // timer query setup
    // use multiple queries to avoid stalling on getting the results
    const int querycount = 5;
    GLuint queries[querycount];
    int current_query = 0;
    glGenQueries(querycount, queries);
    
    // we are drawing 3d objects so we want depth testing
    glEnable(GL_DEPTH_TEST);

    // camera position and orientation
    glm::vec3 position;
    glm::mat4 rotation = glm::mat4(1.0f);
    
    running = true;
    float t = glfwGetTime();
    bool occlusion_cull = true;
    bool space_down = false;
    
    // mouse position
    int mousex, mousey;
    glfwGetMousePos(&mousex, &mousey);
    while(running)
    {   
        // calculate timestep
        float new_t = glfwGetTime();
        float dt = new_t - t;
        t = new_t;

        // update mouse differential
        int tmpx, tmpy;
        glfwGetMousePos(&tmpx, &tmpy);
        glm::vec2 mousediff(tmpx-mousex, tmpy-mousey);
        mousex = tmpx;
        mousey = tmpy;
        
        // find up, forward and right vector
        glm::mat3 rotation3(rotation);
        glm::vec3 up = glm::transpose(rotation3)*glm::vec3(0.0f, 1.0f, 0.0f);
        glm::vec3 right = glm::transpose(rotation3)*glm::vec3(1.0f, 0.0f, 0.0f);
        glm::vec3 forward = glm::transpose(rotation3)*glm::vec3(0.0f, 0.0f,-1.0f);
        
        // apply mouse rotation
        rotation = glm::rotate(rotation,  0.2f*mousediff.x, up);
        rotation = glm::rotate(rotation,  0.2f*mousediff.y, right);
        
        // roll
        if(glfwGetKey('Q'))
        {
            rotation = glm::rotate(rotation, 180.0f*dt, forward); 
        }  
        if(glfwGetKey('E'))
        {
            rotation = glm::rotate(rotation,-180.0f*dt, forward); 
        }
        
        // movement
        if(glfwGetKey('W'))
        {
            position += 10.0f*dt*forward; 
        }  
        if(glfwGetKey('S'))
        {
            position -= 10.0f*dt*forward;
        }
        if(glfwGetKey('D'))
        {
            position += 10.0f*dt*right; 
        }  
        if(glfwGetKey('A'))
        {
            position -= 10.0f*dt*right;
        }
        
        // toggle occlusion culling
        if(glfwGetKey(GLFW_KEY_SPACE) && !space_down)
        {
            occlusion_cull = !occlusion_cull;
        }
        space_down = glfwGetKey(GLFW_KEY_SPACE);
        
        // terminate on escape 
        if(glfwGetKey(GLFW_KEY_ESC))
        {
            running = false;
        }
        
        
        // calculate ViewProjection matrix
        glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 200.f);
        glm::mat4 View = rotation*glm::translate(glm::mat4(1.0f), -position);
        glm::mat4 ViewProjection = Projection*View;


        // set matrices for both shaders
        glUseProgram(query_shader_program);
        glUniformMatrix4fv(QueryViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection)); 
        glUseProgram(shader_program);
        glUniformMatrix4fv(DrawViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection));
        
        // set clear color to sky blue
        glClearColor(0.5f,0.8f,1.0f,1.0f);
        
        // clear
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // sort chunks by distance
        std::sort(chunks.begin(), chunks.end(), DistancePred(position));
        
        size_t i = 0;
        float maxdist = chunksize;

        // start timer query
        glBeginQuery(GL_TIME_ELAPSED, queries[current_query]);
        
        // peel chunks
        while(i!=chunks.size())
        {
            size_t j = i;
            if(occlusion_cull)
            {
                // start occlusion queries and render for the current slice
                glDisable(GL_CULL_FACE);
                
                // we don't want the queries to actually render something
                glDepthMask(GL_FALSE);
                glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
                glUseProgram(query_shader_program);
                for(;j<chunks.size() && glm::distance(chunks[j].center, position)<maxdist;++j)
                {
                    // frustum culling
                    glm::vec4 projected = ViewProjection*glm::vec4(chunks[j].center,1);
                    if( (glm::distance(chunks[j].center,position) > chunksize) &&
                        (std::max(std::abs(projected.x), std::abs(projected.y)) > projected.w+chunksize))
                        continue;
                    
                    // begin occlusion query
                    glBeginQuery(GL_ANY_SAMPLES_PASSED, chunks[j].query);
                    
                    // draw bounding box
                    glBindVertexArray(chunks[j].bounding_vao);
                    glDrawElements(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0);
                    
                    // end occlusion query
                    glEndQuery(GL_ANY_SAMPLES_PASSED);
                }
                j = i;
            }

            // render the current slice
            glEnable(GL_CULL_FACE);
            
            // turn rendering back on
            glDepthMask(GL_TRUE);
            glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
            glUseProgram(shader_program);
            for(;j<chunks.size() && glm::distance(chunks[j].center, position)<maxdist;++j)
            {
                // frustum culling
                glm::vec4 projected = ViewProjection*glm::vec4(chunks[j].center,1);
                if( (glm::distance(chunks[j].center,position) > chunksize) &&
                    (std::max(std::abs(projected.x), std::abs(projected.y)) > projected.w+chunksize))
                    continue;
                
                // begin conditional render
                if(occlusion_cull)
                    glBeginConditionalRender(chunks[j].query, GL_QUERY_BY_REGION_WAIT);
                
                // draw chunk
                glBindVertexArray(chunks[j].vao);
                glDrawElements(GL_TRIANGLES, 6*chunks[j].quadcount, GL_UNSIGNED_INT, 0);
                
                // end conditional render
                if(occlusion_cull)
                    glEndConditionalRender();
            }
            i = j;
            maxdist += 2*chunksize;
        }
        
        // end timer query
        glEndQuery(GL_TIME_ELAPSED);
        
        // display timer query results from querycount frames before
        if(GL_TRUE == glIsQuery(queries[(current_query+1)%querycount]))
        {
            GLuint64 result;
            glGetQueryObjectui64v(queries[(current_query+1)%querycount], GL_QUERY_RESULT, &result);
            std::cout << result*1.e-6 << " ms/frame" << std::endl;
        }
        // advance query counter
        current_query = (current_query + 1)%querycount;
        
        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
            std::cerr << gluErrorString(error);
            running = false;       
        }
        
        // finally swap buffers
        glfwSwapBuffers();       
    }
    
    // delete the created objects
    
    for(size_t i = 0;i<chunks.size();++i)
    {    
        glDeleteVertexArrays(1, &chunks[i].vao);
        glDeleteBuffers(1, &chunks[i].vbo);
        glDeleteBuffers(1, &chunks[i].ibo);
        glDeleteVertexArrays(1, &chunks[i].bounding_vao);
        glDeleteBuffers(1, &chunks[i].bounding_vbo);
        glDeleteBuffers(1, &chunks[i].bounding_ibo);
        glDeleteQueries(1, &chunks[i].query);
    }
    
    glDeleteQueries(querycount, queries);
    
    glDetachShader(shader_program, vertex_shader);	
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);

    glDetachShader(query_shader_program, query_vertex_shader);	
    glDetachShader(query_shader_program, query_fragment_shader);
    glDeleteShader(query_vertex_shader);
    glDeleteShader(query_fragment_shader);
    glDeleteProgram(query_shader_program);
    
    glfwCloseWindow();
    glfwTerminate();
    return 0;
}
Exemplo n.º 6
0
	void StaticMesh::Create(const char* fileName)
	{
		char baseDir[256];
		char fileNameWoExt[256];
		char tempPath[256];
		_splitpath_s(fileName, nullptr, 0, baseDir, sizeof(baseDir), fileNameWoExt, sizeof(baseDir), nullptr, 0);

		// キャッシュファイル名
		snprintf(tempPath, sizeof(tempPath), "%s%s.cache", baseDir, fileNameWoExt);
		std::ifstream cacheFile(tempPath, std::ios::in | std::ios::binary);
		if (cacheFile) {
			/** キャッシュから読み込み **/

			// ファイル全体をリード
			cacheFile.seekg(0, std::fstream::end);
			uint32_t eofPos = (uint32_t)cacheFile.tellg();
			cacheFile.clear();
			cacheFile.seekg(0, std::fstream::beg);
			uint32_t begPos = (uint32_t)cacheFile.tellg();
			uint32_t size = eofPos - begPos;
			std::unique_ptr<uint8_t> cacheData(new uint8_t[size]);
			cacheFile.read((char*)cacheData.get(), size);

			// パース
			const CacheHeader* header = (CacheHeader*)cacheData.get();
			const Shape* shapes = (Shape*)(cacheData.get() + header->offsetToShapes);
			shapes_.resize(header->shapeNum);
			memcpy(&shapes_[0], shapes, sizeof(Shape) * header->shapeNum);

			uint32_t vtxStride = ComputeVertexStride(header->vertexAttrs);
			vertexBuffer_.Create(cacheData.get() + header->offsetToVertices, vtxStride * header->vertexNum, header->vertexAttrs);
			indexBuffer_.Create(cacheData.get() + header->offsetToIndeces, sizeof(uint32_t) * header->vertexNum, INDEX_BUFFER_STRIDE_U32);

			const char* materials = (const char*)(cacheData.get() + header->offsetToMaterial);
			materials_.resize(header->materialNum);
			std::unordered_map<std::string, uint32_t> textureMap;
			for (size_t i = 0; i < (uint32_t)materials_.size(); i++) {
				const char* m = materials + (256 * i);
				ZeroMemory(&materials_[i], sizeof(materials_[i]));

				// テクスチャ検索
				if (strlen(m) > 0) {
					Texture* texture = nullptr;
					auto iter = textureMap.find(m);
					if (iter != textureMap.end()) {
						texture = textures_[iter->second];
					} else {
						texture = new Texture();
						snprintf(tempPath, sizeof(tempPath), "%s%s", baseDir, m);
						texture->LoadFromFile(tempPath);
						textures_.push_back(texture);
						uint32_t index = (uint32_t)textures_.size() - 1;
						textureMap[m] = index;

					}
					materials_[i].albedo = texture;
				}
			}
		} else {
			/** キャッシュがなかったらobjを読み込み **/
			tinyobj::attrib_t attrib;
			std::vector<tinyobj::shape_t> shapes;
			std::vector<tinyobj::material_t> materials;

			Printf("Loading %s\n", fileName);
			std::string err;
			if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, fileName, baseDir, true)) {
				if (!err.empty()) {
					Printf(err.c_str());
				}
				Printf("Failed to load/parse .obj.\n");
				return;
			}
			//Printf("# of vertices  : %d\n", (attrib.vertices.size() / 3));
			//Printf("# of normals   : %d\n", (attrib.normals.size() / 3));
			//Printf("# of texcoords : %d\n", (attrib.texcoords.size() / 2));
			//Printf("# of shapes    : %d\n", shapes.size());
			//Printf("# of materials : %d\n", materials.size());

			// 現状はすべてのシェイプで頂点構造が一致している前提で処理しているため1つの頂点バッファにすべて入っている
			// TODO:tangent, bitangent計算
			uint32_t vtxAttrs = VERTEX_ATTR_FLAG_POSITION;
			vtxAttrs |= (attrib.normals.size() > 0) ? VERTEX_ATTR_FLAG_NORMAL : 0;
			vtxAttrs |= (attrib.texcoords.size() > 0) ? VERTEX_ATTR_FLAG_TEXCOORD0 : 0;
			uint32_t vtxStride = ComputeVertexStride(vtxAttrs);

			// 全インデックス数を計算
			uint32_t totalIndexNum = 0;
			for (auto& shape : shapes) {
				totalIndexNum += static_cast<uint32_t>(shape.mesh.indices.size());
			}

			// 頂点をインデックス展開するためトータルインデックス数分の頂点バッファを確保
			std::unique_ptr<uint8_t> vertexData(new uint8_t[vtxStride * totalIndexNum]);
			std::unique_ptr<uint8_t> indexData(new uint8_t[sizeof(uint32_t) * totalIndexNum]);
			uint32_t currentIndex = 0;
			uint32_t* currentIndexBufferPtr = reinterpret_cast<uint32_t*>(indexData.get());
			for (uint32_t i = 0; i < shapes.size(); i++) {
				auto& shape = shapes[i];
				Assert(shape.mesh.num_face_vertices.size() == shape.mesh.material_ids.size());

				// For each face
				uint32_t currentMaterial = 0xffffffff;
				Shape currentShape;
				for (size_t f = 0; f < shape.mesh.num_face_vertices.size(); f++) {
					Assert(shape.mesh.num_face_vertices[f] == 3);	// 三角形化済みのはず

					// マテリアルの切り替わり判定
					if (currentMaterial != shape.mesh.material_ids[f]) {
						if (currentMaterial != 0xffffffff) {
							currentShape.indexCount = currentIndex - currentShape.indexStart;
							shapes_.push_back(currentShape);
						}
						currentMaterial = shape.mesh.material_ids[f];
						currentShape.materialIndex = currentMaterial;
						currentShape.indexStart = currentIndex;
						currentShape.indexCount = 0;
					}

					// For each vertex in the face
					uint32_t ptrOffset = 0;
					uint8_t* currentVertexBufferPtr = vertexData.get() + (vtxStride * currentIndex);
					for (size_t v = 0; v < 3; v++) {
						tinyobj::index_t idx = shape.mesh.indices[(f * 3) + v];

						// position
						memcpy(currentVertexBufferPtr + ptrOffset, &attrib.vertices[idx.vertex_index * 3], 12);
						ptrOffset += 12;

						// normal
						if (vtxAttrs & VERTEX_ATTR_FLAG_NORMAL) {
							memcpy(currentVertexBufferPtr + ptrOffset, &attrib.normals[idx.normal_index * 3], 12);
							ptrOffset += 12;
						}

						// texcoord
						if (vtxAttrs & VERTEX_ATTR_FLAG_TEXCOORD0) {
							float2* uv = reinterpret_cast<float2*>(currentVertexBufferPtr + ptrOffset);
							uv->x = attrib.texcoords[idx.texcoord_index * 2 + 0];
							uv->y = 1.0f - attrib.texcoords[idx.texcoord_index * 2 + 1]; // OpenGL -> DirectX
							ptrOffset += 8;
						}

						currentIndexBufferPtr[currentIndex] = currentIndex;
						currentIndex++;
					}
				}

				// 最後のマテリアル分追加
				currentShape.indexCount = currentIndex - currentShape.indexStart;
				shapes_.push_back(currentShape);
			}

			vertexBuffer_.Create(vertexData.get(), vtxStride * totalIndexNum, vtxAttrs);
			indexBuffer_.Create(indexData.get(), sizeof(uint32_t) * totalIndexNum, INDEX_BUFFER_STRIDE_U32);

			// マテリアル
			materials_.resize(materials.size());
			std::unordered_map<std::string, uint32_t> textureMap;
			for (size_t i = 0; i < (uint32_t)materials_.size(); i++) {
				auto& m = materials[i];
				ZeroMemory(&materials_[i], sizeof(materials_[i]));

				// テクスチャ検索
				if (m.diffuse_texname.size() > 0) {
					Texture* texture = nullptr;
					auto iter = textureMap.find(m.diffuse_texname);
					if (iter != textureMap.end()) {
						texture = textures_[iter->second];
					} else {
						texture = new Texture();
						snprintf(tempPath, sizeof(tempPath), "%s%s", baseDir, m.diffuse_texname.c_str());
						texture->LoadFromFile(tempPath);
						textures_.push_back(texture);
						uint32_t index = (uint32_t)textures_.size() - 1;
						textureMap[m.diffuse_texname] = index;

					}
					materials_[i].albedo = texture;
				}
			}

			// 読み込み高速化のためのキャッシュデータを生成
			{
				snprintf(tempPath, sizeof(tempPath), "%s%s.cache", baseDir, fileNameWoExt);
				std::ofstream file(tempPath, std::ios::out | std::ios::binary);

				CacheHeader header;
				header.shapeNum = (uint16_t)shapes_.size();
				header.materialNum = (uint16_t)materials_.size();
				header.vertexAttrs = (uint16_t)vtxAttrs;
				header.vertexNum = totalIndexNum;
				header.offsetToShapes = sizeof(CacheHeader);
				header.offsetToVertices = header.offsetToShapes + sizeof(Shape) * header.shapeNum;
				header.offsetToIndeces = header.offsetToVertices + (vtxStride * totalIndexNum);
				header.offsetToMaterial = header.offsetToIndeces + (sizeof(uint32_t) * totalIndexNum);
				file.write((char*)&header, sizeof(header));

				// シェイプ
				for (auto& s : shapes_) {
					file.write((char*)&s, sizeof(s));
				}
				// 頂点
				file.write((char*)vertexData.get(), vtxStride * totalIndexNum);
				// インデックス
				file.write((char*)indexData.get(), sizeof(uint32_t) * totalIndexNum);
				// マテリアル
				for (auto& m : materials) {
					FillMemory(tempPath, sizeof(tempPath), 0);
					snprintf(tempPath, sizeof(tempPath), "%s", m.diffuse_texname.c_str());
					file.write(tempPath, sizeof(tempPath));
				}
			}
		}
	}