422 lines
13 KiB
C++
422 lines
13 KiB
C++
/* -----------------------------------------------------------------------------
|
|
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.<br>
|
|
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.<br>
|
|
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);
|
|
}
|