Browse Source

Adding script support for ray casting and getting screen ray from camera, added MousePress event for WebClient, math primitives C API for Vector2/Vector3/Ray

Josh Engebretson 10 years ago
parent
commit
9f791fc963

+ 154 - 1
Source/AtomicJS/Javascript/JSGraphics.cpp

@@ -20,11 +20,14 @@
 // THE SOFTWARE.
 //
 
+#include "JSMath.h"
 #include "JSGraphics.h"
-#include "JSVM.h"
 
 #include <Atomic/Graphics/Material.h>
 #include <Atomic/Graphics/Light.h>
+#include <Atomic/Graphics/Octree.h>
+#include <Atomic/Graphics/Camera.h>
+#include <Atomic/Scene/Node.h>
 
 namespace Atomic
 {
@@ -198,6 +201,141 @@ static int Material_GetTextureUnitName(duk_context* ctx)
     return 1;
 }
 
+static int Camera_GetScreenRay(duk_context* ctx)
+{
+    float x = (float) duk_to_number(ctx, 0);
+    float y = (float) duk_to_number(ctx, 1);
+
+    duk_push_this(ctx);
+    Camera* camera = js_to_class_instance<Camera>(ctx, -1, 0);
+
+    Ray ray = camera->GetScreenRay(x, y);
+    duk_push_new_ray(ctx, ray);
+
+    return 1;
+}
+
+// Octree Queries
+
+static duk_int_t DUK_MAGIC_RAYCAST = 1;
+static duk_int_t DUK_MAGIC_RAYCAST_SINGLE = 2;
+
+static void duk_push_rayqueryresult(duk_context* ctx, const RayQueryResult& result)
+{
+    duk_push_object(ctx);
+
+    duk_push_new_vector3(ctx, result.position_);
+    duk_put_prop_string(ctx, -2, "position");
+
+    duk_push_new_vector3(ctx, result.normal_);
+    duk_put_prop_string(ctx, -2, "normal");
+
+    duk_push_new_vector2(ctx, result.textureUV_);
+    duk_put_prop_string(ctx, -2, "textureUV");
+
+    duk_push_number(ctx, result.distance_);
+    duk_put_prop_string(ctx, -2, "distance");
+
+    js_push_class_object_instance(ctx, result.drawable_, "Drawable");
+    duk_put_prop_string(ctx, -2, "drawable");
+
+    js_push_class_object_instance(ctx, result.node_, "Node");
+    duk_put_prop_string(ctx, -2, "node");
+
+    duk_push_number(ctx, (duk_double_t) result.subObject_);
+    duk_put_prop_string(ctx, -2, "subObject");
+
+}
+
+static int Octree_Raycast(duk_context* ctx)
+{
+    bool single = duk_get_current_magic(ctx) == DUK_MAGIC_RAYCAST_SINGLE;
+
+    duk_idx_t nargs = duk_get_top(ctx);
+
+    // require at least the ray
+    if (nargs < 1)
+    {
+        duk_push_undefined(ctx);
+        return 1;
+    }
+
+    Ray ray;
+    if (!duk_get_ray(ctx, 0, ray))
+    {
+        duk_push_undefined(ctx);
+        return 1;
+    }
+
+    RayQueryLevel level = RAY_TRIANGLE;
+    if (nargs > 1)
+    {
+        unsigned _level = (unsigned) duk_to_number(ctx, 1);
+        if (_level > (unsigned) RAY_TRIANGLE_UV)
+        {
+            duk_push_undefined(ctx);
+            return 1;
+        }
+
+        level = (RayQueryLevel) _level;
+    }
+
+    float maxDistance = M_INFINITY;
+    if (nargs > 2)
+    {
+        maxDistance = (float) duk_to_number(ctx, 2);
+    }
+
+    unsigned char drawableFlags = DRAWABLE_ANY;
+    if (nargs > 3)
+    {
+        drawableFlags = (unsigned char) duk_to_number(ctx, 3);
+    }
+
+    unsigned viewMask = DEFAULT_VIEWMASK;
+    if (nargs > 4)
+    {
+        viewMask = (unsigned) duk_to_number(ctx, 4);
+    }
+
+    duk_push_this(ctx);
+    Octree* octree = js_to_class_instance<Octree>(ctx, -1, 0);
+
+    PODVector<RayQueryResult> result;
+    RayOctreeQuery query(result, ray, level, maxDistance, drawableFlags, viewMask);
+
+    single ? octree->RaycastSingle(query) : octree->Raycast(query);
+
+    // handle case of nothing hit
+    if (!result.Size())
+    {
+        if (single)
+            duk_push_null(ctx);
+        else
+            duk_push_array(ctx);
+
+        return 1;
+    }
+    else
+    {
+        if (single)
+        {
+            duk_push_rayqueryresult(ctx, result[0]);
+        }
+        else
+        {
+            duk_push_array(ctx);
+
+            for (unsigned i = 0; i < result.Size(); i++)
+            {
+                duk_push_rayqueryresult(ctx, result[i]);
+                duk_put_prop_index(ctx, -2, i);
+            }
+        }
+    }
+
+    return 1;
+}
 
 void jsapi_init_graphics(JSVM* vm)
 {
@@ -221,12 +359,27 @@ void jsapi_init_graphics(JSVM* vm)
     duk_put_prop_string(ctx, -2, "setShaderParameter");
     duk_pop(ctx);
 
+    js_class_get_prototype(ctx, "Atomic", "Octree");
+    duk_push_c_function(ctx, Octree_Raycast, DUK_VARARGS);
+    duk_set_magic(ctx, -1, (unsigned) DUK_MAGIC_RAYCAST);
+    duk_put_prop_string(ctx, -2, "rayCast");
+    duk_push_c_function(ctx, Octree_Raycast, DUK_VARARGS);
+    duk_set_magic(ctx, -1, (unsigned) DUK_MAGIC_RAYCAST_SINGLE);
+    duk_put_prop_string(ctx, -2, "rayCastSingle");
+    duk_pop(ctx);
+
+    js_class_get_prototype(ctx, "Atomic", "Camera");
+    duk_push_c_function(ctx, Camera_GetScreenRay, 2);
+    duk_put_prop_string(ctx, -2, "getScreenRay");
+    duk_pop(ctx);
+
     // static methods
     js_class_get_constructor(ctx, "Atomic", "Material");
     duk_push_c_function(ctx, Material_GetTextureUnitName, 1);
     duk_put_prop_string(ctx, -2, "getTextureUnitName");
     duk_pop(ctx);
 
+
 }
 
 }

+ 0 - 1
Source/AtomicJS/Javascript/JSIO.cpp

@@ -39,7 +39,6 @@ enum IO_MAGIC_TYPE
     IO_MAGIC_BINARY
 };
 
-
 static Serializer* CastToSerializer(duk_context* ctx, int index)
 {
     Object* o = js_to_class_instance<Object>(ctx, index, 0);

+ 154 - 0
Source/AtomicJS/Javascript/JSMath.cpp

@@ -0,0 +1,154 @@
+#include "JSVM.h"
+
+#include <Atomic/Math/Ray.h>
+
+namespace Atomic
+{
+
+bool duk_get_vector2(duk_context* ctx, duk_idx_t idx, Vector2& vec2)
+{
+    idx = duk_normalize_index(ctx, idx);
+
+    // check that we are an array of length 3
+    if (!duk_is_array(ctx, idx) || duk_get_length(ctx, idx) != 2)
+        return false;
+
+    // get the array values
+    duk_get_prop_index(ctx, idx, 0);
+    duk_get_prop_index(ctx, idx, 1);
+
+    if (!duk_is_number(ctx, -2) || !duk_is_number(ctx, -1))
+    {
+        // pop off and return false
+        duk_pop_2(ctx);
+        return false;
+    }
+
+    vec2.x_ = (float) duk_to_number(ctx, -2);
+    vec2.y_ = (float) duk_to_number(ctx, -1);
+
+    duk_pop_2(ctx);
+
+    return true;
+}
+
+bool duk_set_vector2(duk_context* ctx, duk_idx_t idx, const Vector2& vec2)
+{
+    idx = duk_normalize_index(ctx, idx);
+
+    if (!duk_is_array(ctx, idx))
+        return false;
+
+    duk_push_number(ctx, vec2.x_);
+    duk_put_prop_index(ctx, idx, 0);
+    duk_push_number(ctx, vec2.y_);
+    duk_put_prop_index(ctx, idx, 1);
+
+    return true;
+}
+
+
+void duk_push_new_vector2(duk_context* ctx, const Vector2& vec2)
+{
+    duk_push_array(ctx);
+    duk_set_vector2(ctx, -1, vec2);
+}
+
+bool duk_get_vector3(duk_context* ctx, duk_idx_t idx, Vector3& vec3)
+{
+    idx = duk_normalize_index(ctx, idx);
+
+    // check that we are an array of length 3
+    if (!duk_is_array(ctx, idx) || duk_get_length(ctx, idx) != 3)
+        return false;
+
+    // get the array values
+    duk_get_prop_index(ctx, idx, 0);
+    duk_get_prop_index(ctx, idx, 1);
+    duk_get_prop_index(ctx, idx, 2);
+
+    if (!duk_is_number(ctx, -3) || !duk_is_number(ctx, -2) || !duk_is_number(ctx, -1))
+    {
+        // pop off and return false
+        duk_pop_3(ctx);
+        return false;
+    }
+
+    vec3.x_ = (float) duk_to_number(ctx, -3);
+    vec3.y_ = (float) duk_to_number(ctx, -2);
+    vec3.z_ = (float) duk_to_number(ctx, -1);
+
+    duk_pop_3(ctx);
+
+    return true;
+}
+
+bool duk_set_vector3(duk_context* ctx, duk_idx_t idx, const Vector3& vec3)
+{
+    idx = duk_normalize_index(ctx, idx);
+
+    if (!duk_is_array(ctx, idx))
+        return false;
+
+    duk_push_number(ctx, vec3.x_);
+    duk_put_prop_index(ctx, idx, 0);
+    duk_push_number(ctx, vec3.y_);
+    duk_put_prop_index(ctx, idx, 1);
+    duk_push_number(ctx, vec3.z_);
+    duk_put_prop_index(ctx, idx, 2);
+
+    return true;
+}
+
+
+void duk_push_new_vector3(duk_context* ctx, const Vector3& vec3)
+{
+    duk_push_array(ctx);
+    duk_set_vector3(ctx, -1, vec3);
+}
+
+bool duk_get_ray(duk_context* ctx, duk_idx_t idx, Ray& ray)
+{
+    idx = duk_normalize_index(ctx, idx);
+
+    // check that we are an object
+    if (!duk_is_object(ctx, idx))
+        return false;
+
+    duk_get_prop_string(ctx, idx, "origin");
+    duk_get_prop_string(ctx, idx, "direction");
+
+    if (!duk_get_vector3(ctx, -2, ray.origin_) || !duk_get_vector3(ctx, -1, ray.direction_))
+    {
+        duk_pop_2(ctx);
+        return false;
+    }
+
+    duk_pop_2(ctx);
+    return true;
+}
+
+bool duk_set_ray(duk_context* ctx, duk_idx_t idx, const Ray& ray)
+{
+    idx = duk_normalize_index(ctx, idx);
+
+    if (!duk_is_object(ctx, idx))
+        return false;
+
+    duk_push_new_vector3(ctx, ray.origin_);
+    duk_put_prop_string(ctx, idx, "origin");
+
+    duk_push_new_vector3(ctx, ray.direction_);
+    duk_put_prop_string(ctx, idx, "direction");
+
+    return true;
+}
+
+
+void duk_push_new_ray(duk_context* ctx, const Ray& ray)
+{
+    duk_push_object(ctx);
+    duk_set_ray(ctx, -1, ray);
+}
+
+}

+ 22 - 0
Source/AtomicJS/Javascript/JSMath.h

@@ -0,0 +1,22 @@
+#pragma once
+
+#include "JSVM.h"
+#include <Atomic/Math/Ray.h>
+
+namespace Atomic
+{
+
+
+bool duk_get_vector2(duk_context* ctx, duk_idx_t idx, Vector2& vec3);
+bool duk_set_vector2(duk_context* ctx, duk_idx_t idx, const Vector2& vec3);
+void duk_push_new_vector2(duk_context* ctx, const Vector2& vec3);
+
+bool duk_get_vector3(duk_context* ctx, duk_idx_t idx, Vector3& vec3);
+bool duk_set_vector3(duk_context* ctx, duk_idx_t idx, const Vector3& vec3);
+void duk_push_new_vector3(duk_context* ctx, const Vector3& vec3);
+
+bool duk_get_ray(duk_context* ctx, duk_idx_t idx, Ray& ray);
+bool duk_set_ray(duk_context* ctx, duk_idx_t idx, const Ray& ray);
+void duk_push_new_ray(duk_context* ctx, const Ray& ray);
+
+}

+ 6 - 0
Source/AtomicWebView/WebClient.cpp

@@ -311,6 +311,12 @@ void WebClient::SendMouseClickEvent(int x, int y, unsigned button, bool mouseUp,
 
 }
 
+void WebClient::SendMousePressEvent(int x, int y, unsigned button, unsigned modifier) const
+{
+    SendMouseClickEvent(x, y, button, false, modifier);
+    SendMouseClickEvent(x, y, button, true, modifier);
+}
+
 void WebClient::SendMouseMoveEvent(int x, int y, unsigned modifier, bool mouseLeave) const
 {
     if (!d_->browser_.get())

+ 1 - 0
Source/AtomicWebView/WebClient.h

@@ -35,6 +35,7 @@ public:
     CefClient* GetCefClient();
 
     void SendMouseClickEvent(int x, int y, unsigned button, bool mouseUp, unsigned modifier) const;
+    void SendMousePressEvent(int x, int y, unsigned button = 0, unsigned modifier = 0) const;
     void SendMouseMoveEvent(int x, int y, unsigned modifier, bool mouseLeave = false) const;
     void SendMouseWheelEvent(int x, int y, unsigned modifier, int deltaX, int deltaY) const;