diff --git a/cocos/scripting/js-bindings/manual/cocos2d_specifics.cpp b/cocos/scripting/js-bindings/manual/cocos2d_specifics.cpp index 72eda51986..46bd64bb9b 100644 --- a/cocos/scripting/js-bindings/manual/cocos2d_specifics.cpp +++ b/cocos/scripting/js-bindings/manual/cocos2d_specifics.cpp @@ -3891,6 +3891,68 @@ bool js_cocos2dx_ccmat4MultiplyVec3(JSContext *cx, uint32_t argc, jsval *vp) return false; } +bool js_cocos2dx_ccmat4GetInversed(JSContext *cx, uint32_t argc, jsval *vp) +{ + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + if(argc == 1) + { + cocos2d::Mat4 arg0; + bool ok = jsval_to_matrix(cx, args.get(0), &arg0); + JSB_PRECONDITION2(ok, cx, false, "Error processing arguments"); + + jsval jsret = matrix_to_jsval(cx, arg0.getInversed()); + + args.rval().set(jsret); + return true; + } + + JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 1); + return false; +} + +bool js_cocos2dx_ccmat4TransformVector(JSContext *cx, uint32_t argc, jsval *vp) +{ + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + if(argc == 3) + { + cocos2d::Mat4 arg0; + cocos2d::Vec4 arg1; + cocos2d::Vec4 arg2; + bool ok = jsval_to_matrix(cx, args.get(0), &arg0); + ok &= jsval_to_vector4(cx, args.get(1), &arg1); + ok &= jsval_to_vector4(cx, args.get(2), &arg2); + + JSB_PRECONDITION2(ok, cx, false, "Error processing arguments"); + + arg0.transformVector(arg1, &arg2); + jsval jsret = vector4_to_jsval(cx,arg2); + args.rval().set(jsret); + return true; + } + else if (argc == 6) + { + cocos2d::Mat4 arg0; + double arg1 = 0.0,arg2 = 0.0,arg3 = 0.0, arg4 = 0.0; + cocos2d::Vec3 arg5; + + bool ok = jsval_to_matrix(cx, args.get(0), &arg0) && + JS::ToNumber(cx, args.get(1), &arg1) && + JS::ToNumber(cx, args.get(2), &arg2) && + JS::ToNumber(cx, args.get(3), &arg3) && + JS::ToNumber(cx, args.get(4), &arg4) && + jsval_to_vector3(cx, args.get(5), &arg5); + + JSB_PRECONDITION2(ok, cx, false, "Error processing arguments"); + arg0.transformVector(arg1, arg2, arg3, arg4, &arg5); + jsval jsret = vector3_to_jsval(cx,arg5); + args.rval().set(jsret); + return true; + } + + JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 3); + return false; +} + bool js_cocos2dx_ccquatMultiply(JSContext *cx, uint32_t argc, jsval *vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); @@ -5167,12 +5229,13 @@ bool js_cocos2dx_Camera_unproject(JSContext *cx, uint32_t argc, jsval *vp) js_proxy_t *proxy = jsb_get_js_proxy(obj); cocos2d::Camera* cobj = (cocos2d::Camera *)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2( cobj, cx, false, "js_cocos2dx_Camera_unproject : Invalid Native Object"); - if (argc == 2) { + if (argc == 3) { cocos2d::Size arg0; cocos2d::Vec3 arg1; cocos2d::Vec3 arg2; ok &= jsval_to_ccsize(cx, args.get(0), &arg0); ok &= jsval_to_vector3(cx, args.get(1), &arg1); + ok &= jsval_to_vector3(cx, args.get(2), &arg2); JSB_PRECONDITION2(ok, cx, false, "js_cocos2dx_Camera_unproject : Error processing arguments"); cobj->unproject(arg0, &arg1, &arg2); args.rval().set(vector3_to_jsval(cx, arg2)); @@ -5187,7 +5250,7 @@ bool js_cocos2dx_Camera_unproject(JSContext *cx, uint32_t argc, jsval *vp) args.rval().set(vector3_to_jsval(cx, ret)); return true; } - JS_ReportError(cx, "js_cocos2dx_Camera_unproject : wrong number of arguments: %d, was expecting %d", argc, 2); + JS_ReportError(cx, "js_cocos2dx_Camera_unproject : wrong number of arguments: %d, was expecting %d", argc, 3); return false; } @@ -6237,6 +6300,8 @@ void register_cocos2dx_js_core(JSContext* cx, JS::HandleObject global) JS_DefineFunction(cx, tmpObj, "mat4CreateRotation", js_cocos2dx_ccmat4CreateRotation, 1, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineFunction(cx, tmpObj, "mat4Multiply", js_cocos2dx_ccmat4Multiply, 2, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineFunction(cx, tmpObj, "mat4MultiplyVec3", js_cocos2dx_ccmat4MultiplyVec3, 2, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineFunction(cx, tmpObj, "mat4GetInversed", js_cocos2dx_ccmat4GetInversed, 1, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineFunction(cx, tmpObj, "mat4TransformVector", js_cocos2dx_ccmat4TransformVector, 3, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineFunction(cx, tmpObj, "quatMultiply", js_cocos2dx_ccquatMultiply, 2, JSPROP_READONLY | JSPROP_PERMANENT); js_register_cocos2dx_EventKeyboard(cx, ccObj); diff --git a/cocos/scripting/js-bindings/manual/js_manual_conversions.cpp b/cocos/scripting/js-bindings/manual/js_manual_conversions.cpp index 8a6abab752..e70da4f622 100644 --- a/cocos/scripting/js-bindings/manual/js_manual_conversions.cpp +++ b/cocos/scripting/js-bindings/manual/js_manual_conversions.cpp @@ -2718,6 +2718,22 @@ jsval vector3_to_jsval(JSContext *cx, const cocos2d::Vec3& v) return JSVAL_NULL; } +jsval vector4_to_jsval(JSContext *cx, const cocos2d::Vec4& v) +{ + JS::RootedObject proto(cx); + JS::RootedObject parent(cx); + JS::RootedObject tmp(cx, JS_NewObject(cx, NULL, proto, parent)); + if (!tmp) return JSVAL_NULL; + bool ok = JS_DefineProperty(cx, tmp, "x", v.x, JSPROP_ENUMERATE | JSPROP_PERMANENT) && + JS_DefineProperty(cx, tmp, "y", v.y, JSPROP_ENUMERATE | JSPROP_PERMANENT) && + JS_DefineProperty(cx, tmp, "z", v.z, JSPROP_ENUMERATE | JSPROP_PERMANENT) && + JS_DefineProperty(cx, tmp, "w", v.z, JSPROP_ENUMERATE | JSPROP_PERMANENT); + if (ok) { + return OBJECT_TO_JSVAL(tmp); + } + return JSVAL_NULL; +} + jsval blendfunc_to_jsval(JSContext *cx, const cocos2d::BlendFunc& v) { JS::RootedObject proto(cx); diff --git a/cocos/scripting/js-bindings/manual/js_manual_conversions.h b/cocos/scripting/js-bindings/manual/js_manual_conversions.h index 9627ca4679..7c2f6cc14f 100644 --- a/cocos/scripting/js-bindings/manual/js_manual_conversions.h +++ b/cocos/scripting/js-bindings/manual/js_manual_conversions.h @@ -337,6 +337,7 @@ jsval std_vector_float_to_jsval( JSContext *cx, const std::vector& v); jsval matrix_to_jsval(JSContext *cx, const cocos2d::Mat4& v); jsval vector2_to_jsval(JSContext *cx, const cocos2d::Vec2& v); jsval vector3_to_jsval(JSContext *cx, const cocos2d::Vec3& v); +jsval vector4_to_jsval(JSContext *cx, const cocos2d::Vec4& v); jsval blendfunc_to_jsval(JSContext *cx, const cocos2d::BlendFunc& v); jsval vector_vec2_to_jsval(JSContext *cx, const std::vector& v); diff --git a/cocos/scripting/js-bindings/manual/physics3d/jsb_cocos2dx_physics3d_manual.cpp b/cocos/scripting/js-bindings/manual/physics3d/jsb_cocos2dx_physics3d_manual.cpp index 2133904fdd..11531b6338 100644 --- a/cocos/scripting/js-bindings/manual/physics3d/jsb_cocos2dx_physics3d_manual.cpp +++ b/cocos/scripting/js-bindings/manual/physics3d/jsb_cocos2dx_physics3d_manual.cpp @@ -299,6 +299,91 @@ bool js_cocos2dx_physics3d_Physics3dShape_createHeightfield(JSContext *cx, uint3 return false; } + +bool jsval_to_Physics3DWorld_HitResult(JSContext *cx, JS::HandleValue v, cocos2d::Physics3DWorld::HitResult* ret) +{ + JS::RootedObject tmp(cx); + JS::RootedValue jshitPosition(cx); + JS::RootedValue jshitNormal(cx); + JS::RootedValue jshitObject(cx); + + bool ok = v.isObject() && + JS_ValueToObject(cx, v, &tmp) && + JS_GetProperty(cx, tmp, "hitPosition", &jshitPosition) && + JS_GetProperty(cx, tmp, "hitNormal", &jshitNormal) && + JS_GetProperty(cx, tmp, "hitObj", &jshitObject) && + jsval_to_vector3(cx, jshitPosition, &(ret->hitPosition)) && + jsval_to_vector3(cx, jshitNormal, &(ret->hitNormal)); + + JSB_PRECONDITION2(ok, cx, false, "jsval_to_Physics3DWorld_HitResult : Error processing arguments"); + + js_proxy_t *proxy = jsb_get_js_proxy(jshitObject.toObjectOrNull()); + ret->hitObj = (cocos2d::Physics3DObject *)(proxy ? proxy->ptr : nullptr); + + return true; +} + +jsval Physics3DWorld_HitResult_to_jsval(JSContext *cx, const cocos2d::Physics3DWorld::HitResult& v) +{ + JS::RootedObject proto(cx); + JS::RootedObject parent(cx); + JS::RootedObject tmp(cx, JS_NewObject(cx, nullptr, proto, parent)); + if (!tmp) return JSVAL_NULL; + JS::RootedValue hitPosition(cx, vector3_to_jsval(cx, v.hitPosition)); + JS::RootedValue hitNormal(cx, vector3_to_jsval(cx, v.hitNormal)); + JS::RootedValue hitobject(cx); + + if (v.hitObj) + { + js_proxy_t *jsProxy = js_get_or_create_proxy(cx, (cocos2d::Physics3DObject*)v.hitObj); + hitobject.set(OBJECT_TO_JSVAL(jsProxy->obj)); + } + + bool ok = JS_DefineProperty(cx, tmp, "hitPosition", hitPosition, JSPROP_ENUMERATE | JSPROP_PERMANENT) && + JS_DefineProperty(cx, tmp, "hitNormal", hitNormal, JSPROP_ENUMERATE | JSPROP_PERMANENT) && + JS_DefineProperty(cx, tmp, "hitObj", hitobject, JSPROP_ENUMERATE | JSPROP_PERMANENT); + + if (ok) { + return OBJECT_TO_JSVAL(tmp); + } + return JSVAL_NULL; +} + +bool js_cocos2dx_physics3d_Physics3DWorld_rayCast(JSContext *cx, uint32_t argc, jsval *vp) +{ + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + bool ok = true; + JS::RootedObject obj(cx, args.thisv().toObjectOrNull()); + js_proxy_t *proxy = jsb_get_js_proxy(obj); + cocos2d::Physics3DWorld* cobj = (cocos2d::Physics3DWorld *)(proxy ? proxy->ptr : NULL); + JSB_PRECONDITION2( cobj, cx, false, "js_cocos2dx_physics3d_Physics3DWorld_rayCast : Invalid Native Object"); + if (argc == 3) { + cocos2d::Vec3 arg0; + cocos2d::Vec3 arg1; + cocos2d::Physics3DWorld::HitResult arg2; + ok &= jsval_to_vector3(cx, args.get(0), &arg0); + ok &= jsval_to_vector3(cx, args.get(1), &arg1); + ok &= jsval_to_Physics3DWorld_HitResult(cx, args.get(2), &arg2); + JSB_PRECONDITION2(ok, cx, false, "js_cocos2dx_physics3d_Physics3DWorld_rayCast : Error processing arguments"); + bool ret = cobj->rayCast(arg0, arg1, &arg2); + + if (ret) + { + jsval jsret = JSVAL_NULL; + jsret = Physics3DWorld_HitResult_to_jsval(cx, arg2); + args.rval().set(jsret); + } + else + { + args.rval().set(JSVAL_FALSE); + } + return true; + } + + JS_ReportError(cx, "js_cocos2dx_physics3d_Physics3DWorld_rayCast : wrong number of arguments: %d, was expecting %d", argc, 3); + return false; +} + void register_all_cocos2dx_physics3d_manual(JSContext *cx, JS::HandleObject global) { JS::RootedObject ccObj(cx); @@ -319,6 +404,10 @@ void register_all_cocos2dx_physics3d_manual(JSContext *cx, JS::HandleObject glob JS_DefineFunction(cx, tmpObj, "createHeightfield", js_cocos2dx_physics3d_Physics3dShape_createHeightfield, 8, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineFunction(cx, JS::RootedObject(cx, jsb_cocos2d_Physics3DObject_prototype), "setCollisionCallback", jsb_cocos2d_Physics3DObject_setCollisionCallback, 2, JSPROP_READONLY | JSPROP_PERMANENT); + + JS_GetProperty(cx, ccObj, "Physics3DWorld", &tmpVal); + tmpObj = tmpVal.toObjectOrNull(); + JS_DefineFunction(cx, tmpObj, "rayCast", js_cocos2dx_physics3d_Physics3DWorld_rayCast, 3, JSPROP_READONLY | JSPROP_PERMANENT); } #endif //CC_USE_3D_PHYSICS && CC_ENABLE_BULLET_INTEGRATION diff --git a/cocos/scripting/js-bindings/script/physics3d/jsb_physics3d.js b/cocos/scripting/js-bindings/script/physics3d/jsb_physics3d.js index 932f74ea8c..e2e3d68c38 100644 --- a/cocos/scripting/js-bindings/script/physics3d/jsb_physics3d.js +++ b/cocos/scripting/js-bindings/script/physics3d/jsb_physics3d.js @@ -41,3 +41,18 @@ cc.Physics3DComponent.PhysicsSyncFlag = { PHYSICS_TO_NODE : 2, // align physics transform to the node NODE_AND_NODE : 1 | 2, //pre simulation, align the physics object to the node and align the node transform according to physics object after simulation }; + +cc.HitResult = function(){ + this.hitPosition = cc.math.vec3(); + this.hitNormal = cc.math.vec3(); + this.hitObj = null; +} + +cc.hitResult = function(){ + return new cc.HitResult(); +}; + +cc.Physics3DObject.PhysicsObjType = { + UNKNOWN : 0, + RIGID_BODY : 1, +}; \ No newline at end of file diff --git a/tests/js-tests/src/Physics3DTest/Physics3DTest.js b/tests/js-tests/src/Physics3DTest/Physics3DTest.js index 26a53846c0..d216eb5aca 100644 --- a/tests/js-tests/src/Physics3DTest/Physics3DTest.js +++ b/tests/js-tests/src/Physics3DTest/Physics3DTest.js @@ -289,6 +289,14 @@ var Physics3DConstraintDemo = Physics3DTestDemo.extend({ ctor:function(){ this._super(); + cc.eventManager.removeListener(this); + cc.eventManager.addListener({ + event:cc.EventListener.TOUCH_ALL_AT_ONCE, + onTouchesBegan:this.onTouchesBegan.bind(this), + onTouchesMoved:this.onTouchesMoved.bind(this), + onTouchesEnded:this.onTouchesEnded.bind(this) + }, this); + //PhysicsSprite3d = Sprite3D + Physics3DComponent var rbDes = cc.physics3DRigidBodyDes(); rbDes.disableSleep = true; @@ -322,7 +330,7 @@ var Physics3DConstraintDemo = Physics3DTestDemo.extend({ sprite = new jsb.Sprite3D("Sprite3DTest/box.c3t"); sprite.setTexture("Sprite3DTest/plane.png"); sprite.setScaleX(8); - sprite.setScaleZ(8); + sprite.setScaleY(8); sprite.setPosition3D(cc.math.vec3(5, 0, 0)); sprite.addComponent(component); sprite.setCameraMask(cc.CameraFlag.USER1); @@ -408,6 +416,90 @@ var Physics3DConstraintDemo = Physics3DTestDemo.extend({ constraint.setAngularUpperLimit(cc.math.vec3(0, 0, 0)); constraint.setLinearLowerLimit(cc.math.vec3(-10, 0, 0)); constraint.setLinearUpperLimit(cc.math.vec3(10, 0, 0)); + }, + + onTouchesBegan:function(touches, event){ + if(this._camera){ + cc.log("come in began"); + var touch = touches[0]; + var location = touch.getLocationInView(); + + var nearP = cc.math.vec3(location.x, location.y, 0); + var farP = cc.math.vec3(location.x, location.y, 1); + + var size = director.getWinSize(); + nearP = this._camera.unproject(size, nearP, nearP); + farP = this._camera.unproject(size, farP, farP); + + var result = cc.hitResult() + result = physicsScene.getPhysics3DWorld().rayCast(nearP, farP, result); + if(result !== false && result.hitObj.getObjType() == cc.Physics3DObject.PhysicsObjType.RIGID_BODY) + { + var mat = cc.math.mat4GetInversed(result.hitObj.getWorldTransform()); + var position = cc.math.vec4(result.hitPosition.x, result.hitPosition.y, result.hitPosition.z, 1.0); + var dst = cc.math.vec4(0, 0, 0, 1); + dst = cc.math.mat4TransformVector(result.hitObj.getWorldTransform(), position, dst); + + this._constraint = cc.Physics3DPointToPointConstraint.create(result.hitObj, cc.math.vec3(dst.x, dst.y, dst.z)); + physicsScene.getPhysics3DWorld().addPhysics3DConstraint(this._constraint, true); + this._pickingDistance = cc.math.vec3Length(cc.math.vec3Sub(result.hitPosition, nearP)); + return; + } + } + this._needShootBox = false; + }, + + onTouchesMoved:function(touches, event){ + if(this._constraint){ + var touch = touches[0]; + var location = touch.getLocationInView(); + + var nearP = cc.math.vec3(location.x, location.y, 0); + var farP = cc.math.vec3(location.x, location.y, 1); + + var size = director.getWinSize(); + nearP = this._camera.unproject(size, nearP, nearP); + farP = this._camera.unproject(size, farP, farP); + + var dir = cc.math.vec3Normalize(cc.math.vec3Sub(farP, nearP)); + this._constraint.setPivotPointInB(cc.math.vec3Add(nearP, cc.math.vec3(dir.x * this._pickingDistance, dir.y * this._pickingDistance, dir.z * this._pickingDistance))); + + return; + } + + if(touches.length > 0 && this._camera){ + var touch = touches[0]; + var delta = touch.getDelta(); + + this._angle -= cc.degreesToRadians(delta.x); + this._camera.setPosition3D(cc.math.vec3(100*Math.sin(this._angle), 50, 100*Math.cos(this._angle))); + this._camera.lookAt(cc.math.vec3(0, 0, 0), cc.math.vec3(0, 1, 0)); + + if(delta.x * delta.x + delta.y + delta.y > 16) + this._needShootBox = false; + } + }, + + onTouchesEnded:function(touches, event){ + if(this._constraint){ + physicsScene.getPhysics3DWorld().removePhysics3DConstraint(this._constraint); + this._constraint = null; + return; + } + + if(!this._needShootBox) + return; + if(touches.length > 0){ + var location = touches[0].getLocationInView(); + + var nearP = cc.math.vec3(location.x, location.y, -1); + var farP = cc.math.vec3(location.x, location.y, 1); + nearP = this._camera.unproject(nearP); + farP = this._camera.unproject(farP); + + var dir = cc.math.vec3Sub(farP, nearP); + this.shootBox(cc.math.vec3Add(this._camera.getPosition3D(), cc.math.vec3(dir.x*10, dir.y*10, dir.z*10))); + } } }); diff --git a/tools/tojs/cocos2dx_physics3d.ini b/tools/tojs/cocos2dx_physics3d.ini index a16b45760b..ee7c9f11a4 100644 --- a/tools/tojs/cocos2dx_physics3d.ini +++ b/tools/tojs/cocos2dx_physics3d.ini @@ -42,7 +42,7 @@ classes = Physics3DWorld Physics3DShape PhysicsSprite3D Physics3DObject Physics3 skip = Physics3DShape::[createCompoundShape createMesh createHeightfield], Physics3DObject::[setCollisionCallback], - Physics3DWorld::[getPhysicsObjects], + Physics3DWorld::[getPhysicsObjects rayCast], Physics3DConeTwistConstraint::[setMotorTarget setMotorTargetInConstraintSpace], PhysicsSprite3D::[create], Physics3DRigidBody::[create]