2012-07-26 46 views
1

最近我在看一本名爲的書iPhone 3D 3D編程。在它的例子之後,我發現了一個非常令人困惑的問題,即我的代碼與「klein bottle」有「光照不當」(或者它有一個正式名稱)。單面歧管的正常不匹配

左是正確的照明(從本書的源代碼)。 正確的是我的版本。 下面是這個例子和我的區別。

diff --git a/Classes/ApplicationEngine.cpp b/Classes/ApplicationEngine.cpp 
index c3ddd05..68f8b36 100644 
--- a/Classes/ApplicationEngine.cpp 
+++ b/Classes/ApplicationEngine.cpp 
@@ -11,8 +11,6 @@ 
#include <algorithm> 

using namespace std; 
-namespace ParametricViewer { 
- 

static const int Surface_Count = 6; 
static const int Button_Count = Surface_Count - 1; 
@@ -54,7 +52,7 @@ private: 
    Animation _animation; 
}; 

-IApplicationEngine* CreateApplicationEngine(IRenderingEngine* renderingEngine) { 
+IApplicationEngine* createApplicationEngine(IRenderingEngine* renderingEngine) { 
    return new ApplicationEngine(renderingEngine); 
} 

@@ -211,4 +209,3 @@ int ApplicationEngine::mapToButton(ivec2 touchpint) const { 
    return buttonIndex; 
} 

-} 
\ No newline at end of file 
diff --git a/Classes/GLView.mm b/Classes/GLView.mm 
index 0eeedf6..966041b 100644 
--- a/Classes/GLView.mm 
+++ b/Classes/GLView.mm 
@@ -35,10 +35,10 @@ const BOOL ForceES1 = YES; 
      m_renderingEngine = SolidES1::createRenderingEngine(); 
     } else { 
      NSLog(@"Using OpenGL ES 2.0"); 
-   m_renderingEngine = SolidES2::createRenderingEngine(); 
+   m_renderingEngine = ES2::createRenderingEngine(); 
     } 

-  m_applicationEngine = ParametricViewer::CreateApplicationEngine(m_renderingEngine); 
+  m_applicationEngine = createApplicationEngine(m_renderingEngine); 

     [m_context 
      renderbufferStorage:GL_RENDERBUFFER 
diff --git a/Classes/Interfaces.hpp b/Classes/Interfaces.hpp 
index 1f9b129..6bbf0d0 100644 
--- a/Classes/Interfaces.hpp 
+++ b/Classes/Interfaces.hpp 
@@ -58,9 +58,7 @@ namespace SolidES1 { 
    IRenderingEngine* createRenderingEngine(); 
} 

-namespace SolidES2 { 
+namespace ES2 { 
    IRenderingEngine* createRenderingEngine(); 
} 
- 
-namespace ParametricViewer { IApplicationEngine* CreateApplicationEngine(IRenderingEngine*); } 
#endif 
diff --git a/Classes/ParametricEquations.hpp b/Classes/ParametricEquations.hpp 
index f06a0a3..ec2942a 100644 
--- a/Classes/ParametricEquations.hpp 
+++ b/Classes/ParametricEquations.hpp 
@@ -4,7 +4,7 @@ class Cone : public ParametricSurface { 
public: 
    Cone(float height, float radius) : _height(height), _radius(radius) 
    { 
- ParametricInterval interval = { ivec2(20, 20), vec2(TwoPi, 1), vec2(30, 20) }; 
+ ParametricInterval interval = { ivec2(20, 20), vec2(TWO_PI, 1), vec2(30, 20) }; 
    setInterval(interval); 
    } 
    vec3 evaluate(const vec2& domain) const 
@@ -24,7 +24,7 @@ class Sphere : public ParametricSurface { 
public: 
    Sphere(float radius) : _radius(radius) 
    { 
- ParametricInterval interval = { ivec2(20, 20), vec2(Pi, TwoPi), vec2(20, 35) }; 
+ ParametricInterval interval = { ivec2(20, 20), vec2(PI, TWO_PI), vec2(20, 35) }; 
    setInterval(interval); 
    } 
    vec3 evaluate(const vec2& domain) const 
@@ -45,7 +45,7 @@ public: 
    _majorRadius(majorRadius), 
    _minorRadius(minorRadius) 
    { 
- ParametricInterval interval = { ivec2(20, 20), vec2(TwoPi, TwoPi), vec2(40, 10) }; 
+ ParametricInterval interval = { ivec2(20, 20), vec2(TWO_PI, TWO_PI), vec2(40, 10) }; 
    setInterval(interval); 
    } 
    vec3 evaluate(const vec2& domain) const 
@@ -67,7 +67,7 @@ class TrefoilKnot : public ParametricSurface { 
public: 
    TrefoilKnot(float scale) : _scale(scale) 
    { 
- ParametricInterval interval = { ivec2(60, 15), vec2(TwoPi, TwoPi), vec2(100, 8) }; 
+ ParametricInterval interval = { ivec2(60, 15), vec2(TWO_PI, TWO_PI), vec2(100, 8) }; 
    setInterval(interval); 
    } 
    vec3 evaluate(const vec2& domain) const 
@@ -76,7 +76,7 @@ public: 
    const float b = 0.3f; 
    const float c = 0.5f; 
    const float d = 0.1f; 
- float u = (TwoPi - domain.x) * 2; 
+ float u = (TWO_PI - domain.x) * 2; 
    float v = domain.y; 

    float r = a + b * cos(1.5f * u); 
@@ -109,7 +109,7 @@ class MobiusStrip : public ParametricSurface { 
public: 
    MobiusStrip(float scale) : _scale(scale) 
    { 
- ParametricInterval interval = { ivec2(40, 20), vec2(TwoPi, TwoPi), vec2(40, 15) }; 
+ ParametricInterval interval = { ivec2(40, 20), vec2(TWO_PI, TWO_PI), vec2(40, 15) }; 
    setInterval(interval); 
    } 
    vec3 evaluate(const vec2& domain) const 
@@ -141,7 +141,7 @@ class KleinBottle : public ParametricSurface { 
public: 
    KleinBottle(float scale) : _scale(scale) 
    { 
- ParametricInterval interval = { ivec2(20, 20), vec2(TwoPi, TwoPi), vec2(15, 50) }; 
+ ParametricInterval interval = { ivec2(20, 20), vec2(TWO_PI, TWO_PI), vec2(15, 50) }; 
    setInterval(interval); 
    } 
    vec3 evaluate(const vec2& domain) const 
@@ -155,19 +155,19 @@ public: 
    float y0 = 8 * sin(u) + (2 * (1 - cos(u)/2)) * sin(u) * cos(v); 

    float x1 = 3 * cos(u) * (1 + sin(u)) + 
- (2 * (1 - cos(u)/2)) * cos(v + Pi); 
+ (2 * (1 - cos(u)/2)) * cos(v + PI); 

    float y1 = 8 * sin(u); 

    vec3 range; 
- range.x = u < Pi ? x0 : x1; 
- range.y = u < Pi ? -y0 : -y1; 
+ range.x = u < PI ? x0 : x1; 
+ range.y = u < PI ? -y0 : -y1; 
    range.z = (-2 * (1 - cos(u)/2)) * sin(v); 
    return range * _scale; 
    } 
- bool invertNormal(const vec2& domain) const 
+ bool InvertNormal(const vec2& domain) const 
    { 
- return domain.y > 3 * Pi/2; 
+ return domain.y > 3 * PI/2; 
    } 
private: 
    float _scale; 
diff --git a/mathLib/Matrix.hpp b/mathLib/Matrix.hpp 
index 7b73954..fbbb2d4 100644 
--- a/mathLib/Matrix.hpp 
+++ b/mathLib/Matrix.hpp 
@@ -150,7 +150,7 @@ struct Matrix4 { 
    } 

    static Matrix4<T> rotate(T degrees) { 
- T radians = degrees * Pi/180.0f; 
+ T radians = degrees * PI/180.0f; 
    T s = std::sin(radians); 
    T c = std::cos(radians); 

@@ -161,7 +161,7 @@ struct Matrix4 { 
    } 

    static Matrix4<T> rotate(T degrees, const vec3& axis) { 
- T radians = degrees * Pi/180.0f; 
+ T radians = degrees * PI/180.0f; 
    T s = std::sin(radians); 
    T c = std::cos(radians); 

diff --git a/mathLib/Quaternion.hpp b/mathLib/Quaternion.hpp 
index d1a2a0b..e043760 100644 
--- a/mathLib/Quaternion.hpp 
+++ b/mathLib/Quaternion.hpp 
@@ -53,21 +53,21 @@ inline QuaternionT<T>::QuaternionT(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) 
template <typename T> 
inline QuaternionT<T> QuaternionT<T>:: slerp(T t, const QuaternionT<T>& v1) const { 
    const T epsilon = 0.0005f; 
- T DotT = dot(v1); 
+ T dotT = dot(v1); 

- if (DotT > 1 - epsilon) { 
+ if (dotT > 1 - epsilon) { 
    QuaternionT<T> result = v1 + (*this - v1).scaled(t); 
    result.normalize(); 
    return result; 
    } 

- if (DotT < 0) DotT = 0; 
- if (DotT > 1) DotT = 1; 
+ if (dotT < 0) dotT = 0; 
+ if (dotT > 1) dotT = 1; 

- T theta0 = std::acos(DotT); 
+ T theta0 = std::acos(dotT); 
    T theta = theta0 * t; 

- QuaternionT<T> v2 = (v1 - scaled(DotT)); 
+ QuaternionT<T> v2 = (v1 - scaled(dotT)); 
    v2.normalize(); 

    QuaternionT<T> q = scaled(std::cos(theta)) + v2.scaled(std::sin(theta)); 
@@ -139,12 +139,12 @@ bool QuaternionT<T>::operator != (const QuaternionT<T>& q) const { 
    return !(*this == q); 
} 

-// Compute the quaternion that Rotates from a to b, avoiding numerical instability. 
+// Compute the quaternion that rotates from a to b, avoiding numerical instability. 
// Taken from "The Shortest Arc Quaternion" by Stan Melax in "Game Programming Gems". 
template <typename T> 
inline QuaternionT<T> QuaternionT<T>::createFromVectors(const Vector3<T>& v0, const Vector3<T>& v1) { 
    if (v0 == -v1) 
- return QuaternionT<T>::createFromAxisAngle(vec3(1, 0, 0), Pi); 
+ return QuaternionT<T>::createFromAxisAngle(vec3(1, 0, 0), PI); 

    Vector3<T> c = v0.cross(v1); 
    T d = v0.dot(v1); 
@@ -187,7 +187,7 @@ inline void QuaternionT<T>::rotate(const QuaternionT<T>& q2) 
    q.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z; 
    q.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x; 

- q.Normalize(); 
+ q.normalize(); 
    *this = q; 
} 

diff --git a/mathLib/Vector.hpp b/mathLib/Vector.hpp 
index 781fc64..f43051e 100644 
--- a/mathLib/Vector.hpp 
+++ b/mathLib/Vector.hpp 
@@ -11,15 +11,15 @@ 

#include <cmath> 

-const float Pi = 4 * std::atan(1.0f); 
-const float TwoPi = 2 * Pi; 
+const float PI = 4 * std::atan(1.0f); 
+const float TWO_PI = 2 * PI; 

template <typename T> 
struct Vector2 { 
    Vector2() {} 
    Vector2(T x, T y) : x(x), y(y) {} 

- T Dot(const Vector2& v) const { 
+ T dot(const Vector2& v) const { 
    return x * v.x + y * v.y; 
    } 

代碼幾乎與字符大小寫相同。那麼我錯在哪裏? 錯誤的版本使用ES1.1 任何建議將明白。

Full source code

+0

哇,從來沒有見過差異文件作爲代碼示例,但是再次,一個是綽綽有餘。 – 2012-07-26 07:54:44

+0

@ChristianRau因爲我複製了書中的代碼,但結果不同,所以我發佈了一個diff文件以尋求幫助。 – Pikaurd 2012-07-26 13:49:02

+0

我的頭頂上,你的問題的一個好名字可能是「正常不匹配」,或「方向問題」。 – comingstorm 2012-07-27 00:03:33

回答

0

與克萊因瓶的問題是它不是orientable:它是一個片面歧管,所以這是不可能在整個表面保持一致的正常。無論您如何選擇網格上的法線,總會有一條線從正常的一側翻轉到另一側。

它看起來像原來的(金)克萊因瓶可能已經調整,所以方向不匹配就在瓶子的「口」內,隱藏缺陷而不是固定它。請注意,在您的(灰色)版本中,您可以正確地在嘴內看到表面;在金瓶中,它顯得黑色。從你的差異,我猜他們可能已經調整了InvertNormal()函數的條件。 (不,差異不顯示任何調整 - 但它聽起來像調整的邏輯地點...)

使您的克萊恩瓶無縫最簡單的方法是做一個雙重封面:每個三角形出現兩次,面對相反的方向。這可能比簡單地製作三角形更加複雜 - 關鍵是每個也必須出現兩次,指向相反的方向。最方便的方法是複製頂點,併爲相對(單面)三角形使用不同的頂點集。 (我沒有仔細看過你的代碼,但是要做雙覆蓋的事情,你可能需要擴展你的參數化循環的一個因子2,並可能做一些事情,如區分積極的和負的四元數,不要忘了讓所得的三角形單面。)

+0

我有一個'invertNormal()'在超類和子類中使用'InvertNormal()'...我第一次聽說'可定向'你能推薦任何書嗎?非常感謝你。 – Pikaurd 2012-07-27 02:31:08

+0

對不起,我不知道一本關於拓撲的好書。我建議你使用谷歌關鍵詞,如「可定向」,「多樣」,「單面」,「克萊因瓶」和「莫比烏斯帶」。 – comingstorm 2012-07-27 17:38:10