我创建使用OpenGL ES 2.0的iPhone应用程序,它同时使用Objective-C和C ++。在它有用于限定一些矢量特性的头文件,并且该文件包括CMATH然后导致错误。
有人建议将main.m文件到main.mm但这会导致没有发现建筑的错误(其中65)符号。但是,它会摆脱CMATH错误的。我曾尝试与代码类型的各种文件编译为摆弄但这并没有帮助。另外,如果我没有在我的渲染引擎包括Vector.h那么CMATH错误消失,反而使得更多的错误。
这有发生在现在两个项目,这是相同的形式。
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);
}
}
}
代替
#include <cmath>
采用
#include <math.h>
这里的问题是,Objective-C的工作基于C API之上,并且<cmath>
不可用C - <cmath>
是一个C ++包括与C相当于是<math.h>
(如@MrTweek pointed out)。
解决的办法是切换到使用Objective-C ++,它适用于C ++的顶部,让您可以访问所有的C在你的OBJ-C类的功能++,以及让您导入C ++头文件(比如你的)。
切换您的Objective-C代码的Objective-C ++是trivial-只是重命名具有所需#include "Vector.h"
有.mm
延伸,而不是.m
_任何Objective-C的实现文件(如MyRendererView.m
更名为MyRendererView.mm
; MyRendererView.h
可以保持原样) 。而已!所有现有的Objective-C代码将能够使用的Objective-C ++类毫不费力;你只需要改变的Objective-C的文件扩展名包括您Vector.h
或将C ++类型他们自己的头。
使用Objective-C ++而不是Objective-C中,它已经太长了我记得有几个小的命名注意事项。如果碰到任何奇怪的错误,这是几乎可以肯定的StackOverflow的答案解决它。它可能会回落到调整一个Xcode构建设置 - 最重要的构建设置在偷看是“C语言方言”和“C ++语言方言”设置。