Related
I am trying to build a code that uses OpenGL and shaders that adds texture to a square pyramid. After I added the functions to add the texture, ran the code but instead of rendering, I get a console window giving me the following error:
INFO: OpenGL Version: 4.4.0 NVIDIA 512.15
ERROR::SHADER::VERTEX::COMPILATION_FAILED
0(2) : error C1503: undefined variable "cameraPosition"
0(2) : error C1503: undefined variable "cameraPosition"
0(2) : error C1503: undefined variable "cameraPosition"
0(2) : error C1035: assignment of incompatible types
I have tried copying and pasting the cameraPosition variable from the bottom of my code to one of my main functions that has the gl_Position variable. But that did not solve the problem. Do I need to change the vec3 to vec4 somewhere or do I need to copy and paste the cameraPostion variable and definition somewhere else? Here is my code:
#include <iostream> // cout, cerr
#include <cstdlib> // EXIT_FAILURE
#include <GL/glew.h> // GLEW library
#include <GLFW/glfw3.h> // GLFW library
// GLM Math Header inclusions
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <SOIL2.h> // SOIL2 library
using namespace std; // Standard namespace
/*Shader program Macro*/
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version " core \n" #Source
#endif
// Input Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void cursor_position_callback(GLFWwindow* window, double xpos, double ypos);
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
// Declare View Matrix
glm::mat4 viewMatrix;
// Initialize FOV
GLfloat fov = 45.f;
// Define Camera Attributes
glm::vec3 cameraPosition = glm::vec3(0.f, 0.f, 3.f);
glm::vec3 target = glm::vec3(0.f, 0.f, 0.f);
glm::vec3 cameraDirection = glm::normalize(cameraPosition - target);
glm::vec3 worldUp = glm::vec3(0.f, 1.f, 0.f);
glm::vec3 cameraRight = glm::normalize(glm::cross(worldUp, cameraDirection));
glm::vec3 cameraUp = glm::normalize(glm::cross(cameraDirection, cameraRight));
glm::vec3 cameraFront = glm::normalize(glm::vec3(0.f, 0.f, -1.f));
// Declare target prototype
glm::vec3 getTarget();
// Camera transformation prototype
void TransformCamera();
// Boolean for keys and mouse buttons
bool keys[1024], mouseButtons[3];
// Boolean to check camera transformations
bool isPanning = false, isOrbiting = false;
// Radius, Pitch, and Yaw
GLfloat radius = 3.f, rawYaw = 0.f, rawPitch = 0.f, degYaw, degPitch;
GLfloat deltaTime = 0.f, lastFrame = 0.f;
GLfloat lastX = 400, lastY = 300, xChange, yChange;
bool firstMouseMove = true; // Detect inititial mouse movement
void initCamera();
// Unnamed namespace
namespace
{
const char* const WINDOW_TITLE = "Basic Camera Movement"; // Macro for window title
// Variables for window width and height
int WINDOW_WIDTH = 800;
int WINDOW_HEIGHT = 600;
// Stores the GL data relative to a given mesh
struct GLMesh
{
GLuint vao; // Handle for the vertex array object
GLuint vbos[2]; // Handles for the vertex buffer objects
GLuint nIndices; // Number of indices of the mesh
};
// Main GLFW window
GLFWwindow* gWindow = nullptr;
// Triangle mesh data
GLMesh gMesh;
// Shader program
GLuint gProgramId;
}
/* User-defined Function prototypes to:
* initialize the program, set the window size,
* redraw graphics on the window when resized,
* and render graphics on the screen
*/
bool UInitialize(int, char* [], GLFWwindow** window);
void UResizeWindow(GLFWwindow* window, int width, int height);
void UProcessInput(GLFWwindow* window);
void UCreateMesh(GLMesh& mesh);
void UDestroyMesh(GLMesh& mesh);
void URender();
bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId);
void UDestroyShaderProgram(GLuint programId);
/* Vertex Shader Source Code*/
const GLchar* vertexShaderSource = GLSL(440,
layout(location = 0) in vec3 position; // Vertex data from Vertex Attrib Pointer 0
layout(location = 1) in vec3 color; // Color data from Vertex Attrib Pointer 1
layout(location = 2) in vec2 texture; // Texture data from Vertex Attrib Pointer 2
out vec3 vertexColor; // variable to transfer color data to the fragment shader
out vec3 vertexTexture;
//Global variables for the transform matrices
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform sampler2D myTexture; // Sampler
void main()
{
gl_Position = projection * view * model * vec4(cameraPosition.x, cameraPosition.y, cameraPosition.z, 1.0f); // transforms vertices to clip coordinates
vertexColor = color; // references incoming color data
vertexTexture = texture;
}
);
/* Fragment Shader Source Code*/
const GLchar* fragmentShaderSource = GLSL(440,
in vec3 vertexColor; // Variable to hold incoming color data from vertex shader
out vec3 fragmentColor;
out vec3 fragmentTexture;
void main()
{
fragmentColor = texture(myTexture, textTexture);
fragmentTexture = vec2(vertexTexture);
}
);
int main(int argc, char* argv[])
{
if (!UInitialize(argc, argv, &gWindow))
return EXIT_FAILURE;
// Create the mesh
UCreateMesh(gMesh); // Calls the function to create the Vertex Buffer Object
// Create the shader program
if (!UCreateShaderProgram(vertexShaderSource, fragmentShaderSource, gProgramId))
return EXIT_FAILURE;
// Sets the background color of the window to black (it will be implicitely used by glClear)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Set input call back functions
glfwSetKeyCallback(gWindow, key_callback);
glfwSetCursorPosCallback(gWindow, cursor_position_callback);
glfwSetMouseButtonCallback(gWindow, mouse_button_callback);
glfwSetScrollCallback(gWindow, scroll_callback);
// render loop
// -----------
while (!glfwWindowShouldClose(gWindow))
{
// Set delta time
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
// Resize window and graphics simultaneously
glfwGetFramebufferSize(gWindow, &WINDOW_WIDTH, &WINDOW_HEIGHT);
// input
// -----
UProcessInput(gWindow);
// Render this frame
URender();
glfwPollEvents();
// Poll camera transformations
TransformCamera();
}
// Release mesh data
UDestroyMesh(gMesh);
// Release shader program
UDestroyShaderProgram(gProgramId);
exit(EXIT_SUCCESS); // Terminates the program successfully
}
// Initialize GLFW, GLEW, and create a window
bool UInitialize(int argc, char* argv[], GLFWwindow** window)
{
// GLFW: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// GLFW: window creation
// ---------------------
* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, NULL, NULL);
if (*window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return false;
}
glfwMakeContextCurrent(*window);
glfwSetFramebufferSizeCallback(*window, UResizeWindow);
// GLEW: initialize
// ----------------
// Note: if using GLEW version 1.13 or earlier
glewExperimental = GL_TRUE;
GLenum GlewInitResult = glewInit();
if (GLEW_OK != GlewInitResult)
{
std::cerr << glewGetErrorString(GlewInitResult) << std::endl;
return false;
}
// Displays GPU OpenGL version
cout << "INFO: OpenGL Version: " << glGetString(GL_VERSION) << endl;
return true;
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
void UProcessInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
float cameraSpeed = 2.5 * deltaTime;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
cameraPosition += cameraSpeed * cameraFront;
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
cameraPosition -= cameraSpeed * cameraFront;
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
cameraPosition -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
cameraPosition += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS)
cameraPosition -= cameraSpeed * cameraUp;
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS)
cameraPosition += cameraSpeed * cameraUp;
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
void UResizeWindow(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
// Functioned called to render a frame
void URender()
{
// Enable z-depth
glEnable(GL_DEPTH_TEST);
// Wireframe mode
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// Clear the frame and z buffers
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 1. Scales the object by 2
glm::mat4 scale = glm::scale(glm::vec3(1.0f, 1.0f, 1.0f));
// 2. Rotates shape by 15 degrees in the x axis
glm::mat4 rotation = glm::rotate(45.0f, glm::vec3(1.0, 1.0f, 1.0f));
// 3. Place object at the origin
glm::mat4 translation = glm::translate(glm::vec3(0.0f, 0.0f, 0.0f));
// Model matrix: transformations are applied right-to-left order
glm::mat4 model = translation * rotation * scale;
// Transforms the camera: move the camera back (z axis)
glm::mat4 view = glm::lookAt(cameraPosition, getTarget(), worldUp);
// Creates a perspective projection
glm::mat4 projection = glm::perspective(fov, (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, 0.1f, 100.0f);
// Set the shader to be used
glUseProgram(gProgramId);
// Retrieves and passes transform matrices to the Shader program
GLint modelLoc = glGetUniformLocation(gProgramId, "model");
GLint viewLoc = glGetUniformLocation(gProgramId, "view");
GLint projLoc = glGetUniformLocation(gProgramId, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
GLuint crateTexture = {1};
glBindTexture(GL_TEXTURE_2D, crateTexture);
// Activate the VBOs contained within the mesh's VAO
glBindVertexArray(gMesh.vao);
// Draws the triangles
glDrawElements(GL_TRIANGLES, gMesh.nIndices, GL_UNSIGNED_SHORT, NULL); // Draws the triangle
// Deactivate the Vertex Array Object
glBindVertexArray(0);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
glfwSwapBuffers(gWindow); // Flips the the back buffer with the front buffer every frame.
}
// Implements the UCreateMesh function
void UCreateMesh(GLMesh& mesh)
{
// Position and Color data
GLfloat verts[] = {
0.0f, 1.0f, 0.0f, // Top Center Vertex 0
1.0f, 0.0f, 0.0f, 1.0f, // Red
0.5f, 1.0f, // UV
-1.0f, -1.0f, 1.0f, // Bottom Left Vertex 1
0.0f, 1.0f, 0.0f, 1.0f, // Green
0.0f, 0.0f, // UV
1.0f, -1.0f, 1.0f, // Bottom Right Vertex 2
0.0f, 0.0f, 1.0f, 1.0f, // Blue
1.0f, 0.0f, // UV
1.0f, -1.0f, -1.0f, // Bottom Back Right Vertex 3
1.0f, 0.0f, 1.0f, 1.0f, // Magenta
0.0f, 0.0f, // UV
-1.0f, -1.0f, -1.0f, // Bottom Back Left Vertex 4
1.0f, 1.0f, 0.0f, 1.0f, // Yellow
1.0f, 0.0f // UV
};
// Index data to share position data
GLushort indices[] = {
// Sides
0, 1, 2, // Triangle 1
0 ,2, 3, // Triangle 2
0, 3, 1, // Triangle 3
0, 3, 4, // Triangle 4
// Base
1, 2, 3, // Triangle 5
1, 4, 3 // Triangle 6
};
const GLuint floatsPerVertex = 3;
const GLuint floatsPerColor = 4;
const GLuint floatsPerTexture = 2;
glGenVertexArrays(1, &mesh.vao); // we can also generate multiple VAOs or buffers at the same time
glBindVertexArray(mesh.vao);
// Create 2 buffers: first one for the vertex data; second one for the indices
glGenBuffers(2, mesh.vbos);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbos[0]); // Activates the buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); // Sends vertex or coordinate data to the GPU
mesh.nIndices = sizeof(indices) / sizeof(indices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.vbos[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Strides between vertex coordinates is 6 (x, y, z, r, g, b, a). A tightly packed stride is 0.
GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor);// The number of floats before each
// Create Vertex Attribute Pointers
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, floatsPerTexture, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerTexture));
glEnableVertexAttribArray(2);
// Load textures
int crateTexWidth, crateTexHeight, gridTexWidth, gridTexHeight;
unsigned char* crateImage = SOIL_load_image("crate.png", &crateTexWidth, &crateTexHeight, 0, SOIL_LOAD_RGB);
unsigned char* gridImage = SOIL_load_image("crate.png", &gridTexWidth, &gridTexHeight, 0, SOIL_LOAD_RGB);
// Generate Textures
GLuint crateTexture = {1};
glGenTextures(1, &crateTexture);
glBindTexture(GL_TEXTURE_2D, crateTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, crateTexWidth, crateTexHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, crateImage);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(crateImage);
glBindTexture(GL_TEXTURE_2D, 0);
// Generate Textures
GLuint gridTexture;
glGenTextures(1, &gridTexture);
glBindTexture(GL_TEXTURE_2D, gridTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, gridTexWidth, gridTexHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, gridImage);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(gridImage);
glBindTexture(GL_TEXTURE_2D, 0);
}
void UDestroyMesh(GLMesh& mesh)
{
glDeleteVertexArrays(1, &mesh.vao);
glDeleteBuffers(2, mesh.vbos);
}
// Implements the UCreateShaders function
bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId)
{
// Compilation and linkage error reporting
int success = 0;
char infoLog[512];
// Create a Shader program object.
programId = glCreateProgram();
// Create the vertex and fragment shader objects
GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
// Retrive the shader source
glShaderSource(vertexShaderId, 1, &vtxShaderSource, NULL);
glShaderSource(fragmentShaderId, 1, &fragShaderSource, NULL);
// Compile the vertex shader, and print compilation errors (if any)
glCompileShader(vertexShaderId); // compile the vertex shader
// check for shader compile errors
glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShaderId, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
return false;
}
glCompileShader(fragmentShaderId); // compile the fragment shader
// check for shader compile errors
glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShaderId, sizeof(infoLog), NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
return false;
}
// Attached compiled shaders to the shader program
glAttachShader(programId, vertexShaderId);
glAttachShader(programId, fragmentShaderId);
glLinkProgram(programId); // links the shader program
// check for linking errors
glGetProgramiv(programId, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(programId, sizeof(infoLog), NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
return false;
}
glUseProgram(programId); // Uses the shader program
return true;
}
void UDestroyShaderProgram(GLuint programId)
{
glDeleteProgram(programId);
}
// Define Input Callback functions
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
// Display ASCII Keycode
//cout << "ASCII: " << key << endl;
if (action == GLFW_PRESS)
keys[key] = true;
else if (action == GLFW_RELEASE)
keys[key] = false;
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
/*
// Display scroll offset
if (yoffset > 0)
cout << "Scroll Up: ";
if (yoffset < 0)
cout << "Scroll Down: ";
cout << yoffset << endl;
*/
// Clamp FOV
if (fov >= 1.f && fov <= 45.f)
fov -= yoffset * 0.01f;
//Default FOV
if (fov < 1.f)
fov = 1.f;
if (fov > 45.f)
fov = 45.f;
}
void cursor_position_callback(GLFWwindow* window, double xpos, double ypos) {
// Display mouse x and y coordinates
// cout << "Mouse X: " << xpos << endl;
// cout << "Mouse Y: " << ypos << endl;
if (firstMouseMove) {
lastX = xpos;
lastY = ypos;
firstMouseMove = false;
}
// Calculate cursor offset
xChange = xpos - lastX;
yChange = lastY - ypos;
lastX = xpos;
lastY = ypos;
// Pan camera
if (isPanning) {
if (cameraPosition.z < 0.f)
cameraFront.z = 1.f;
else
cameraFront.z = -1.f;
GLfloat cameraSpeed = xChange * deltaTime;
cameraPosition += cameraSpeed * cameraRight;
cameraSpeed = yChange * deltaTime;
cameraPosition += cameraSpeed * cameraUp;
}
// Orbit camera
if (isOrbiting) {
rawYaw += xChange;
rawPitch += yChange;
// Convert Yaw and Pitch to degrees
degYaw = glm::radians(rawYaw);
// degPitch = glm::radians(rawPitch)
degPitch = glm::clamp(glm::radians(rawPitch), -glm::pi<float>() / 2.f + .1f, glm::pi<float>() / 2.f - .1f);
// Azimuth Altitude formula
cameraPosition.x = target.x + radius * cosf(degPitch) * sin(degYaw);
cameraPosition.y = target.y + radius * sinf(degPitch);
cameraPosition.z = target.z + radius * cosf(degPitch) * cosf(degYaw);
}
}
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
/*
// Detect mouse button clicks
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
cout << "LMB clicked!" << endl;
if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS)
cout << "MMB clicked!" << endl;
if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
cout << "RMB clicked!" << endl;
*/
if (action == GLFW_PRESS)
mouseButtons[button] = true;
else if (action == GLFW_RELEASE)
mouseButtons[button] = false;
}
// Define getTarget function
glm::vec3 getTarget() {
if (isPanning)
target = cameraPosition + cameraFront;
return target;
}
// Define TransformCamera function
void TransformCamera() {
// Pan camera
if (keys[GLFW_KEY_LEFT_ALT] && mouseButtons[GLFW_MOUSE_BUTTON_MIDDLE])
isPanning = true;
else
isPanning = false;
// Orbit camera
if ((mouseButtons[GLFW_MOUSE_BUTTON_LEFT]))
isOrbiting = true;
else
isOrbiting = false;
// Reset camera
if (keys[GLFW_KEY_F])
initCamera();
}
void initCamera() {
cameraPosition = glm::vec3(0.f, 0.f, 3.f);
target = glm::vec3(0.f, 0.f, 0.f);
cameraDirection = glm::normalize(cameraPosition - target);
worldUp = glm::vec3(0.f, 1.f, 0.f);
cameraRight = glm::normalize(glm::cross(worldUp, cameraDirection));
cameraUp = glm::normalize(glm::cross(cameraDirection, cameraRight));
cameraFront = glm::normalize(glm::vec3(0.f, 0.f, -1.f));
}
You never actually bother to declare/define a cameraPosition (presumably) uniform in your vertex shader or set its value via an appropriate glUniform*() call.
...not that you'd really want to since then every vertex would end up being set to the same position and you'd end up with a dot somewhere (maybe) on screen.
Rather,
gl_Position = projection * view * model * vec4(cameraPosition.x, cameraPosition.y, cameraPosition.z, 1.0f);
should probably be:
gl_Position = projection * view * model * vec4(position, 1.0);
...so all your fancy geometry in verts actually has some chance of being sensibly displayed.
I'm currently working on an assignment on creating a solar system using openGL. I've managed to create the planets, orbit of planet around the sun, and rotation of each planet axis.
i'm stuck on how do i dynamically draw a line for the orbit path for the planets. so that even if the orbit path changes the line would change.(those thin lines that shows the orbit path in most solar system images)
Hope to get a direction to work towards to instead of the answer.
Thanks ahead for the replies (if any)
P.S : Using GLFW not GLUT library. Below is what i have so far
static void init(GLFWwindow* window)
{
glEnable(GL_DEPTH_TEST);
// Create the shader object
g_shaderProgramID = loadShaders("ModelSpaceVS.vert", "ColorFS.frag");
// Getting Locations of shader's variables
GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition");
GLuint colorIndex = glGetAttribLocation(g_shaderProgramID, "aColor");
g_modelMatrixIndex = glGetUniformLocation(g_shaderProgramID, "uModelMatrix");
// Creating camera object
// Set camera's view matrix
g_camera.setViewMatrix(vec3(0.0f, 15.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f), vec3(0, 1, 0));
// Window Aspect Ratio
int width, height;
glfwGetFramebufferSize(window, &width, &height);
float aspectRatio = static_cast<float>(width) / height;
// Set camera's projection matrix
g_camera.setProjectionMatrix(perspective(45.0f, aspectRatio, 0.1f, 100.0f));
// Initialise the model matrix to identity matrix
// Set to 1.0f so that during the transformation process where
// the matrix is multiplied, it would be 1*<value> = <value>
// The transformation && scale && rotate are placed in the update_scene Function
// as the update scene needs to update the orbitting value as well
g_modelMatrix[0] = mat4(1.0f);
g_modelMatrix[1] = mat4(1.0f);
g_modelMatrix[2] = mat4(1.0f);
g_modelMatrix[3] = mat4(1.0f);
g_modelMatrix[4] = mat4(1.0f);
// Generate identifier for VBO and copy data to GPU
glGenBuffers(4, g_VBO);
// Binding the vertices for the planet (Only 1 vertices for sun + 4 planets)
// Transformation is not done here
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(planetOrigin), planetOrigin, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_VBO[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices), g_indices, GL_STATIC_DRAW);
// Line Vertex
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]); // Binding the VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(linePos), linePos, GL_STATIC_DRAW); // Copy data to buffer
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[3]); // Binding the VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(lineColor), lineColor, GL_STATIC_DRAW); // Copy data to buffer
// generate identifiers for VAOs
glGenVertexArrays(2, g_VAO);
// create VAO and specify VBO data
glBindVertexArray(g_VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_VBO[1]);
// interleaved attributes
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertices), reinterpret_cast<void*>(offsetof(Vertices, position)));
glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertices), reinterpret_cast<void*>(offsetof(Vertices, color)));
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
// Binding the VBO to a VAO
// Lines
glBindVertexArray(g_VAO[1]); // Create the VAO object
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[3]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
}
// Keyboard Input Actions
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
// Exit the program on ESC
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
// Closes the window and end the program
glfwSetWindowShouldClose(window, GL_TRUE);
return;
}
else if (key == GLFW_KEY_P && action == GLFW_PRESS)
{
// Animating the planets Orbit around the sun
// and also their own individual rotation about their own axis
if (animate == false)
animate = true;
else if (animate == true)
animate = false;
}
else if (key == GLFW_KEY_R && action == GLFW_PRESS)
{
// Randomize the Size / Orbit Speed Around the Sun / Rotation Speed about their own axis
// of all the planet and the sun
//
//
// Rand + 100 to prevent the orbit or rotationSpeed from being 0
// Or being too low that it seems to stop
//
// Randomizing the orbitSpeed of planet
// Capping the orbit Speed at 300, minimum 100
orbitSpeed = (rand() % 200) + 100;
// Randomizing the rotationSpeed of planet + sun
// upon its own axis
// Capping the rotation Speed at 300, minimum 100
rotationSpeed = (rand() % 200) + 100;
// Randomizing the planet/sun size
// Values of the rand() is to ensure the planet will never be bigger than the sun
// rand() % 3 / 10 + 0.7 = min : 0.7, Max : 1.0
// rand() % 5 / 10 + 0.2 = min : 0.2, Max : 0.7
sunSize = (rand() % 2) + 3.0;
planetSize1 = (rand() % 2) + 0.9;
planetSize2 = (rand() % 2) + 0.9;
planetSize3 = (rand() % 2) + 0.9;
planetSize4 = (rand() % 2) + 0.9;
}
else if (key == GLFW_KEY_1 && action == GLFW_PRESS)
{
// Set the camera view to a far-away top down view of the
// solar system
// Looks like a RTS camera style
// Set camera's view matrix
g_camera.setViewMatrix(vec3(0.0f, 10.0f, 20.0f), vec3(0.0f, 0.0f, 0.0f), vec3(0, 1, 0));
}
else if (key == GLFW_KEY_2 && action == GLFW_PRESS)
{
// Set the camera view to a top down view
// directly looking at it from above
// Set camera's view matrix
g_camera.setViewMatrix(vec3(0.0f, 20.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f), vec3(0, 1.0, 0));
}
}
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
// variables to store mouse cursor coordinates
static double previous_xpos = xpos;
static double previous_ypos = ypos;
double delta_x = xpos - previous_xpos;
double delta_y = ypos - previous_ypos;
// pass mouse movement to camera class
g_camera.updateYaw(delta_x);
g_camera.updatePitch(delta_y);
// update previous mouse coordinates
previous_xpos = xpos;
previous_ypos = ypos;
}
// Frame Buffer Action
static void framebuffer_Size_callback(GLFWwindow* window, int width, int height)
{
string title = "Assignment 1 - " + to_string(width) + " x " + to_string(height);
glfwSetWindowTitle(window, title.c_str());
}
// error callback function
static void error_callback(int error, const char* description)
{
// output error description
cerr << "Error Occurred: " << description << endl;
}
// Update Scene Function
// Updates the "planet" solitary rotation about its own axis
// Updates the "planet" orbit around a point around the "sun"
static void update_scene(GLFWwindow* window, double frameTime)
{
static float rotateAngleY = 0.0f;
static float rotateAngleY1 = 0.0f;
static float rotateAngleY2 = 0.0f;
static float rotateAngleY3 = 0.0f;
static float sunRotateAngleY = 0.0f;
static float orbitAngle1 = 0.0f;
static float orbitAngle2 = 0.0f;
static float orbitAngle3 = 0.0f;
static float orbitAngle4 = 0.0f;
if (animate == true)
{
rotateAngleY += 1.5 * rotationSpeed * frameTime;
rotateAngleY1 += 1.0 * rotationSpeed * frameTime;
rotateAngleY2 -= 2.0 * rotationSpeed * frameTime;
rotateAngleY3 -= 2.5 * rotationSpeed * frameTime;
sunRotateAngleY += 0.1 * rotationSpeed * frameTime;
orbitAngle1 += 0.6 * orbitSpeed * frameTime;
orbitAngle2 += 0.5 * orbitSpeed * frameTime;
orbitAngle3 += 0.2 * orbitSpeed * frameTime;
orbitAngle4 += 0.1 * orbitSpeed * frameTime;
}
// Updating the Scene the rotate the individual planets
// Each of the planet needs their initial translate/scale value
// if the transform/scale here is vec(0.0,0.0,0.0) || vec3(1.0,1.0,1.0)
// They will be rendered on the origin, which is where the sun is
// at the same size
//
// rotate(radians(orbitAngle1), vec3(0.0f, 1.0f, 0.0f)) - Controls Orbit Rotation of Planet
// rotate(radians(rotateAngleY), vec3(1.0f, 1.0f, 0.0f)) - Controls Orbit About Own Axis
// rotate(radians(-60.0f), vec3(0.0f, 0.0f, 1.0f)) - Controls the rotation of a planet on display(without movement)
g_modelMatrix[0] = translate(vec3(0.0f, 0.0, 0.0f)) * rotate(radians(sunRotateAngleY), vec3(0.0, 1.0, 0.0f))
* scale(vec3(1.0f, 1.0f, 1.0f) * sunSize);
g_modelMatrix[1] = rotate(radians(orbitAngle1), vec3(0.0f, 1.0f, 0.0f)) * translate(vec3(2.0f, 0.0f, 0.0f) + (sunSize/10)) * rotate(radians(rotateAngleY), vec3(0.0f, 1.0f, 0.0f))
* rotate(radians(-60.0f), vec3(0.0f, 0.0f, 1.0f)) * scale(vec3(1.0f, 1.0f, 1.0f) * planetSize1);
g_modelMatrix[2] = rotate(radians(orbitAngle2), vec3(0.0f, 1.0f, 0.0f)) * translate(vec3(4.0f, 0.0f, 0.0f) + (sunSize/10)) * rotate(radians(rotateAngleY1), vec3(0.0f, 1.0f, 0.0f))
* rotate(radians(-45.0f), vec3(0.0f, 0.0f, 1.0f)) * scale(vec3(1.0f, 1.0f, 1.0f)* planetSize2);
g_modelMatrix[3] = rotate(radians(orbitAngle3), vec3(0.0f, 1.0f, 0.0f)) * translate(vec3(6.0f, 0.0f, 0.0f) + (sunSize/10)) * rotate(radians(rotateAngleY2), vec3(0.0f, 1.0f, 0.0f))
* rotate(radians(45.0f), vec3(0.0f, 0.0f, 1.0f)) * scale(vec3(1.0f, 1.0f, 1.0f) * planetSize3);
g_modelMatrix[4] = rotate(radians(orbitAngle4), vec3(0.0f, 1.0f, 0.0f)) * translate(vec3(8.0f, 0.0f, 0.0f) + (sunSize/10)) * rotate(radians(rotateAngleY), vec3(0.0f, 1.0f, 0.0f))
* rotate(radians(60.0f), vec3(0.0f, 0.0f, 1.0f)) * scale(vec3(1.0f, 1.0f, 1.0f) * planetSize4);
}
// Render Scene Function
static void render_scene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear colour buffer && clear depth buffer
glUseProgram(g_shaderProgramID);
// Make VAO active
glBindVertexArray(g_VAO[0]);
// Sun Object
// compute multiplication of model, view and projection matrices
mat4 MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[0];
glUniformMatrix4fv(g_modelMatrixIndex, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
// Planet 1
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[1];
glUniformMatrix4fv(g_modelMatrixIndex, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
// Planet 2
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[2];
glUniformMatrix4fv(g_modelMatrixIndex, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
// Planet 3
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[3];
glUniformMatrix4fv(g_modelMatrixIndex, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
// Planet 4
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[4];
glUniformMatrix4fv(g_modelMatrixIndex, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
glFlush(); // Flushing the pipelines
}
// ------------------------------------------------------------------------------------
// Main Function
int main(void)
{
srand(time(NULL));
GLFWwindow* window = NULL; // Creating of window variable
glfwSetErrorCallback(error_callback);
// Initialise glfw
// if false = failed initialization
if (!glfwInit())
{
cout << "glfw Initialisation failed" << endl;
exit(EXIT_FAILURE);
}
// Declaring the version of OpenGL
// Version 3.3 in this case
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// Creating the window object
window = glfwCreateWindow(1080, 720, "Assignment 2 - 1080 x 720", NULL, NULL);
// Check if the Creating of window Object succeeded
if (window == NULL)
{
cout << "Creation of window failed" << endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
// Making Context Current
glfwMakeContextCurrent(window);
// Determine Swap Buffer Interval
glfwSwapInterval(1);
// Set a background color for window
// Black - Solar System in space
glClearColor(0.0, 0.0, 0.0, 1.0);
// Initialise GLEW
if (glewInit() != GLEW_OK)
{
cout << "Initialisation of GLEW failed" << endl;
exit(EXIT_FAILURE);
}
// Keyboard/Mouse Input/Callbacks
glfwSetFramebufferSizeCallback(window, framebuffer_Size_callback);
glfwSetKeyCallback(window, key_callback);
glfwSetCursorPosCallback(window, cursor_position_callback);
// Init function
init(window);
// Frame Variables
double lastUpdateTime = glfwGetTime(); // last update time
double elapsedTime = lastUpdateTime; // time elapsed since last update
double frameTime = 0.0f; // frame time
int frameCount = 0; // number of frames since last update
// Rendering Loop
while (!glfwWindowShouldClose(window))
{
g_camera.update(window);
update_scene(window, frameTime);
render_scene();
// Swap Buffer
glfwSwapBuffers(window);
// Poll Events
glfwPollEvents();
frameCount++;
elapsedTime = glfwGetTime() - lastUpdateTime; // current time - last update time
if (elapsedTime >= 1.0f) // if time since last update >= to 1 second
{
frameTime = 1.0f / frameCount; // calculate frame time
string str = "FPS = " + to_string(frameCount) + "; FT = " + to_string(frameTime);
glfwSetWindowTitle(window, str.c_str()); // update window title
frameCount = 0; // reset frame count
lastUpdateTime += elapsedTime; // update last update time
}
}
// Cleaning Up Shader Program
glDeleteProgram(g_shaderProgramID);
// Cleaning Up Vertexes
glDeleteBuffers(14, g_VBO);
glDeleteVertexArrays(2, g_VAO);
// Destroying the window before terminating the program
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
I need to create a virtual trackball with c++. I have made all the calculations and I can find the rotation angle and axis values. My object rotates as I intented with every mouse drag but the problem is after every rotation it goes back to its initial position.
So I figured out that I need to get the current modelview matrix, multiply it by the rotation matrix then load the result back to the opengl.
I have tried it but unfortunately, glRotatef rotates my camera instead of the object. Here is my function to draw the scene
//--- Drawing code ---------------------------------------
/** Drawing code for one frame. */
void drawGLScene ()
{
// Real time in seconds.
GLfloat t = frameStat->frameStart( width, height );
// Clear the frame buffer and the depth buffer
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// Set current model-view transform:
glLoadIdentity();
// Looking from "camera" to the "center" point (y-axis defines the "up" vector)
gluLookAt( 0.0f, 0.0f, 10.0f,
center[ 0 ], center[ 1 ], center[ 2 ],
0.0f, 1.0f, 0.0f );
if (dragging)
glLoadMatrixf(matModelView.array());
glScalef( zoom, zoom, zoom );
#ifdef USE_VBO
// scene rendering using VBO buffers:
scene.render();
#else
// client-side vertex arrays (cube):
glVertexPointer( 3, GL_FLOAT, 6 * sizeof(GLfloat), vert ); // specify vertex data array
glColorPointer( 3, GL_FLOAT, 6 * sizeof(GLfloat), vert + 3 ); // specify vertex color array
glDrawElements( GL_QUADS, sizeof(ind) / sizeof(GLubyte), GL_UNSIGNED_BYTE, ind );
#endif
frameStat->swapBuffers( drawStat ); // SDL_GL_SwapWindow() and frame statistics
}
//--- Event handling -------------------------------------
/** Function to release/destroy our resources and restore the old desktop. */
void Quit ( int returnCode )
{
scene.deleteBuffers();
if ( glcontext )
SDL_GL_DeleteContext( glcontext );
// Clean up the window ..
SDL_Quit();
// .. and exit appropriately
exit( returnCode );
}
And here is my mouse handling functions, I am excluding the release function since it is trivial.
//--------------------------------------------------------
// Mouse handling:
void handleMouseMove ( SDL_Event &ev )
{
if ( ev.button.button == SDL_BUTTON_LEFT && dragging )
{
rotation.set(MI_IDENTITY);
rotation.rotate(5, 0.0f, 1.0f, 0.0f);
matModelView = matModelView * rotation;
}
}
void handleMousePress ( SDL_Event &ev )
{
if ( ev.button.button == SDL_BUTTON_LEFT )
{
dragging = true;
glMatrixMode(GL_MODELVIEW);
glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)matModelView.array());
rotation.set(MI_IDENTITY);
}
}
matModelView and rotation are 4x4 matrices. In this code, I am not included my trackball calculations. Here, I just expect it to rotate by 5 degree through the x axis as long as mouse dragging .
Maybe it is so simple but I am stuked into this point. Any guideness, code samples would be great.
Try changing:
matModelView = matModelView * rotation;
To this:
matModelView = rotation * matModelView;
Right now I'm rotating an object, lets call it 'mainBody' but attached to the mainBody are several attachments and when I rotate my mainBody they are supposed to rotate along as well, but right now they don't. I'm not using a parent/child system. The main body has an array of it's attachments and draws them in the mainBody draw function.
The glPopMatrix() from the main body is done after the equipment items are drawn.
I know I managed to do this in the past with pushMatrix(); and popMatrix(); But now it doesn't seem to work.
I'm using c++, opengl, and glm.
Here is some code that shows you what I have right now:
{
setupStartModelMatrix(); //<---- Has glPushMatrix();
setupModelviewMatrix(); //<--- has all the gml stuff
drawMainBody();
}
if(mNumberOfEquipementOwned != 0)
{
for(int i = 0; i < mNumberOfEquipementOwned; i++)
{
//obj is retrieved with a function
obj->render();
}
}
setupEndModelMatrix(); // <--- Has glPopMatrix();
}
And the glm code
void GameObject::setupModelviewMatrix()
{
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.f);
glm::mat4 Model = glm::scale( glm::mat4(1.0f), glm::vec3(1.0f));
glm::mat4 ViewTranslate = glm::translate( glm::mat4(1.0f), glm::vec3(mPosition.x, mPosition.y, mPosition.z));
glm::mat4 ViewRotateX = glm::rotate( ViewTranslate, mRotation.x, glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 ViewRotateY = glm::rotate( ViewRotateX, mRotation.y, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 View = glm::rotate( ViewRotateY, mRotation.z, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 MVP = View * Model;
glUniformMatrix4fv( 0, 1, GL_FALSE, glm::value_ptr(MVP));
glLoadMatrixf(glm::value_ptr(MVP));
}
And the draw equipement code
void Gun::render()
{
glPushMatrix();
setupModelviewMatrix();
mMesh->render();
glPopMatrix();
}
My guess is that you are calling glPushMatrix(), rotating, drawing your main body, calling glPopMatrix(), then drawing the attachments. If this is true, move the glPopMatrix() call to after drawing the attachments.
Because of Tim I noticed my matrix wasn't passed trough too the others. When I finally understood what he was saying it's a easy fix so 100% of the props go to him.
Now the code for anyone who might need it.
{
glm::mat4 startingModel(1.0);
setupStartModelMatrix();
startingModel = continuedModelvieuwMatrix(startingModel);
drawMainBody();
}
if(mNumberOfEquipementOwned != 0)
{
for(int i = 0; i < mNumberOfEquipementOwned; i++)
{
//obj is retrieved with a function
obj->render(startingModel);
}
}
setupEndModelMatrix(); // <--- Has glPopMatrix();
}
And the glm code
glm::mat4 GameObject::continuedModelvieuwMatrix(glm::mat4 startingModel)
{
glm::mat4 Model = glm::scale( glm::mat4(1.0f), glm::vec3(1.0f));
glm::mat4 ViewTranslate = glm::translate( startingModel, glm::vec3(mPosition.x, mPosition.y, mPosition.z));
glm::mat4 ViewRotateX = glm::rotate( ViewTranslate, mRotation.x, glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 ViewRotateY = glm::rotate( ViewRotateX, mRotation.y, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 View = glm::rotate( ViewRotateY, mRotation.z, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 MVP = View * Model;
glUniformMatrix4fv( 0, 1, GL_FALSE, glm::value_ptr(MVP));
glLoadMatrixf(glm::value_ptr(MVP));
return MVP;
}
void GameObject::setupStartModelMatrix()
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
And the draw equipement code
void Gun::render(glm::mat4 startingModel)
{
glm::math4 tempModel;
tempModel = continuedModelvieuwMatrix(startingModel);
mMesh->render();
}
And thats about it.
I'm not 100% sure if this code works as I had to fix it for my self in a different way because of my object construction but this should at least give a good head start for anyone with the same problem.
Also no glPopMatrix() or glPushMatrix() is required to make this work.
For some strange reason my depth buffer is not working, i.e. the triangles drawn later always overlap, regardless of their position.
I have these presenter parameters
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = mWindow;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = mScreenWidth;
d3dpp.BackBufferHeight = mScreenHeight;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
and these render states:
d3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE); // turn off the 3D lighting
d3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE); // turn on the z-buffer
d3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);
d3dDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(50, 50, 50)); // ambient light
edit:
thanks for replying. this is the rendering code code:
d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3dDevice->BeginScene();
// View transform
D3DXMATRIX matView;
D3DXMatrixLookAtLH(&matView,
&PlayerPos, // the camera position
&(LookAtRelative + PlayerPos), // the look-at position
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f)); // the up direction
d3dDevice->SetTransform(D3DTS_VIEW, &matView);
// Projection transform
D3DXMATRIX matProjection;
D3DXMatrixPerspectiveFovLH(&matProjection,
D3DXToRadian(45), // the horizontal field of view
(FLOAT)mScreenWidth / (FLOAT)mScreenHeight, // aspect ratio
0.0f, // the near view-plane
1000.0f); // the far view-plane
d3dDevice->SetTransform(D3DTS_PROJECTION, &matProjection);
for (unsigned int i=0; i < mModels.size(); i++) {
mModels[i]->Draw();
}
d3dDevice->EndScene();
d3dDevice->Present(NULL, NULL, NULL, NULL);
and the Model::Draw() code is this:
void Model :: Draw () {
// Setup the world transform matrix
D3DXMATRIX matScale;
D3DXMATRIX matRotate;
D3DXMATRIX matTranslate;
D3DXMATRIX matWorldTransform;
D3DXMatrixScaling(&matScale, mScale->x, mScale->y, mScale->z);
D3DXMatrixRotationY(&matRotate, 0);
D3DXMatrixTranslation(&matTranslate, mPosition->x, mPosition->y, mPosition->z);
matWorldTransform = matScale * matRotate * matTranslate;
d3dDevice->SetTransform(D3DTS_WORLD, &matWorldTransform);
d3dDevice->SetFVF(CUSTOMFVF);
d3dDevice->SetStreamSource(0, vertexBuffer, 0, sizeof(CUSTOMVERTEX));
d3dDevice->SetIndices(indexBuffer);
d3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, vertexCount, 0, indexCount/3);
}
where vertexBuffer and indexBuffer with with their counts are attributes of the class.
Here are some screenshots (FU, spam protection):
1) http://img822.imageshack.us/img822/1705/dx2010080913182262.jpg this is the situation
2) http://img691.imageshack.us/img691/7358/dx2010080913183790.jpg this is the (correct) view when the cube is in front (the cube is drawn later)
3) http://img340.imageshack.us/img340/4720/dx2010080913184509.jpg But when I have the truncated pyramid in front, the cube still overlaps
it's easier to see when you move the camera yourself...
Now that's a gotcha. The problem was me setting the near view plane to 0.0f - when I changed it to something like 0.001f, the z-buffer suddenly started to work.