/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include "binding_helpers.h" #include "scene3d/scene.h" #include "scene3d/mobject.h" #include "scene3d/mcamera.h" #include "script_squirrel/cobject/matrix_decl.h" #include "core/renderer.h" #include "math/vector.h" using namespace GS; using namespace GS::S3D; using namespace GS::Script; static CObjectType camera_derived_types[] = { typetag_Item, typetag_Camera, typetag_Undefined }; static CObjectType object_derived_types[] = { typetag_Item, typetag_Object, typetag_Undefined }; //------------------------------------------------------------------------------ SQInteger CameraGetItem(HSQUIRRELVM vm) { __SQ_GETSINGLESAFEPTR(cam, MCamera, typetag_Camera) __SQ_RETURNSAFEPTR((MItem *)cam, typetag_Item) } SQInteger CameraGetFov(HSQUIRRELVM vm) { __SQ_GETSINGLE(__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)) __SQ_RETURNFLOAT(c->GetFov()) } SQInteger CameraSetFov(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETFLOAT(f) __SQ_GETEND c->SetFov(f); __SQ_RETURN } SQInteger CameraGetZoomFactor(HSQUIRRELVM vm) { __SQ_GETSINGLE(__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)) __SQ_RETURNFLOAT(c->zoom_factor) } SQInteger CameraSetZoomFactor(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETFLOAT(z) __SQ_GETEND c->SetZoomFactor(z); __SQ_RETURN } SQInteger CameraSetFStop(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETFLOAT(f) __SQ_GETEND c->registry.CreateKey("PostProcess:Dof:FStop", f); __SQ_RETURN } SQInteger CameraSetFocalDistance(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETFLOAT(f) __SQ_GETEND c->registry.CreateKey("PostProcess:Dof:FDist", f); __SQ_RETURN } SQInteger CameraGetVisibleItems(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d) __SQ_GETEND sq_newarray(vm, 0); Vector4 cameraPos = c->GetMatrix().GetRow(3); Vector4 cameraForward = c->GetMatrix().GetRow(2); // Camera's forward vector ListForeachPtr(MItem *, item, scene->GetItemList()) { if (item->GetItemType() == Type_Object) { if (MObject *o = (MObject *)item) { if (o->render_data.IsValid() && o->render_data->geometry.IsValid()) { Vector4 objectPos = o->GetMatrix().GetRow(3); Vector4 toObject = objectPos - cameraPos; // Skip this object if it's too far float distance = toObject.Len(); if (distance > 500) { continue; } // Check if object is in front of the camera float dot = toObject.x * cameraForward.x + toObject.y * cameraForward.y + toObject.z * cameraForward.z; if (dot > 0) { // Perform frustum culling Frustum::Visibility vis = c->frustum.ClassifyMinMax(o->render_data->geometry->minmax, &o->GetMatrix()); if (vis != Frustum::Outside) { CObject::Push(vm, (void *)item, typetag_Item); sq_arrayappend(vm, -2); } } } } } } return 1; } /* SQInteger CameraComputeProjectionMatrix(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETFRECT(viewport) __SQ_GETEND Matrix4 projection_matrix; c->ComputeProjectionMatrix(viewport, projection_matrix); __SQ_RETURNMATRIX4(projection_matrix) } */ SQInteger CameraSetAspectRatio(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETFLOAT(v) __SQ_GETEND c->aspect_ratio = v; __SQ_RETURN } SQInteger CameraGetAspectRatio(HSQUIRRELVM vm) { __SQ_GETSINGLE(__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)) __SQ_RETURNFLOAT(c->aspect_ratio) } SQInteger CameraSetAspectRatioRefAxis(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETBOOL(v) __SQ_GETEND c->aspect_ratio_ref_yaxis = asbool(v); __SQ_RETURN } SQInteger CameraSetClipping(HSQUIRRELVM vm) { __SQ_GETSTART(3) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETFLOAT(n) __SQ_GETFLOAT(f) __SQ_GETEND c->z_near = n; c->z_far = f; __SQ_RETURN } SQInteger CameraGetZNear(HSQUIRRELVM vm) { __SQ_GETSTART(1) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETEND __SQ_RETURNFLOAT(c->z_near) } SQInteger CameraGetZFar(HSQUIRRELVM vm) { __SQ_GETSTART(1) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETEND __SQ_RETURNFLOAT(c->z_far) } SQInteger CameraCullObject(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETCOBJECTBASE(o, MObject, object_derived_types) __SQ_GETEND Frustum::Visibility vis = Frustum::Outside; if (o->render_data.IsValid() && o->render_data->geometry.IsValid()) vis = c->frustum.ClassifyMinMax(o->render_data->geometry->minmax, &o->GetMatrix()); __SQ_RETURNINT(int(vis)) } SQInteger CameraCullPosition(HSQUIRRELVM vm) { __SQ_GETSTART(2) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETVECTOR(p) __SQ_GETEND __SQ_RETURNINT(int(c->frustum.ClassifySet(1, &p))) } SQInteger CameraGetFrustumVertices(HSQUIRRELVM vm) { __SQ_GETSTART(1) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETEND const Vector4* vtx = c->frustum.GetVertices(); sq_newarray(vm, 0); for (int i = 0; i < 8; ++i) { PushVector(vm, vtx[i], false); sq_arrayappend(vm, -2); } return 1; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ SQInteger CameraWorldToScreen(HSQUIRRELVM vm) { __SQ_GETSTART(3) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETSAFEPTR(renderer, Renderer, typetag_Renderer) __SQ_GETVECTOR(world) __SQ_GETEND Vector4 screen; if (!c->WorldToScreen(renderer->GetViewport(), world, screen)) screen.Set(-1, -1, -1, -1); __SQ_RETURNVECTOR(screen) } SQInteger CameraScreenToWorld(HSQUIRRELVM vm) { __SQ_GETSTART(4) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETSAFEPTR(renderer, Renderer, typetag_Renderer) __SQ_GETFLOAT(x) __SQ_GETFLOAT(y) __SQ_GETEND __SQ_RETURNVECTOR(c->ScreenToWorld(renderer->GetViewport(), x, y)) } SQInteger CameraScreenToWorldPlane(HSQUIRRELVM vm) { __SQ_GETSTART(5) __SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types) __SQ_GETSAFEPTR(renderer, Renderer, typetag_Renderer) __SQ_GETFLOAT(x) __SQ_GETFLOAT(y) __SQ_GETFLOAT(z) __SQ_GETEND __SQ_RETURNVECTOR(c->ScreenToWorld(renderer->GetViewport(), x, y, z)) } //------------------------------------------------------------------------------ //------------------------------------------------------- void RegisterCameraBinding(HSQUIRRELVM vm) //------------------------------------------------------- { /*# Topic: Camera Type: Camera Related: Item #*/ /*# Section: CameraGeneric Desc: Generic functions #*/ /*# Func: CameraGetItem Proto: Item:Camera Example: local camera_item = CameraGetItem(camera) Desc: Return camera item. #*/ sq_register(vm, CameraGetItem, "CameraGetItem", _SC(".x")); /*# Section: CameraAR Desc: Aspect ratio functions. #*/ /*# Func: CameraSetAspectRatio Proto: void:Camera,float aspect_ratio Desc: Set camera aspect ratio. #*/ sq_register(vm, CameraSetAspectRatio, "CameraSetAspectRatio", _SC(".xn")); /*# Func: CameraGetAspectRatio Proto: float:Camera Desc: Get camera aspect ratio. #*/ sq_register(vm, CameraGetAspectRatio, "CameraGetAspectRatio", _SC(".x")); /*# Func: CameraSetAspectRatioRefAxis Proto: void:Camera,bool use_Y_axis Desc: Set camera aspect ratio correction to be done on the vertical screen axis (Y) instead of the horizontal axis (X). #*/ sq_register(vm, CameraSetAspectRatioRefAxis, "CameraSetAspectRatioRefAxis", _SC(".xb")); /*# Section: CameraViewport Desc: Viewport functions #*/ /*# Func: CameraCullObject Proto: VisibilityFlags:Camera camera_to_cull_against,Object object_to_cull Desc: Cull an object against the camera frustum. Returns a visibility flag mask. #*/ sq_register(vm, CameraCullObject, "CameraCullObject", _SC(".xx")); /*# Func: CameraCullPosition Proto: VisibilityFlags:Camera camera_to_cull_against,Vector world_position Desc: Cull a position in world space against the camera frustum. Returns a visibility flag mask. #*/ sq_register(vm, CameraCullPosition, "CameraCullPosition", _SC(".xx")); sq_register(vm, CameraGetFrustumVertices, "CameraGetFrustumVertices", _SC(".x")); sq_register(vm, CameraGetZNear, "CameraGetZNear", _SC(".x")); sq_register(vm, CameraGetZFar, "CameraGetZFar", _SC(".x")); /*# Func: CameraGetFov Proto: float:Camera Desc: Get camera fov in radian. #*/ sq_register(vm, CameraGetFov, "CameraGetFov", _SC(".x")); /*# Func: CameraSetFov Proto: void:Camera,float fov_in_radian Example: CameraSetFov(camera, Deg(60)) Desc: Get camera fov in radian. #*/ sq_register(vm, CameraSetFov, "CameraSetFov", _SC(".xn")); /*# Func: CameraGetZoomFactor Proto: float:Camera Desc: Get camera zoom. #*/ sq_register(vm, CameraGetZoomFactor, "CameraGetZoomFactor", _SC(".x")); /*# Func: CameraSetZoomFactor Proto: void:Camera,float zoom_factor Example: CameraSetZoomFactor(camera, 3.2) Desc: Set camera zoom. #*/ sq_register(vm, CameraSetZoomFactor, "CameraSetZoomFactor", _SC(".xn")); /*# Func: CameraSetFocalDistance Proto: void:Camera,float distance_in_meters Example: // Set focus 10 meters from camera. Objects closer or father than 10 meters will appear out of focus. CameraSetFocalDistance(camera, Mtr(10)) Desc: Set camera focal distance, set to 0 or less to disable depth of field on the camera. #*/ sq_register(vm, CameraSetFocalDistance, "CameraSetFocalDistance", _SC(".xn")); /*# Func: CameraSetFStop Proto: void:Camera,float fstop_in_meters Example: CameraSetFStop(camera, Mtr(4)) Desc: Set camera f-stop, set to 0 or less to disable depth of field on the camera. #*/ sq_register(vm, CameraSetFStop, "CameraSetFStop", _SC(".xn")); /*# Func: CameraSetClipping Proto: void:camera,float near, float far Example: CameraSetClipping(camera, Cm(1), Mtr(100)) Desc: Set camera near and far clipping planes. #*/ sq_register(vm, CameraSetClipping, "CameraSetClipping", _SC(".xnn")); /*# Func: CameraWorldToScreen Proto: vector:Camera,Renderer,Vector world_position Example: // Project world position {10,5,1} on the screen. local p2d = CameraWorldToScreen(camera, g_render, Vector(10, 5, 1)) Desc: Transform a world space position to a normalized screen space position, in the range { [0;1], [0;1] }. #*/ sq_register(vm, CameraWorldToScreen, "CameraWorldToScreen", _SC(".xxx")); /*# Func: CameraScreenToWorld Proto: vector:Camera,Renderer,float x,float y Example: // Transform the middle of the screen to a 3d world position 1 meter away from the camera. local wp = CameraScreenToWorld(camera, g_render, 0.5, 0.5) Desc: Transform a normalized screen space position to a world space position.
The screen space position is the result of a projection on the Z=1 imaginary plane, situated 1 meter in front of the camera. See: CameraScreenToWorldPlane #*/ sq_register(vm, CameraScreenToWorld, "CameraScreenToWorld", _SC(".xxnn")); /*# Func: CameraScreenToWorldPlane Proto: vector:Camera,Renderer,float x,float y,float plane_distance_in_meters Desc: Transform a normalized screen space position to a world space position.
The screen space position is the result of a projection on an imaginary plane situated in front of the camera. #*/ sq_register(vm, CameraScreenToWorldPlane, "CameraScreenToWorldPlane", _SC(".xxnnn")); sq_pushroottable(vm); /*# Enum: VisibilityFlags Desc: Reported by the visibility functions, visibility can be total, partial or null. Values: VisibilityOutside,VisibilityClipped,VisibilityInside #*/ sq_pushstring(vm, "VisibilityOutside", -1); sq_pushinteger(vm, Frustum::Outside); sq_newslot(vm, -3, true); sq_pushstring(vm, "VisibilityClipped", -1); sq_pushinteger(vm, Frustum::Clipped); sq_newslot(vm, -3, true); sq_pushstring(vm, "VisibilityInside", -1); sq_pushinteger(vm, Frustum::Inside); sq_newslot(vm, -3, true); /*# Func: CameraGetVisibleItems Proto: array:Camera,Scene3d Desc: Get all visible items in the camera frustum. #*/ sq_register(vm, CameraGetVisibleItems, "CameraGetVisibleItems", _SC(".xx")); sq_pop(vm, 1); }