2023-06-17 14:30:49 +02:00
function Node_create_3D_Obj(_x, _y, _group = noone) {
var path = "";
if(!LOADING && !APPENDING && !CLONING) {
path = get_open_filename(".obj", "");
key_release();
if(path == "") return noone;
}
var node = new Node_3D_Obj(_x, _y, _group);
node.setPath(path);
return node;
}
2022-12-18 03:20:38 +01:00
function Node_create_3D_Obj_path(_x, _y, path) {
2022-12-12 09:08:03 +01:00
if(!file_exists(path)) return noone;
2023-01-17 08:11:55 +01:00
var node = new Node_3D_Obj(_x, _y, PANEL_GRAPH.getCurrentContext());
2023-01-01 02:06:02 +01:00
node.setPath(path);
return node;
2022-12-12 09:08:03 +01:00
}
2023-02-28 09:43:01 +01:00
function Node_3D_Obj(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
2023-01-25 06:49:00 +01:00
name = "3D Object";
2022-01-13 05:24:03 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 0] = nodeValue("Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.path, "")
.setDisplay(VALUE_DISPLAY.path_load, [ "*.obj", "" ])
.rejectArray();
2022-01-13 05:24:03 +01:00
2023-03-28 06:58:28 +02:00
inputs[| 1] = nodeValue("Generate", self, JUNCTION_CONNECT.input, VALUE_TYPE.trigger, 0)
2022-01-13 05:24:03 +01:00
.setDisplay(VALUE_DISPLAY.button, [ function() {
updateObj();
2022-01-16 14:28:57 +01:00
doUpdate();
2022-01-13 05:24:03 +01:00
}, "Generate"] );
2023-07-21 12:40:20 +02:00
inputs[| 2] = nodeValue("Dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, DEF_SURF)
2022-01-19 03:05:13 +01:00
.setDisplay(VALUE_DISPLAY.vector);
2022-01-13 05:24:03 +01:00
2023-05-03 21:42:17 +02:00
inputs[| 3] = nodeValue("Render position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0.5, 0.5 ])
2022-12-27 04:00:50 +01:00
.setDisplay(VALUE_DISPLAY.vector)
2023-05-03 21:42:17 +02:00
.setUnitRef( function() { return inputs[| 2].getValue(); }, VALUE_UNIT.reference);
2022-01-19 03:05:13 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 4] = nodeValue("Render rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 0 ])
2022-01-13 05:24:03 +01:00
.setDisplay(VALUE_DISPLAY.vector);
2023-02-14 05:32:32 +01:00
inputs[| 5] = nodeValue("Render scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1 ])
2022-01-13 05:24:03 +01:00
.setDisplay(VALUE_DISPLAY.vector);
2022-01-19 03:05:13 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 6] = nodeValue("Light direction", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
.setDisplay(VALUE_DISPLAY.rotation)
.rejectArray();
2022-12-12 09:08:03 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 7] = nodeValue("Light height", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.5)
.setDisplay(VALUE_DISPLAY.slider, [-1, 1, 0.01])
.rejectArray();
2022-12-12 09:08:03 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 8] = nodeValue("Light intensity", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1)
.setDisplay(VALUE_DISPLAY.slider, [0, 1, 0.01])
.rejectArray();
2022-12-12 09:08:03 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 9] = nodeValue("Light color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_white)
.rejectArray();
2023-01-01 02:06:02 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 10] = nodeValue("Ambient color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_grey)
.rejectArray();
2022-12-18 03:20:38 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 11] = nodeValue("Object scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1, 1 ])
2023-01-01 02:06:02 +01:00
.setDisplay(VALUE_DISPLAY.vector);
2023-02-14 05:32:32 +01:00
inputs[| 12] = nodeValue("Flip UV", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true, "Flip UV axis, can be use to fix some texture mapping error.")
.rejectArray();
2023-01-01 02:06:02 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 13] = nodeValue("Object rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 180 ])
2023-01-01 02:06:02 +01:00
.setDisplay(VALUE_DISPLAY.vector);
2023-02-14 05:32:32 +01:00
inputs[| 14] = nodeValue("Object position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 0 ])
2022-12-18 03:20:38 +01:00
.setDisplay(VALUE_DISPLAY.vector);
2023-02-14 05:32:32 +01:00
inputs[| 15] = nodeValue("Projection", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
.setDisplay(VALUE_DISPLAY.enum_button, [ "Orthographic", "Perspective" ])
.rejectArray();
2023-01-09 03:14:20 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 16] = nodeValue("Field of view", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 60)
.setDisplay(VALUE_DISPLAY.slider, [ 0, 90, 1 ])
.rejectArray();
2023-01-09 03:14:20 +01:00
2023-02-23 07:02:19 +01:00
inputs[| 17] = nodeValue("Scale view with dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true)
input_display_list = [
2023-05-03 21:42:17 +02:00
["Output", false], 2, 17,
2023-01-01 02:06:02 +01:00
["Geometry", false], 0, 1,
["Object transform", false], 14, 13, 11,
2023-01-09 03:14:20 +01:00
["Camera", false], 15, 16, 3, 5,
2023-01-01 02:06:02 +01:00
["Light", false], 6, 7, 8, 9, 10,
["Textures", true], 12,
2022-01-13 05:24:03 +01:00
];
2022-12-12 09:08:03 +01:00
input_length = ds_list_size(inputs);
2022-01-13 05:24:03 +01:00
input_display_len = array_length(input_display_list);
2023-02-14 05:32:32 +01:00
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
2023-01-09 03:14:20 +01:00
2023-05-03 21:42:17 +02:00
outputs[| 1] = nodeValue("3D scene", self, JUNCTION_CONNECT.output, VALUE_TYPE.d3object, function() { return submit_vertex(); });
2023-01-01 02:06:02 +01:00
2023-02-14 05:32:32 +01:00
outputs[| 2] = nodeValue("Normal pass", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
2023-01-09 03:14:20 +01:00
output_display_list = [
0, 2, 1
]
2023-05-03 21:42:17 +02:00
_3d_node_init(2, /*Transform*/ 3, 5, 14, 13, 11);
2022-01-13 05:24:03 +01:00
2023-02-23 07:02:19 +01:00
tex_surface = surface_create(1, 1);
2022-01-13 05:24:03 +01:00
function reset_tex() {
2023-02-23 07:02:19 +01:00
tex_surface = surface_verify(tex_surface, 1, 1);
2022-01-13 05:24:03 +01:00
surface_set_target(tex_surface);
draw_clear(c_black);
surface_reset_target();
}
reset_tex();
2023-02-14 05:32:32 +01:00
static onValueUpdate = function(index = 0) {
if(index == 12) updateObj(false);
2023-01-01 02:06:02 +01:00
}
function setPath(path) {
inputs[| 0].setValue(path);
updateObj();
}
2022-01-13 05:24:03 +01:00
function createMaterial(m_index) {
var index = ds_list_size(inputs);
2023-02-14 05:32:32 +01:00
inputs[| index] = nodeValue(materialNames[m_index] + " texture", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, tex_surface);
2022-12-12 09:08:03 +01:00
inputs[| index].setVisible(true);
2022-01-13 05:24:03 +01:00
input_display_list[input_display_len + m_index] = index;
2022-12-12 09:08:03 +01:00
if(m_index >= array_length(materials)) return;
var matY = y - (array_length(materials) - 1) / 2 * (128 + 32);
var mat = materials[m_index];
2023-01-01 02:06:02 +01:00
2022-12-12 09:08:03 +01:00
if(file_exists(mat.diff_path)) {
var sol = Node_create_Image_path(x - (w + 64), matY + m_index * (128 + 32), mat.diff_path);
sol.name = mat.name + " texture";
inputs[| index].setFrom(sol.outputs[| 0]);
} else {
2022-12-13 09:20:36 +01:00
var sol = nodeBuild("Node_Solid", x - (w + 64), matY + m_index * (128 + 32));
2022-12-12 09:08:03 +01:00
sol.name = mat.name + " texture";
sol.inputs[| 1].setValue(mat.diff);
inputs[| index].setFrom(sol.outputs[| 0]);
}
2022-01-13 05:24:03 +01:00
}
2022-12-12 09:08:03 +01:00
materialNames = [];
materialIndex = [];
2022-01-13 05:24:03 +01:00
materials = [];
2023-01-01 02:06:02 +01:00
2023-02-14 05:32:32 +01:00
static updateObj = function(updateMat = true) {
2023-01-01 02:06:02 +01:00
var _path = inputs[| 0].getValue();
2023-06-17 14:30:49 +02:00
if(!file_exists(_path)) return;
2023-01-01 02:06:02 +01:00
var _flip = inputs[| 12].getValue();
2023-02-14 05:32:32 +01:00
var _dir = filename_dir(_path);
2022-12-12 09:08:03 +01:00
var _pathMtl = string_copy(_path, 1, string_length(_path) - 4) + ".mtl";
2023-01-01 02:06:02 +01:00
var _v = readObj(_path, _flip);
2023-02-14 05:32:32 +01:00
2022-01-13 05:24:03 +01:00
if(_v != noone) {
2023-02-14 05:32:32 +01:00
VB = _v.vertex_groups;
materialNames = _v.materials;
materialIndex = _v.material_index;
use_normal = _v.use_normal;
if(_v.mtl_path != "")
2023-03-08 12:14:01 +01:00
_pathMtl = _dir + "/" + _v.mtl_path;
2022-01-13 05:24:03 +01:00
}
2023-02-14 05:32:32 +01:00
if(updateMat) {
if(array_length(materialNames))
materials = readMtl(_pathMtl);
else {
materialNames = ["Material"];
materialIndex = [0];
materials = [ new MTLmaterial("Material") ];
}
2022-12-12 09:08:03 +01:00
2023-02-14 05:32:32 +01:00
do_reset_material = true;
}
update();
2022-01-13 05:24:03 +01:00
}
do_reset_material = false;
2022-12-19 13:35:30 +01:00
static drawOverlay = function(active, _x, _y, _s, _mx, _my, _snx, _sny) {
2023-05-03 21:42:17 +02:00
_3d_gizmo(active, _x, _y, _s, _mx, _my, _snx, _sny);
2023-01-01 02:06:02 +01:00
}
static submit_vertex = function() {
var _lpos = inputs[| 14].getValue();
var _lrot = inputs[| 13].getValue();
var _lsca = inputs[| 11].getValue();
2022-01-13 05:24:03 +01:00
2023-01-01 02:06:02 +01:00
_3d_local_transform(_lpos, _lrot, _lsca);
2022-01-13 05:24:03 +01:00
2023-01-01 02:06:02 +01:00
for(var i = 0; i < array_length(VB); i++) {
if(i >= array_length(materialIndex)) continue;
var mIndex = materialIndex[i];
var tex = inputs[| input_length + mIndex].getValue();
if(!is_surface(tex)) continue;
vertex_submit(VB[i], pr_trianglelist, surface_get_texture(tex));
2022-01-13 05:24:03 +01:00
}
2022-12-12 09:08:03 +01:00
2023-01-01 02:06:02 +01:00
_3d_clear_local_transform();
2022-01-13 05:24:03 +01:00
}
2023-07-06 19:49:16 +02:00
static update = function(frame = PROJECT.animator.current_frame) {
2022-01-13 05:24:03 +01:00
if(!surface_exists(tex_surface)) reset_tex();
if(do_reset_material) {
array_resize(input_display_list, input_display_len);
2023-06-17 18:59:20 +02:00
2022-12-12 09:08:03 +01:00
while(ds_list_size(inputs) > input_length)
ds_list_delete(inputs, input_length);
2022-01-13 05:24:03 +01:00
2022-12-12 09:08:03 +01:00
for(var i = 0; i < array_length(materialNames); i++)
2022-01-13 05:24:03 +01:00
createMaterial(i);
do_reset_material = false;
}
2023-01-01 02:06:02 +01:00
var _dim = inputs[| 2].getValue();
var _pos = inputs[| 3].getValue();
//var _rot = inputs[| 4].getValue();
var _sca = inputs[| 5].getValue();
2022-12-12 09:08:03 +01:00
2023-01-01 02:06:02 +01:00
var _ldir = inputs[| 6].getValue();
var _lhgt = inputs[| 7].getValue();
var _lint = inputs[| 8].getValue();
var _lclr = inputs[| 9].getValue();
2022-12-12 09:08:03 +01:00
var _aclr = inputs[| 10].getValue();
2023-01-01 02:06:02 +01:00
var _lpos = inputs[| 14].getValue();
var _lrot = inputs[| 13].getValue();
var _lsca = inputs[| 11].getValue();
2022-01-13 05:24:03 +01:00
2023-01-09 03:14:20 +01:00
var _proj = inputs[| 15].getValue();
var _fov = inputs[| 16].getValue();
2023-02-23 07:02:19 +01:00
var _dimS = inputs[| 17].getValue();
2023-01-09 03:14:20 +01:00
2023-01-17 08:11:55 +01:00
inputs[| 16].setVisible(_proj == 1);
2022-01-13 05:24:03 +01:00
2023-07-25 20:12:40 +02:00
for( var i = 0, n = array_length(output_display_list) - 1; i < n; i++ ) {
2023-01-09 03:14:20 +01:00
var ind = output_display_list[i];
var _outSurf = outputs[| ind].getValue();
var pass = "diff";
switch(ind) {
case 0 : pass = "diff" break;
case 2 : pass = "norm" break;
}
2023-02-23 07:02:19 +01:00
2023-06-13 14:42:06 +02:00
var _transform = new __3d_transform(_pos,, _sca, _lpos, _lrot, _lsca, true, _dimS );
var _light = new __3d_light(_ldir, _lhgt, _lint, _lclr, _aclr);
var _cam = new __3d_camera(_proj, _fov);
_outSurf = _3d_pre_setup(_outSurf, _dim, _transform, _light, _cam, pass);
2023-06-17 18:59:20 +02:00
for(var j = 0; j < array_length(VB); j++) {
if(j >= array_length(materialIndex)) continue;
var mIndex = materialIndex[j];
2023-05-03 21:42:17 +02:00
var tex = inputs[| input_length + mIndex].getValue();
if(!is_surface(tex)) continue;
2023-06-17 18:59:20 +02:00
vertex_submit(VB[j], pr_trianglelist, surface_get_texture(tex));
2023-05-03 21:42:17 +02:00
}
2023-01-09 03:14:20 +01:00
_3d_post_setup();
2023-05-03 21:42:17 +02:00
outputs[| ind].setValue(_outSurf);
2023-01-09 03:14:20 +01:00
}
2022-01-13 05:24:03 +01:00
}
2023-02-23 07:02:19 +01:00
static onCleanUp = function() {
surface_free(tex_surface);
}
2022-01-13 05:24:03 +01:00
}