浏览代码

Reflection plane support in Camera. Reflection plane clipping not yet implemented.

Lasse Öörni 12 年之前
父节点
当前提交
3553b287ac

+ 10 - 7
Source/Engine/Graphics/Batch.cpp

@@ -214,10 +214,10 @@ void Batch::Prepare(View* view, bool setModelTransform) const
     unsigned cameraHash = overrideView_ ? (unsigned)(size_t)camera_ + 4 : (unsigned)(size_t)camera_;
     if (graphics->NeedParameterUpdate(SP_CAMERA, reinterpret_cast<void*>(cameraHash)))
     {
-        Matrix3 cameraWorldRotation = cameraNode->GetWorldRotation().RotationMatrix();
+        Matrix3x4 cameraEffectiveTransform = camera_->GetEffectiveWorldTransform();
         
-        graphics->SetShaderParameter(VSP_CAMERAPOS, cameraNode->GetWorldPosition());
-        graphics->SetShaderParameter(VSP_CAMERAROT, cameraWorldRotation);
+        graphics->SetShaderParameter(VSP_CAMERAPOS, cameraEffectiveTransform.Translation());
+        graphics->SetShaderParameter(VSP_CAMERAROT, cameraEffectiveTransform.RotationMatrix());
         Vector4 depthMode = Vector4::ZERO;
         if (camera_->IsOrthographic())
         {
@@ -399,6 +399,9 @@ void Batch::Prepare(View* view, bool setModelTransform) const
     
     if (light && graphics->NeedParameterUpdate(SP_LIGHT, light))
     {
+        Matrix3x4 cameraEffectiveTransform = camera_->GetEffectiveWorldTransform();
+        Vector3 cameraEffectivePos = cameraEffectiveTransform.Translation();
+
         Node* lightNode = light->GetNode();
         Matrix3 lightWorldRotation = lightNode->GetWorldRotation().RotationMatrix();
         
@@ -460,7 +463,7 @@ void Batch::Prepare(View* view, bool setModelTransform) const
         
         graphics->SetShaderParameter(PSP_LIGHTCOLOR, Color(light->GetColor(), light->GetSpecularIntensity()) * fade);
         graphics->SetShaderParameter(PSP_LIGHTDIR, lightWorldRotation * Vector3::BACK);
-        graphics->SetShaderParameter(PSP_LIGHTPOS, Vector4(lightNode->GetWorldPosition() - cameraNode->GetWorldPosition(), atten));
+        graphics->SetShaderParameter(PSP_LIGHTPOS, Vector4(lightNode->GetWorldPosition() - cameraEffectivePos, atten));
         
         if (graphics->HasShaderParameter(PS, PSP_LIGHTMATRICES))
         {
@@ -471,7 +474,7 @@ void Batch::Prepare(View* view, bool setModelTransform) const
                     Matrix4 shadowMatrices[MAX_CASCADE_SPLITS];
                     unsigned numSplits = lightQueue_->shadowSplits_.Size();
                     for (unsigned i = 0; i < numSplits; ++i)
-                        CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer, cameraNode->GetWorldPosition());
+                        CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer, cameraEffectivePos);
                     
                     graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits);
                 }
@@ -481,10 +484,10 @@ void Batch::Prepare(View* view, bool setModelTransform) const
                 {
                     Matrix4 shadowMatrices[2];
                     
-                    CalculateSpotMatrix(shadowMatrices[0], light, cameraNode->GetWorldPosition());
+                    CalculateSpotMatrix(shadowMatrices[0], light, cameraEffectivePos);
                     bool isShadowed = lightQueue_->shadowMap_ != 0;
                     if (isShadowed)
-                        CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer, cameraNode->GetWorldPosition());
+                        CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer, cameraEffectivePos);
                     
                     graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), isShadowed ? 32 : 16);
                 }

+ 48 - 5
Source/Engine/Graphics/Camera.cpp

@@ -70,9 +70,12 @@ Camera::Camera(Context* context) :
     viewOverrideFlags_(VO_NONE),
     fillMode_(FILL_SOLID),
     projectionOffset_(Vector2::ZERO),
+    reflectionPlane_(Plane::UP),
     autoAspectRatio_(true),
-    flipVertical_(false)
+    flipVertical_(false),
+    useReflection_(false)
 {
+    reflectionMatrix_ = reflectionPlane_.ReflectionMatrix();
 }
 
 Camera::~Camera()
@@ -97,6 +100,8 @@ void Camera::RegisterObject(Context* context)
     ATTRIBUTE(Camera, VAR_INT, "View Mask", viewMask_, DEFAULT_VIEWMASK, AM_DEFAULT);
     ATTRIBUTE(Camera, VAR_INT, "View Override Flags", viewOverrideFlags_, VO_NONE, AM_DEFAULT);
     REF_ACCESSOR_ATTRIBUTE(Camera, VAR_VECTOR2, "Projection Offset", GetProjectionOffset, SetProjectionOffset, Vector2, Vector2::ZERO, AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(Camera, VAR_VECTOR4, "Reflection Plane", GetReflectionPlaneAttr, SetReflectionPlaneAttr, Vector4, Vector4(0.0f, 1.0f, 0.0f, 0.0f), AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(Camera, VAR_BOOL, "Use Reflection", GetUseReflection, SetUseReflection, bool, false, AM_DEFAULT);
 }
 
 void Camera::SetNearClip(float nearClip)
@@ -202,6 +207,23 @@ void Camera::SetProjectionOffset(const Vector2& offset)
     MarkNetworkUpdate();
 }
 
+void Camera::SetUseReflection(bool enable)
+{
+    useReflection_ = enable;
+    viewDirty_ = true;
+    frustumDirty_ = true;
+    MarkNetworkUpdate();
+}
+
+void Camera::SetReflectionPlane(const Plane& reflectionPlane)
+{
+    reflectionPlane_ = reflectionPlane;
+    reflectionMatrix_ = reflectionPlane_.ReflectionMatrix();
+    viewDirty_ = true;
+    frustumDirty_ = true;
+    MarkNetworkUpdate();
+}
+
 void Camera::SetFlipVertical(bool enable)
 {
     flipVertical_ = enable;
@@ -222,8 +244,8 @@ float Camera::GetNearClip() const
 Frustum Camera::GetSplitFrustum(float nearClip, float farClip) const
 {
     Frustum ret;
-
-    const Matrix3x4& worldTransform = node_ ? node_->GetWorldTransform() : Matrix3x4::IDENTITY;
+    
+    Matrix3x4 worldTransform = GetEffectiveWorldTransform();
     nearClip = Max(nearClip, GetNearClip());
     farClip = Min(farClip, farClip_);
     if (farClip < nearClip)
@@ -323,7 +345,8 @@ const Frustum& Camera::GetFrustum() const
 {
     if (frustumDirty_)
     {
-        const Matrix3x4& worldTransform = node_ ? node_->GetWorldTransform() : Matrix3x4::IDENTITY;
+        Matrix3x4 worldTransform = GetEffectiveWorldTransform();
+        
         if (!orthographic_)
             frustum_.Define(fov_, aspectRatio_, zoom_, GetNearClip(), farClip_, worldTransform);
         else
@@ -503,6 +526,12 @@ float Camera::GetLodDistance(float distance, float scale, float bias) const
         return orthoSize_ / d;
 }
 
+Matrix3x4 Camera::GetEffectiveWorldTransform() const
+{
+    Matrix3x4 worldTransform = node_ ? Matrix3x4(node_->GetWorldPosition(), node_->GetWorldRotation(), 1.0f) : Matrix3x4::IDENTITY;
+    return useReflection_ ? reflectionMatrix_ * worldTransform : worldTransform;
+}
+
 bool Camera::IsProjectionValid() const
 {
     return farClip_ > GetNearClip();
@@ -513,13 +542,27 @@ const Matrix3x4& Camera::GetView() const
     if (viewDirty_)
     {
         // Note: view matrix is unaffected by node or parent scale
-        view_ = node_ ? Matrix3x4(node_->GetWorldPosition(), node_->GetWorldRotation(), 1.0f).Inverse() : Matrix3x4::IDENTITY;
+        view_ = GetEffectiveWorldTransform().Inverse();
         viewDirty_ = false;
     }
     
     return view_;
 }
 
+void Camera::SetReflectionPlaneAttr(Vector4 value)
+{
+    Plane plane;
+    plane.normal_ = Vector3(value.x_, value.y_, value.z_).Normalized();
+    plane.absNormal_ = plane.normal_.Abs();
+    plane.intercept_ = value.w_;
+    SetReflectionPlane(plane);
+}
+
+Vector4 Camera::GetReflectionPlaneAttr() const
+{
+    return Vector4(reflectionPlane_.normal_, reflectionPlane_.intercept_);
+}
+
 void Camera::OnNodeSet(Node* node)
 {
     if (node)

+ 24 - 0
Source/Engine/Graphics/Camera.h

@@ -76,6 +76,10 @@ public:
     void SetAutoAspectRatio(bool enable);
     /// Set projection offset. It needs to be calculated as (offset in pixels) / (viewport dimensions.)
     void SetProjectionOffset(const Vector2& offset);
+    /// Set reflection mode. The reflection plane is specified in world space.
+    void SetUseReflection(bool enable);
+    /// Set reflection plane in world space for reflection mode.
+    void SetReflectionPlane(const Plane& reflectionPlane);
     /// Set vertical flipping mode. Called internally by View to resolve OpenGL / Direct3D9 rendertarget sampling differences.
     void SetFlipVertical(bool enable);
     
@@ -135,17 +139,30 @@ public:
     Vector3 GetUpVector() const;
     /// Return projection offset.
     const Vector2& GetProjectionOffset() const { return projectionOffset_; }
+    /// Return whether is using reflection.
+    bool GetUseReflection() const { return useReflection_; }
+    /// Return the reflection plane.
+    const Plane& GetReflectionPlane() const { return reflectionPlane_; }
     /// Return vertical flipping mode.
     bool GetFlipVertical() const { return flipVertical_; }
+    /// Return whether to reverse culling; affected by vertical flipping and reflection.
+    bool GetReverseCulling() const { return flipVertical_ ^ useReflection_; }
     /// Return distance to position. In orthographic mode uses only Z coordinate.
     float GetDistance(const Vector3& worldPos) const;
     /// Return squared distance to position. In orthographic mode uses only Z coordinate.
     float GetDistanceSquared(const Vector3& worldPos) const;
     /// Return a scene node's LOD scaled distance.
     float GetLodDistance(float distance, float scale, float bias) const;
+    /// Get effective world transform for matrix and frustum calculations including reflection but excluding node scaling.
+    Matrix3x4 GetEffectiveWorldTransform() const;
     /// Return if projection parameters are valid for rendering and raycasting.
     bool IsProjectionValid() const;
     
+    /// Set reflection plane attribute.
+    void SetReflectionPlaneAttr(Vector4 value);
+    /// Return reflection plane attribute.
+    Vector4 GetReflectionPlaneAttr() const;
+
 protected:
     /// Handle node being assigned.
     virtual void OnNodeSet(Node* node);
@@ -153,6 +170,7 @@ protected:
     virtual void OnMarkedDirty(Node* node);
     
 private:
+
     /// Cached view matrix.
     mutable Matrix3x4 view_;
     /// Cached projection matrix.
@@ -189,10 +207,16 @@ private:
     FillMode fillMode_;
     /// Projection offset.
     Vector2 projectionOffset_;
+    /// Reflection plane.
+    Plane reflectionPlane_;
+    /// Reflection matrix calculated from the plane.
+    Matrix3x4 reflectionMatrix_;
     /// Auto aspect ratio flag.
     bool autoAspectRatio_;
     /// Flip vertical flag.
     bool flipVertical_;
+    /// Reflection mode enabled flag.
+    bool useReflection_;
 };
 
 }

+ 9 - 0
Source/Engine/Graphics/OcclusionBuffer.cpp

@@ -48,6 +48,7 @@ OcclusionBuffer::OcclusionBuffer(Context* context) :
     maxTriangles_(OCCLUSION_DEFAULT_MAX_TRIANGLES),
     cullMode_(CULL_CCW),
     depthHierarchyDirty_(true),
+    reverseCulling_(false),
     nearClip_(0.0f),
     farClip_(0.0f)
 {
@@ -112,6 +113,7 @@ void OcclusionBuffer::SetView(Camera* camera)
     viewProj_ = projection_ * view_;
     nearClip_ = camera->GetNearClip();
     farClip_ = camera->GetFarClip();
+    reverseCulling_ = camera->GetReverseCulling();
     CalculateViewport();
 }
 
@@ -122,6 +124,13 @@ void OcclusionBuffer::SetMaxTriangles(unsigned triangles)
 
 void OcclusionBuffer::SetCullMode(CullMode mode)
 {
+    if (reverseCulling_)
+    {
+        if (mode == CULL_CW)
+            mode = CULL_CCW;
+        else if (mode == CULL_CCW)
+            mode = CULL_CW;
+    }
     cullMode_ = mode;
 }
 

+ 2 - 0
Source/Engine/Graphics/OcclusionBuffer.h

@@ -140,6 +140,8 @@ private:
     CullMode cullMode_;
     /// Depth hierarchy needs update flag.
     bool depthHierarchyDirty_;
+    /// Culling reverse flag.
+    bool reverseCulling_;
     /// View transform matrix.
     Matrix3x4 view_;
     /// Projection matrix.

+ 2 - 2
Source/Engine/Graphics/Renderer.cpp

@@ -1257,8 +1257,8 @@ void Renderer::SetLightVolumeBatchShaders(Batch& batch, PODVector<ShaderVariatio
 
 void Renderer::SetCullMode(CullMode mode, Camera* camera)
 {
-    // If a camera is specified, check for vertical flipping and reverse culling in that case
-    if (camera && camera->GetFlipVertical())
+    // If a camera is specified, check whether it reverses culling due to vertical flipping or reflection
+    if (camera && camera->GetReverseCulling())
     {
         if (mode == CULL_CW)
             mode = CULL_CCW;

+ 4 - 5
Source/Engine/Graphics/Skybox.cpp

@@ -66,16 +66,15 @@ void Skybox::UpdateBatches(const FrameInfo& frame)
         lastFrame_ = frame.frameNumber_;
     }
 
-    // Follow only the camera rotation, not position
-    Matrix3x4 customView(Vector3::ZERO, frame.camera_->GetNode()->GetWorldRotation().Inverse(), Vector3::ONE);
-    HashMap<Camera*, Matrix3x4>::Iterator it = customWorldTransforms_.Insert(MakePair(frame.camera_, customView *
-        node_->GetWorldTransform()));
+    // Add camera position to fix the skybox in space. Use effective world transform to take reflection into account
+    Matrix3x4 customWorldTransform = node_->GetWorldTransform();
+    customWorldTransform.SetTranslation(node_->GetWorldPosition() + frame.camera_->GetEffectiveWorldTransform().Translation());
+    HashMap<Camera*, Matrix3x4>::Iterator it = customWorldTransforms_.Insert(MakePair(frame.camera_, customWorldTransform));
 
     for (unsigned i = 0; i < batches_.Size(); ++i)
     {
         batches_[i].worldTransform_ = &it->second_;
         batches_[i].distance_ = 0.0f;
-        batches_[i].overrideView_ = true;
     }
 }
 

+ 9 - 1
Source/Engine/LuaScript/pkgs/Graphics/Camera.pkg

@@ -23,6 +23,8 @@ class Camera : public Component
     void SetOrthographic(bool enable);
     void SetAutoAspectRatio(bool enable);
     void SetProjectionOffset(const Vector2& offset);
+    void SetUseReflection(bool enable);
+    void SetReflectionPlane(const Plane& reflectionPlane);
 
     float GetFarClip() const;
     float GetNearClip() const;
@@ -38,7 +40,6 @@ class Camera : public Component
     bool GetAutoAspectRatio() const;
     const Frustum& GetFrustum() const;
     const Matrix4& GetProjection() const;
-    Matrix4 GetProjection(bool apiSpecific) const;
     const Matrix3x4& GetView() const;
     void GetFrustumSize(Vector3& near, Vector3& far) const;
     float GetHalfViewSize() const;
@@ -52,10 +53,14 @@ class Camera : public Component
     Vector3 GetRightVector() const;
     Vector3 GetUpVector() const;
     const Vector2& GetProjectionOffset() const;
+    bool GetUseReflection() const;
+    const Plane& GetReflectionPlane() const;
+
     float GetDistance(const Vector3& worldPos) const;
     float GetDistanceSquared(const Vector3& worldPos) const;
     float GetLodDistance(float distance, float scale, float bias) const;
     bool IsProjectionValid() const;
+    Matrix3x4 GetEffectiveWorldTransform() const;
     
     tolua_property__get_set float farClip;
     tolua_property__get_set float nearClip;
@@ -78,6 +83,9 @@ class Camera : public Component
     tolua_readonly tolua_property__get_set Vector3 rightVector;
     tolua_readonly tolua_property__get_set Vector3 upVector;
     tolua_property__get_set Vector2& projectionOffset;
+    tolua_property__get_set bool useReflection;
+    tolua_property__get_set Plane& reflectionPlane;
     tolua_readonly tolua_property__is_set bool projectionValid;
+    tolua_readonly tolua_property__get_set Matrix3x4 effectiveWorldTransform;
 };
 

+ 3 - 1
Source/Engine/LuaScript/pkgs/Math/Plane.pkg

@@ -11,7 +11,7 @@ class Plane
     
     void Define(const Vector3& v0, const Vector3& v1, const Vector3& v2);
     void Define(const Vector3& normal, const Vector3& point);
-    
+
     float Distance(const Vector3& point) const;
     Vector3 Reflect(const Vector3& direction) const;
     Matrix3x4 ReflectionMatrix() const;
@@ -19,4 +19,6 @@ class Plane
     Vector3 normal_ @ normal;
     Vector3 absNormal_ @ absNormal;
     float intercept_ @ intercept;
+    
+    static const Plane UP;
 };

+ 11 - 0
Source/Engine/Math/Frustum.cpp

@@ -193,6 +193,17 @@ void Frustum::UpdatePlanes()
     planes_[PLANE_UP].Define(vertices_[0], vertices_[4], vertices_[7]);
     planes_[PLANE_DOWN].Define(vertices_[6], vertices_[5], vertices_[1]);
     planes_[PLANE_FAR].Define(vertices_[5], vertices_[6], vertices_[7]);
+
+    // Check if we ended up with inverted planes (reflected transform) and flip in that case
+    if (planes_[PLANE_NEAR].Distance(vertices_[5]) < 0.0f)
+    {
+        for (unsigned i = 0; i < NUM_FRUSTUM_PLANES; ++i)
+        {
+            planes_[i].normal_ = -planes_[i].normal_;
+            planes_[i].intercept_ = -planes_[i].intercept_;
+        }
+    }
+
 }
 
 }

+ 52 - 0
Source/Engine/Math/Plane.cpp

@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2008-2013 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "Precompiled.h"
+#include "Plane.h"
+
+namespace Urho3D
+{
+
+// Static initialization order can not be relied on, so do not use Vector3 constants
+const Plane Plane::UP(Vector3(0.0f, 1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f));
+
+Matrix3x4 Plane::ReflectionMatrix() const
+{
+    float negIntercept = -intercept_;
+
+    return Matrix3x4(
+        -2.0f * normal_.x_ * normal_.x_ + 1.0f,
+        -2.0f * normal_.x_ * normal_.y_,
+        -2.0f * normal_.x_ * normal_.z_,
+        -2.0f * normal_.x_ * negIntercept,
+        -2.0f * normal_.y_ * normal_.x_ ,
+        -2.0f * normal_.y_ * normal_.y_ + 1.0f,
+        -2.0f * normal_.y_ * normal_.z_,
+        -2.0f * normal_.y_ * negIntercept,
+        -2.0f * normal_.z_ * normal_.x_,
+        -2.0f * normal_.z_ * normal_.y_,
+        -2.0f * normal_.z_ * normal_.z_ + 1.0f,
+        -2.0f * normal_.z_ * negIntercept
+    );
+}
+
+}

+ 9 - 25
Source/Engine/Math/Plane.h

@@ -62,42 +62,23 @@ public:
         Vector3 dist1 = v1 - v0;
         Vector3 dist2 = v2 - v0;
         
-        Define(dist1.CrossProduct(dist2).Normalized(), v0);
+        Define(dist1.CrossProduct(dist2), v0);
     }
 
-    /// Define from a normal and a point.
+    /// Define from a normal vector and a point on the plane.
     void Define(const Vector3& normal, const Vector3& point)
     {
-        normal_ = normal;
-        absNormal_ = normal.Abs();
-        intercept_ = normal.DotProduct(point);
+        normal_ = normal.Normalized();
+        absNormal_ = normal_.Abs();
+        intercept_ = normal_.DotProduct(point);
     }
     
     /// Return signed distance to a point.
     float Distance(const Vector3& point) const { return normal_.DotProduct(point) - intercept_; }
     /// Reflect a normalized direction vector.
     Vector3 Reflect(const Vector3& direction) const { return direction - (2.0f * normal_.DotProduct(direction) * normal_); }
-
     /// Return a reflection matrix.
-    Matrix3x4 ReflectionMatrix() const
-    {
-        float negIntercept = -intercept_;
-
-        return Matrix3x4(
-            -2.0f * normal_.x_ * normal_.x_ + 1.0f,
-            -2.0f * normal_.x_ * normal_.y_,
-            -2.0f * normal_.x_ * normal_.z_,
-            -2.0f * normal_.x_ * negIntercept,
-            -2.0f * normal_.y_ * normal_.x_ ,
-            -2.0f * normal_.y_ * normal_.y_ + 1.0f,
-            -2.0f * normal_.y_ * normal_.z_,
-            -2.0f * normal_.y_ * negIntercept,
-            -2.0f * normal_.z_ * normal_.x_,
-            -2.0f * normal_.z_ * normal_.y_,
-            -2.0f * normal_.z_ * normal_.z_ + 1.0f,
-            -2.0f * normal_.z_ * negIntercept
-        );
-    }
+    Matrix3x4 ReflectionMatrix() const;
 
     /// Plane normal.
     Vector3 normal_;
@@ -105,6 +86,9 @@ public:
     Vector3 absNormal_;
     /// Plane intercept parameter.
     float intercept_;
+
+    /// Plane at origin with normal pointing up.
+    static const Plane UP;
 };
 
 }

+ 6 - 1
Source/Engine/Script/GraphicsAPI.cpp

@@ -97,6 +97,10 @@ static void RegisterCamera(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Camera", "bool get_autoAspectRatio() const", asMETHOD(Camera, GetAutoAspectRatio), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "void set_projectionOffset(const Vector2&in)", asMETHOD(Camera, SetProjectionOffset), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "const Vector2& get_projectionOffset() const", asMETHOD(Camera, GetProjectionOffset), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Camera", "void set_useReflection(bool)", asMETHOD(Camera, SetUseReflection), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Camera", "bool get_useReflection() const", asMETHOD(Camera, GetUseReflection), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Camera", "void set_reflectionPlane(const Plane&in) const", asMETHOD(Camera, SetReflectionPlane), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Camera", "const Plane& get_reflectionPlane() const", asMETHOD(Camera, GetReflectionPlane), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "void set_viewMask(uint)", asMETHOD(Camera, SetViewMask), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "uint get_viewMask() const", asMETHOD(Camera, GetViewMask), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "void set_viewOverrideFlags(uint)", asMETHOD(Camera, SetViewOverrideFlags), asCALL_THISCALL);
@@ -111,7 +115,8 @@ static void RegisterCamera(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Camera", "Vector3 get_forwardVector() const", asMETHOD(Camera, GetForwardVector), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "Vector3 get_rightVector() const", asMETHOD(Camera, GetRightVector), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "Vector3 get_upVector() const", asMETHOD(Camera, GetUpVector), asCALL_THISCALL);
-    
+    engine->RegisterObjectMethod("Camera", "Matrix3x4 get_effectiveWorldTransform() const", asMETHOD(Camera, GetEffectiveWorldTransform), asCALL_THISCALL);
+
     // Register Variant GetPtr() for Camera
     engine->RegisterObjectMethod("Variant", "Camera@+ GetCamera() const", asFUNCTION(GetVariantPtr<Camera>), asCALL_CDECL_OBJLAST);
 }