I am creating an iPhone app using OpenGL ES 2, and it uses both objective-c and c++. In it there is a header file for defining some vector properties, and this file includes cmath which then causes the error.
Somebody suggested changing main.m to main.mm but this causes symbols not found for architecture errors(65 of them). However it does get rid of the cmath error. I have tried fiddling with which code type various files are compiled as but this does not help. Also, if I don't include Vector.h in my rendering engine then the cmath error goes away, but makes more errors.
This has happen on two projects now, that are of the same form.
Vector.h
#ifndef Robots_Vector_h
#define Robots_Vector_h
#include <cmath>
const float Pi = 4 * std::atan(1.0f);
const float TwoPi = 2 * Pi;
template <typename T>
struct Vector2 {
Vector2() {}
Vector2(T x, T y) : x(x), y(y) {}
T Dot(const Vector2& v) const
{
return x * v.x + y * v.y;
}
Vector2 operator+(const Vector2& v) const
{
return Vector2(x + v.x, y + v.y);
}
Vector2 operator-(const Vector2& v) const
{
return Vector2(x - v.x, y - v.y);
}
void operator+=(const Vector2& v)
{
*this = Vector2(x + v.x, y + v.y);
}
void operator-=(const Vector2& v)
{
*this = Vector2(x - v.x, y - v.y);
}
Vector2 operator/(float s) const
{
return Vector2(x / s, y / s);
}
Vector2 operator*(float s) const
{
return Vector2(x * s, y * s);
}
void operator/=(float s)
{
*this = Vector2(x / s, y / s);
}
void operator*=(float s)
{
*this = Vector2(x * s, y * s);
}
void Normalize()
{
float s = 1.0f / Length();
x *= s;
y *= s;
}
Vector2 Normalized() const
{
Vector2 v = *this;
v.Normalize();
return v;
}
T LengthSquared() const
{
return x * x + y * y;
}
T Length() const
{
return sqrt(LengthSquared());
}
const T* Pointer() const
{
return &x;
}
operator Vector2<float>() const
{
return Vector2<float>(x, y);
}
bool operator==(const Vector2& v) const
{
return x == v.x && y == v.y;
}
Vector2 Lerp(float t, const Vector2& v) const
{
return Vector2(x * (1 - t) + v.x * t,
y * (1 - t) + v.y * t);
}
template <typename P>
P* Write(P* pData)
{
Vector2* pVector = (Vector2*) pData;
*pVector++ = *this;
return (P*) pVector;
}
T x;
T y;
};
template <typename T>
struct Vector3 {
Vector3() {}
Vector3(T x, T y, T z) : x(x), y(y), z(z) {}
T Length()
{
return std::sqrt(x * x + y * y + z * z);
}
Vector3 Cross(const Vector3& v) const
{
return Vector3(y * v.z - z * v.y,
z * v.x - x * v.z,
x * v.y - y * v.x);
}
T Dot(const Vector3& v) const
{
return x * v.x + y * v.y + z * v.z;
}
Vector3 operator+(const Vector3& v) const
{
return Vector3(x + v.x, y + v.y, z + v.z);
}
void operator+=(const Vector3& v)
{
x += v.x;
y += v.y;
z += v.z;
}
void operator-=(const Vector3& v)
{
x -= v.x;
y -= v.y;
z -= v.z;
}
void operator/=(T s)
{
x /= s;
y /= s;
z /= s;
}
Vector3 operator-(const Vector3& v) const
{
return Vector3(x - v.x, y - v.y, z - v.z);
}
Vector3 operator-() const
{
return Vector3(-x, -y, -z);
}
Vector3 operator*(T s) const
{
return Vector3(x * s, y * s, z * s);
}
Vector3 operator/(T s) const
{
return Vector3(x / s, y / s, z / s);
}
bool operator==(const Vector3& v) const
{
return x == v.x && y == v.y && z == v.z;
}
Vector3 Lerp(float t, const Vector3& v) const
{
return Vector3(x * (1 - t) + v.x * t,
y * (1 - t) + v.y * t,
z * (1 - t) + v.z * t);
}
const T* Pointer() const
{
return &x;
}
void Normalize()
{
if (this->Dot(*this) != 0) {
float s = 1.0f / Length();
x *= s;
y *= s;
z *= s;
}
}
/*Vector3 operator=(const Vector3& v) {
x = v.x;
y = v.y;
z = v.z;
return v;
}*/
Vector3 Normalized() const
{
Vector3 v = *this;
v.Normalize();
return v;
}
template <typename P>
P* Write(P* pData)
{
Vector3<T>* pVector = (Vector3<T>*) pData;
*pVector++ = *this;
return (P*) pVector;
}
T x;
T y;
T z;
};
template <typename T>
struct Vector4 {
Vector4() {}
Vector4(T xarg, T yarg, T zarg, T warg) : x(xarg), y(yarg), z(zarg), w(warg) {}
Vector4(const Vector3<T>& v, T w) : x(v.x), y(v.y), z(v.z), w(w) {}
T Dot(const Vector4& v) const
{
return x * v.x + y * v.y + z * v.z + w * v.w;
}
Vector4 Lerp(float t, const Vector4& v) const
{
return Vector4(x * (1 - t) + v.x * t,
y * (1 - t) + v.y * t,
z * (1 - t) + v.z * t,
w * (1 - t) + v.w * t);
}
void operator+=(const Vector4& v) {
x += v.x;
y += v.y;
z += v.z;
w += v.w;
}
Vector4 operator*(T s) {
return Vector4(x*s, y*s, z*s, w*s);
}
const T* Pointer() const
{
return &x;
}
T x;
T y;
T z;
T w;
};
typedef Vector2<bool> bvec2;
typedef Vector2<int> ivec2;
typedef Vector3<int> ivec3;
typedef Vector4<int> ivec4;
typedef Vector2<float> vec2;
typedef Vector3<float> vec3;
typedef Vector4<float> vec4;
#endif
RenderingEngineES2.cpp
//
// RenderingEngineES2.cpp
// Robots
//
// Created by James Thorneycroft on 01/07/2015.
// Copyright (c) 2015 James Thorneycroft. All rights reserved.
//
#include <stdio.h>
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#include "Interfaces.h"
#include "Matrix.h"
#include <iostream>
namespace ES2 {
#define STRINGIFY(A) #A
//#include "../Shaders/Simple.frag"
//#include "../Shaders/SimpleLighting.vert"
#include "../PixelLighting.vert"
#include "../Shaders/PixelLighting.frag"
struct UniformHandles {
GLuint Modelview;
GLuint Projection;
GLuint NormalMatrix;
GLuint LightPosition;
GLuint CameraAxis;
};
struct AttributeHandle {
GLint Position;
GLint Normal;
GLint Ambient;
GLint Diffuse;
GLint Specular;
GLint Shininess;
};
struct Drawable {
GLuint VertexBuffer;
GLuint IndexBuffer;
int IndexCount;
};
class RenderingEngine : public IRenderingEngine {
public:
RenderingEngine();
void Initialize(const vector<ISurface*>& surfaces);
void Render(const vector<Visual>& visuals) const;
private:
GLuint BuildProgram(const char* vertexShaderSource, const char* fragmentShaderSource) const;
GLuint BuildShader(const char* source, GLenum shaderType) const;
vector<Drawable> m_drawables;
GLuint m_depthRenderBuffer;
GLuint m_colorRenderBuffer;
UniformHandles m_uniforms;
AttributeHandle m_attributes;
};
IRenderingEngine* CreateRenderingEngine() {
return new RenderingEngine();
}
GLuint RenderingEngine::BuildShader(const char* source, GLenum shaderType) const
{
GLuint shaderHandle = glCreateShader(shaderType);
glShaderSource(shaderHandle, 1, &source, 0);
glCompileShader(shaderHandle);
GLint compileSuccess;
glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
if (compileSuccess == GL_FALSE) {
GLchar messages[256];
glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]);
std::cout << messages;
exit(1);
}
return shaderHandle;
}
GLuint RenderingEngine::BuildProgram(const char* vertexShaderSource,
const char* fragmentShaderSource) const
{
GLuint vertexShader = BuildShader(vertexShaderSource, GL_VERTEX_SHADER);
GLuint fragmentShader = BuildShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
GLuint programHandle = glCreateProgram();
glAttachShader(programHandle, vertexShader);
glAttachShader(programHandle, fragmentShader);
glLinkProgram(programHandle);
GLint linkSuccess;
glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
if (linkSuccess == GL_FALSE) {
GLchar messages[256];
glGetProgramInfoLog(programHandle, sizeof(messages), 0, &messages[0]);
std::cout << messages;
exit(1);
}
return programHandle;
}
RenderingEngine::RenderingEngine() {
glGenRenderbuffers(1, &m_colorRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, m_colorRenderBuffer);
}
void RenderingEngine::Initialize(const vector<ISurface *> &surfaces) {
m_cameraPosition = vec4(0,0,0,0);
vector<ISurface*>::const_iterator surface;
for (surface = surfaces.begin(); surface != surfaces.end(); ++surface) {
vector<float> vertices;
(*surface)->GenerateVertices(vertices, VertexFlagNormals);
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(vertices[0]), &vertices[0], GL_STATIC_DRAW);
int indexCount = (*surface)->GetTriangleIndexCount();
GLuint indexBuffer;
if (!m_drawables.empty() && indexCount == m_drawables[0].IndexCount) {
indexBuffer = m_drawables[0].IndexBuffer;
} else {
vector<GLushort> indices(indexCount);
(*surface)->GenerateTriangleIndices(indices);
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(GLushort), &indices[0], GL_STATIC_DRAW);
}
Drawable drawable = { vertexBuffer, indexBuffer, indexCount };
m_drawables.push_back(drawable);
}
int height, width;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
glGenRenderbuffers(1, &m_depthRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, m_depthRenderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorRenderBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, m_colorRenderBuffer);
GLuint program = BuildProgram(PixelLightingVertexShader, PixelLightingFragmentShader);
glUseProgram(program);
m_attributes.Position = glGetAttribLocation(program, "Position");
m_attributes.Normal = glGetAttribLocation(program, "Normal");
m_attributes.Ambient = glGetUniformLocation(program, "AmbientMaterial");
m_attributes.Diffuse = glGetAttribLocation(program, "DiffuseMaterial");
m_attributes.Specular = glGetUniformLocation(program, "SpecularMaterial");
m_attributes.Shininess = glGetUniformLocation(program, "Shininess");
m_uniforms.Projection = glGetUniformLocation(program, "Projection");
m_uniforms.Modelview = glGetUniformLocation(program, "Modelview");
m_uniforms.NormalMatrix = glGetUniformLocation(program, "NormalMatrix");
m_uniforms.LightPosition = glGetUniformLocation(program, "LightPosition");
m_uniforms.CameraAxis = glGetUniformLocation(program, "CameraAxis");
glUniform3f(m_attributes.Ambient, 0.15f, 0.15f, 0.15f);
glUniform3f(m_attributes.Specular, 0.15f, 0.15f, 0.15f);
glUniform1f(m_attributes.Shininess, 100.0f);
glEnableVertexAttribArray(m_attributes.Position);
glEnableVertexAttribArray(m_attributes.Normal);
glEnable(GL_DEPTH_TEST);
//m_cameraOrientation.Identity();
}
void RenderingEngine::Render(const vector<Visual> &visuals) const {
glClearColor(0, 0.3f, 0.6f, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
vector<Visual>::const_iterator visual = visuals.begin();
for (int visualIndex = 0; visual != visuals.end(); ++visual, ++visualIndex) {
ivec2 size = visual->ViewportSize;
ivec2 lowerLeft = visual->LowerLeft;
glViewport(lowerLeft.x, lowerLeft.y, size.x, size.y);
mat4 rotation = visual->Orientation.ToMatrix4();
mat4 modelView = m_cameraOrientation.ToMatrix4() * mat4::Translate(vec3(m_cameraPosition.x,m_cameraPosition.y,m_cameraPosition.z-100)) * rotation * Quaternion::CreateFromAxisAngle(vec3(-1,0,0), 1.2f).ToMatrix4();
glUniformMatrix4fv(m_uniforms.Modelview, 1, 0, modelView.Pointer());
vec3 camAx = m_cameraOrientation.ToMatrix3() * visual->Orientation.ToMatrix3() * Quaternion::CreateFromAxisAngle(vec3(-1,0,0), 1.2f).ToMatrix3() * vec3(0,0,1);
glUniform3f(m_uniforms.CameraAxis, camAx.x, camAx.y, camAx.z);
vec4 lightPosition(0, 0, 1, 0);
glUniform3fv(m_uniforms.LightPosition, 1, (modelView*lightPosition).Pointer());
mat3 normalMatrix = modelView.ToMat3();
glUniformMatrix3fv(m_uniforms.NormalMatrix, 1, 0, normalMatrix.Pointer());
float h = 4.0f * size.y / size.x;
mat4 projectionMatrix = mat4::Frustum(-2, 2, -h / 2, h / 2, 5, 1000);
glUniformMatrix4fv(m_uniforms.Projection, 1, 0, projectionMatrix.Pointer());
vec3 color = visual->Color * 0.75f;
glVertexAttrib4f(m_attributes.Diffuse, color.x, color.y, color.z, 1);
int stride = 2*sizeof(vec3);
const GLvoid* offset = (const GLvoid*) sizeof(vec3);
GLint position = m_attributes.Position;
GLint normal = m_attributes.Normal;
const Drawable& drawable = m_drawables[visualIndex];
glBindBuffer(GL_ARRAY_BUFFER, drawable.VertexBuffer);
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, stride, 0);
glVertexAttribPointer(normal, 3, GL_FLOAT, GL_FALSE, stride, offset);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, drawable.IndexBuffer);
glDrawElements(GL_TRIANGLES, drawable.IndexCount, GL_UNSIGNED_SHORT, 0);
}
}
}