论坛

由用户创建的信息 henrydf
20 November 2017 11:46
red marker is the ray test result.
green marker is the closest vertex in mesh.
it seems engine executes ray test with a bounding box which just like a cube. lose geometry information.
below is my blender file.
wshirt.blend
and my code in raytest.js
"use strict";

b4w.register("RayTest", function(exports, require) {

var m_anim    = require("animation");
var m_app     = require("app");
var m_cam     = require("camera");
var m_cfg     = require("config");
var m_cont    = require("container");
var m_cons    = require("constraints");
var m_ctl     = require("controls");
var m_data    = require("data");
var m_math    = require("math");
var m_obj     = require("objects");
var m_phy     = require("physics");
var m_quat    = require("quat");
var m_scenes  = require("scenes");
var m_trans   = require("transform");
var m_tsr     = require("tsr");
var m_util    = require("util");
var m_vec3    = require("vec3");
var m_version = require("version");
var m_geometry= require("geometry");
var m_mat     = require("material");

var DEBUG = (m_version.type() === "DEBUG");

var APP_ASSETS_PATH = m_cfg.get_assets_path("RayTest");

exports.init = function() {
    m_app.init({
        autoresize: true,
        callback: init_cb,
        canvas_container_id: "main_canvas_container",
        physics_enabled: true,
        show_fps: true,
        assets_dds_available: !DEBUG,
        assets_min50_available: !DEBUG,
        console_verbose: true
    });
}

function init_cb(canvas_elem, success) {

    if (!success) {
        console.log("b4w init failure");
        return;
    }
    load();
}

function load() {
    m_data.load(APP_ASSETS_PATH + "wcy.json", load_cb);
}

function load_cb(data_id) {
    init_logic();
    m_app.enable_camera_controls();
}

function init_logic() {

    var from = new Float32Array(3);
    var pline = m_math.create_pline();
    var to = new Float32Array(3);

    var decal_num = 0;
    // var decal_src = m_scenes.get_object_by_name("Decal");
    var decal = m_scenes.get_object_by_name('R');
    var decalG = m_scenes.get_object_by_name('G');

    var decal_tsr = m_tsr.create();
    var obj_tsr = m_tsr.create();
    var decal_rot = m_quat.create();
    var decal_tsrG = m_tsr.create();
    var obj_tsrG = m_tsr.create();
    var decal_rotG = m_quat.create();

    var ray_test_cb = function(id, hit_fract, obj_hit, hit_time, hit_pos, hit_norm) {
        console.log(hit_pos);
        var texture_array = m_geometry.extract_vertex_array(obj_hit, 'Material.003', 'param_GEOMETRY_UV_a_0');
        // console.log(texture_array);
        var position_array = m_geometry.extract_vertex_array(obj_hit, 'Material.003', 'a_position');
        // console.log(position_array);
        // var index_array = m_geometry.extract_index_array(obj_hit, 'Material.003');
        // console.log(index_array);
        
        var x1 = hit_pos[0];
        var y1 = hit_pos[1];
        var z1 = hit_pos[2];
        var point_number = texture_array.length / 2;
        var min_distance = 999999;
        var min_distance_offset = -1;
        for (let index = 0; index < point_number; index++) {
            const offset = 3 * index;
            var x2 = position_array[offset + 0];
            var y2 = position_array[offset + 1];
            var z2 = position_array[offset + 2];
            var distance = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2) + Math.pow(z1 - z2, 2));
            if (distance < min_distance) {
                min_distance = distance;
                min_distance_offset = index;
            }
        }
        if (min_distance_offset !== -1) {
            var wanted_x = position_array[min_distance_offset * 3 + 0];
            var wanted_y = position_array[min_distance_offset * 3 + 1];
            var wanted_z = position_array[min_distance_offset * 3 + 2];
            var wanted_u = texture_array[min_distance_offset * 2 + 0];
            var wanted_v = texture_array[min_distance_offset * 2 + 1];
            console.log(`find wanted point(${wanted_x}, ${wanted_y}, ${wanted_z}) with UV(${wanted_u}, ${wanted_v})`);
            m_tsr.set_trans(new Float32Array([wanted_x, wanted_y, wanted_z]), decal_tsrG);
            m_trans.set_tsr(decalG, decal_tsrG);
        } else {
            console.error('should have a closest point');
        }

        m_mat.set_nodemat_value(obj_hit, ['Material.003', 'OffsetU'], (0.5102689862251282 - wanted_u) * 2);
        m_mat.set_nodemat_value(obj_hit, ['Material.003', 'OffsetV'], (0.4943990111351013 - wanted_v) * 2);

        // var decal = m_obj.copy(decal_src, "decal" + String(++decal_num), false);
        // m_scenes.append_object(decal);

        m_tsr.set_trans(hit_pos, decal_tsr);

        m_quat.rotationTo(m_util.AXIS_Z, hit_norm, decal_rot);
        m_trans.set_rotation_v(decal, decal_rot);
        m_tsr.set_quat(decal_rot, decal_tsr);

        if (obj_hit && m_anim.is_animated(obj_hit)) {
            m_trans.get_tsr(obj_hit, obj_tsr);

            m_tsr.invert(obj_tsr, obj_tsr);
            m_tsr.multiply(obj_tsr, decal_tsr, decal_tsr);

            var offset = m_tsr.get_trans_view(decal_tsr);
            var rot_offset = m_tsr.get_quat_view(decal_tsr);
            m_cons.append_stiff(decal, obj_hit, offset, rot_offset);
        }

        m_trans.set_tsr(decal, decal_tsr);
    }

    var mouse_cb = function(e) {
        var x = e.clientX;
        var y = e.clientY;
        m_cam.calc_ray(m_scenes.get_active_camera(), x, y, pline);
        m_math.get_pline_directional_vec(pline, to);
        // m_cam.get_translation(m_scenes.get_active_camera(), from);

        m_vec3.scale(to, 100, to);
        var obj_src = m_scenes.get_active_camera();
        var id = m_phy.append_ray_test_ext(obj_src, from, to, "ANY",
                ray_test_cb, true, false, true, true);
    }

    var cont = m_cont.get_container();
    cont.addEventListener("mousedown", mouse_cb, false);
}

});
b4w.require("RayTest").init();
03 November 2017 10:00
Is there a way do this? Or any exists API?
03 November 2017 09:09
Reply to post of user Konstantin Khomyakov
You can try to use Vector Math -> Add instead of Mapping -> Location if you use Mapping for Point and Vector (not Texture and Normal)

It works, thanks.
02 November 2017 05:39
Reply to post of user Konstantin Khomyakov
Hello!

You can update Value and RGB nodes via JS. Please take a look at this code snippet

Thank you.
I know that, but my target is change location property in mapping node…
01 November 2017 04:59
Is there a way to update node value in node material by js?
I have a material by 2 textures, and using a mapping to change its location.
Now I want to change location with js, but can not find a related API…
Anybody can help?
Thanks.
31 October 2017 06:07
Kirill, you can clone the demo from git@github.com:henrydf/b4w-raytest-demo.git

Thanks for your help.
31 October 2017 05:09
Thanks for your kindly reply.
This demo which I am using is intergrated with a complecated system. I need more time to isolate.
30 October 2017 13:01
I clone the code snipet by making project in demo page.
And I found something interesting.
exports.append_ray_test = function(obj, from, to, collision_id, callback,
        autoremove, calc_all_hits, calc_pos_norm, ign_src_rot) {

    var id = get_unique_ray_test_id();

    var test = {
        id: id,
        body_id: obj ? obj.physics.body_id : 0,
        from: new Float32Array(from),
        to: new Float32Array(to),
        collision_id: collision_id,
        collision_id_num: col_id_num(collision_id),
        autoremove: autoremove,
        calc_all_hits: calc_all_hits,
        calc_pos_norm: calc_pos_norm,
        ign_src_rot: ign_src_rot,
        callback: callback
    }

    // NOTE: it's not possible to determine the worker in no obj specified
    var worker = find_worker_by_body_id(test.body_id) || _workers[0];
    var scene = find_scene_by_worker(worker);

    var sphy = scene._physics;

    sphy.ray_tests[id] = test;
    sphy.ray_tests_arr.push(test);

    m_ipc.post_msg(worker, m_ipc.OUT_APPEND_RAY_TEST, test.id, test.body_id, test.from,
            test.to, test.collision_id_num, test.autoremove,
            test.calc_all_hits, test.calc_pos_norm, test.ign_src_rot);

    return id;
}

I add a breakpoint in below codes.
Ray test instructions have been added in scene._physics.ray_tests.
But callbacks always been hang up…

Anyone can help?