Forum

error in ray test

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();
24 November 2017 16:01
I've attached the corrected project.
Some notes:
1) The option "Object Physics" overrides "Special: Collision" option. I've disabled it.
2) Currently, obj_hit is always null for ray test with "Special collision" objects and you should use "Collision ID" and register the callback for each part of your cloth, or join all parts into one mesh.

Great model! And project!
Alexander (Blend4Web Team)
twitter
 
Please register or log in to leave a reply.