mirror of
https://github.com/Ttanasart-pt/Pixel-Composer.git
synced 2025-02-26 11:44:52 +01:00
- New mesh export node.
This commit is contained in:
parent
be99110708
commit
e67d134d2a
10 changed files with 298 additions and 5 deletions
|
@ -637,6 +637,7 @@
|
|||
{"name":"node_3d_material","order":10,"path":"scripts/node_3d_material/node_3d_material.yy",},
|
||||
{"name":"node_3d_mesh_cone","order":6,"path":"scripts/node_3d_mesh_cone/node_3d_mesh_cone.yy",},
|
||||
{"name":"node_3d_mesh_cylinder","order":3,"path":"scripts/node_3d_mesh_cylinder/node_3d_mesh_cylinder.yy",},
|
||||
{"name":"node_3d_mesh_export","order":14,"path":"scripts/node_3d_mesh_export/node_3d_mesh_export.yy",},
|
||||
{"name":"node_3d_mesh_extrude","order":8,"path":"scripts/node_3d_mesh_extrude/node_3d_mesh_extrude.yy",},
|
||||
{"name":"node_3d_mesh_obj","order":2,"path":"scripts/node_3d_mesh_obj/node_3d_mesh_obj.yy",},
|
||||
{"name":"node_3d_mesh_plane","order":7,"path":"scripts/node_3d_mesh_plane/node_3d_mesh_plane.yy",},
|
||||
|
@ -1630,6 +1631,7 @@
|
|||
{"name":"s_node_3d_light_point","order":18,"path":"sprites/s_node_3d_light_point/s_node_3d_light_point.yy",},
|
||||
{"name":"s_node_3d_meterial","order":12,"path":"sprites/s_node_3d_meterial/s_node_3d_meterial.yy",},
|
||||
{"name":"s_node_3d_obj_combine","order":5,"path":"sprites/s_node_3d_obj_combine/s_node_3d_obj_combine.yy",},
|
||||
{"name":"s_node_3d_obj_export","order":30,"path":"sprites/s_node_3d_obj_export/s_node_3d_obj_export.yy",},
|
||||
{"name":"s_node_3d_obj","order":3,"path":"sprites/s_node_3d_obj/s_node_3d_obj.yy",},
|
||||
{"name":"s_node_3d_plane","order":6,"path":"sprites/s_node_3d_plane/s_node_3d_plane.yy",},
|
||||
{"name":"s_node_3d_point_affector","order":21,"path":"sprites/s_node_3d_point_affector/s_node_3d_point_affector.yy",},
|
||||
|
|
|
@ -1017,6 +1017,7 @@
|
|||
{"id":{"name":"node_3d_mesh_cone","path":"scripts/node_3d_mesh_cone/node_3d_mesh_cone.yy",},},
|
||||
{"id":{"name":"node_3d_mesh_cube","path":"scripts/node_3d_mesh_cube/node_3d_mesh_cube.yy",},},
|
||||
{"id":{"name":"node_3d_mesh_cylinder","path":"scripts/node_3d_mesh_cylinder/node_3d_mesh_cylinder.yy",},},
|
||||
{"id":{"name":"node_3d_mesh_export","path":"scripts/node_3d_mesh_export/node_3d_mesh_export.yy",},},
|
||||
{"id":{"name":"node_3d_mesh_extrude","path":"scripts/node_3d_mesh_extrude/node_3d_mesh_extrude.yy",},},
|
||||
{"id":{"name":"node_3d_mesh_obj","path":"scripts/node_3d_mesh_obj/node_3d_mesh_obj.yy",},},
|
||||
{"id":{"name":"node_3d_mesh_plane","path":"scripts/node_3d_mesh_plane/node_3d_mesh_plane.yy",},},
|
||||
|
@ -2172,6 +2173,7 @@
|
|||
{"id":{"name":"s_node_3d_light_point","path":"sprites/s_node_3d_light_point/s_node_3d_light_point.yy",},},
|
||||
{"id":{"name":"s_node_3d_meterial","path":"sprites/s_node_3d_meterial/s_node_3d_meterial.yy",},},
|
||||
{"id":{"name":"s_node_3d_obj_combine","path":"sprites/s_node_3d_obj_combine/s_node_3d_obj_combine.yy",},},
|
||||
{"id":{"name":"s_node_3d_obj_export","path":"sprites/s_node_3d_obj_export/s_node_3d_obj_export.yy",},},
|
||||
{"id":{"name":"s_node_3d_obj","path":"sprites/s_node_3d_obj/s_node_3d_obj.yy",},},
|
||||
{"id":{"name":"s_node_3d_plane","path":"sprites/s_node_3d_plane/s_node_3d_plane.yy",},},
|
||||
{"id":{"name":"s_node_3d_point_affector","path":"sprites/s_node_3d_point_affector/s_node_3d_point_affector.yy",},},
|
||||
|
|
|
@ -5,19 +5,19 @@
|
|||
global.VF_POS_COL = vertex_format_end();
|
||||
|
||||
vertex_format_begin();
|
||||
vertex_format_add_position_3d();
|
||||
vertex_format_add_normal();
|
||||
vertex_format_add_texcoord();
|
||||
vertex_format_add_color();
|
||||
vertex_format_add_position_3d(); // x y z // 12
|
||||
vertex_format_add_normal(); // x y z // 12
|
||||
vertex_format_add_texcoord(); // u v // 8
|
||||
vertex_format_add_color(); // r g b a // 4
|
||||
global.VF_POS_NORM_TEX_COL = vertex_format_end();
|
||||
global.VF_POS_NORM_TEX_COL_size = 36;
|
||||
#endregion
|
||||
|
||||
function __3dObject() constructor {
|
||||
vertex = [];
|
||||
VB = [];
|
||||
normal_vertex = [];
|
||||
object_counts = 1;
|
||||
VB = [];
|
||||
|
||||
NVB = noone;
|
||||
normal_draw_size = 0.2;
|
||||
|
|
173
scripts/node_3d_mesh_export/node_3d_mesh_export.gml
Normal file
173
scripts/node_3d_mesh_export/node_3d_mesh_export.gml
Normal file
|
@ -0,0 +1,173 @@
|
|||
function Node_3D_Mesh_Export(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
|
||||
name = "Mesh Export";
|
||||
|
||||
inputs[| 0] = nodeValue("Mesh", self, JUNCTION_CONNECT.input, VALUE_TYPE.d3Mesh, noone)
|
||||
.setVisible(true, true);
|
||||
|
||||
inputs[| 1] = nodeValue("Paths", self, JUNCTION_CONNECT.input, VALUE_TYPE.path, "")
|
||||
.setDisplay(VALUE_DISPLAY.path_save, { filter: "Obj (.obj)|*.obj" })
|
||||
.setVisible(true);
|
||||
|
||||
inputs[| 2] = nodeValue("Export Texture", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true);
|
||||
|
||||
inputs[| 3] = nodeValue("Invert UV", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
|
||||
|
||||
input_display_list = [ 0,
|
||||
["Export", false], 1, 2, 3,
|
||||
];
|
||||
|
||||
|
||||
insp1UpdateTooltip = "Export";
|
||||
insp1UpdateIcon = [ THEME.sequence_control, 1, COLORS._main_value_positive ];
|
||||
|
||||
static onInspector1Update = function() { export(); }
|
||||
|
||||
static export = function() {
|
||||
var _mesh = getInputData(0);
|
||||
var _path = getInputData(1);
|
||||
var _mat = getInputData(2);
|
||||
var _invv = getInputData(3);
|
||||
|
||||
if(_mesh == noone) return;
|
||||
if(!is_instanceof(_mesh, __3dObject)) return;
|
||||
|
||||
var _vbs = _mesh.VB;
|
||||
|
||||
var _mtlPath = filename_dir(_path) + "\\" + filename_name_only(_path) + ".mtl";
|
||||
var _mtlName = filename_name(_mtlPath);
|
||||
var _mtl = "# Pixel Composer\n";
|
||||
var _obj = "# Pixel Composer\n";
|
||||
if(_mat) _obj += $"mtllib {_mtlName}\n";
|
||||
|
||||
for (var i = 0, n = array_length(_vbs); i < n; i++) {
|
||||
var _vb = _vbs[i];
|
||||
|
||||
var _buffer = buffer_create_from_vertex_buffer(_vb, buffer_fixed, 1);
|
||||
var _buffer_s = buffer_get_size(_buffer);
|
||||
|
||||
_obj += $"o shape{i}\n";
|
||||
|
||||
if(_mat) {
|
||||
var _matName = $"mat.{i}";
|
||||
var _material = array_safe_get_fast(_mesh.materials, i, 0);
|
||||
|
||||
if(_material) {
|
||||
_mtl += $"newmtl {_matName}\n";
|
||||
_obj += $"usemtl {_matName}\n";
|
||||
|
||||
if(is_surface(_material.surface)) {
|
||||
var _surfPath = $"{filename_dir(_path)}\\{filename_name_only(_path)}_texture{i}.png";
|
||||
surface_save(_material.surface, _surfPath);
|
||||
_mtl += $"map_Kd {_surfPath}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var _obj_v = "";
|
||||
var _obj_vn = "";
|
||||
var _obj_vt = "";
|
||||
var _obj_f = "";
|
||||
|
||||
var _map_v = ds_map_create();
|
||||
var _map_vn = ds_map_create();
|
||||
var _map_vt = ds_map_create();
|
||||
var _map_f = ds_map_create();
|
||||
|
||||
switch(_mesh.VF) {
|
||||
case global.VF_POS_NORM_TEX_COL :
|
||||
var _format_s = global.VF_POS_NORM_TEX_COL_size;
|
||||
var _vertex_s = floor(_buffer_s / _format_s);
|
||||
var _ind = 0;
|
||||
buffer_to_start(_buffer);
|
||||
|
||||
var _idx_v = [ 0, 0, 0 ];
|
||||
var _idx_vn = [ 0, 0, 0 ];
|
||||
var _idx_vt = [ 0, 0, 0 ];
|
||||
|
||||
ds_map_clear(_map_v);
|
||||
ds_map_clear(_map_vn);
|
||||
ds_map_clear(_map_vt);
|
||||
ds_map_clear(_map_f);
|
||||
|
||||
repeat(_vertex_s) {
|
||||
var _px = buffer_read(_buffer, buffer_f32);
|
||||
var _py = buffer_read(_buffer, buffer_f32);
|
||||
var _pz = buffer_read(_buffer, buffer_f32);
|
||||
|
||||
var _nx = buffer_read(_buffer, buffer_f32);
|
||||
var _ny = buffer_read(_buffer, buffer_f32);
|
||||
var _nz = buffer_read(_buffer, buffer_f32);
|
||||
|
||||
var _u = buffer_read(_buffer, buffer_f32);
|
||||
var _v = buffer_read(_buffer, buffer_f32);
|
||||
if(_invv) _v = 1. - _v;
|
||||
|
||||
var _r = buffer_read(_buffer, buffer_s8);
|
||||
var _g = buffer_read(_buffer, buffer_s8);
|
||||
var _b = buffer_read(_buffer, buffer_s8);
|
||||
var _a = buffer_read(_buffer, buffer_s8);
|
||||
|
||||
var __v = $"v {string_format(_px, -1, 5)} {string_format(_py, -1, 5)} {string_format(_pz, -1, 5)}";
|
||||
var __vn = $"vn {string_format(_nx, -1, 5)} {string_format(_ny, -1, 5)} {string_format(_nz, -1, 5)}";
|
||||
var __vt = $"vt {string_format(_u, -1, 5)} {string_format(_v, -1, 5)}";
|
||||
|
||||
var _id_v, _id_vn, _id_vt;
|
||||
|
||||
if(ds_map_exists(_map_v, __v)) {
|
||||
_id_v = _map_v[? __v];
|
||||
} else {
|
||||
_id_v = ds_map_size(_map_v) + 1;
|
||||
_map_v[? __v] = _id_v;
|
||||
_obj_v += $"{__v} \n";
|
||||
}
|
||||
|
||||
if(ds_map_exists(_map_vn, __vn)) {
|
||||
_id_vn = _map_vn[? __vn];
|
||||
} else {
|
||||
_id_vn = ds_map_size(_map_vn) + 1;
|
||||
_map_vn[? __vn] = _id_vn;
|
||||
_obj_vn += $"{__vn} \n";
|
||||
}
|
||||
|
||||
if(ds_map_exists(_map_vt, __vt)) {
|
||||
_id_vt = _map_vt[? __vt];
|
||||
} else {
|
||||
_id_vt = ds_map_size(_map_vt) + 1;
|
||||
_map_vt[? __vt] = _id_vt;
|
||||
_obj_vt += $"{__vt} \n";
|
||||
}
|
||||
|
||||
_idx_v[_ind % 3] = _id_v;
|
||||
_idx_vn[_ind % 3] = _id_vn;
|
||||
_idx_vt[_ind % 3] = _id_vt;
|
||||
|
||||
if(_ind % 3 == 2) _obj_f += $"f {_idx_v[0]}/{_idx_vt[0]}/{_idx_vn[0]} {_idx_v[1]}/{_idx_vt[1]}/{_idx_vn[1]} {_idx_v[2]}/{_idx_vt[2]}/{_idx_vn[2]}\n";
|
||||
_ind++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ds_map_destroy(_map_v);
|
||||
ds_map_destroy(_map_vn);
|
||||
ds_map_destroy(_map_vt);
|
||||
ds_map_destroy(_map_f);
|
||||
|
||||
_obj += _obj_v + "\n";
|
||||
_obj += _obj_vn + "\n";
|
||||
_obj += _obj_vt + "\n";
|
||||
_obj += _obj_f + "\n";
|
||||
|
||||
buffer_delete(_buffer);
|
||||
}
|
||||
|
||||
file_text_write_all( _path, _obj);
|
||||
if(_mat) file_text_write_all(_mtlPath, _mtl);
|
||||
|
||||
var noti = log_message("EXPORT", $"Export model complete.", THEME.noti_icon_tick, COLORS._main_value_positive, false);
|
||||
noti.path = filename_dir(_path);
|
||||
noti.setOnClick(function() { shellOpenExplorer(self.path); }, "Open in explorer", THEME.explorer);
|
||||
}
|
||||
|
||||
static update = function() {}
|
||||
|
||||
}
|
13
scripts/node_3d_mesh_export/node_3d_mesh_export.yy
Normal file
13
scripts/node_3d_mesh_export/node_3d_mesh_export.yy
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"$GMScript":"",
|
||||
"%Name":"node_3d_mesh_export",
|
||||
"isCompatibility":false,
|
||||
"isDnD":false,
|
||||
"name":"node_3d_mesh_export",
|
||||
"parent":{
|
||||
"name":"3D",
|
||||
"path":"folders/nodes/data/3D.yy",
|
||||
},
|
||||
"resourceType":"GMScript",
|
||||
"resourceVersion":"2.0",
|
||||
}
|
12
scripts/node_3d_mesh_export/node_counter.yy
Normal file
12
scripts/node_3d_mesh_export/node_counter.yy
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"isDnD": false,
|
||||
"isCompatibility": false,
|
||||
"parent": {
|
||||
"name": "variable",
|
||||
"path": "folders/nodes/data/variable.yy",
|
||||
},
|
||||
"resourceVersion": "1.0",
|
||||
"name": "node_counter",
|
||||
"tags": [],
|
||||
"resourceType": "GMScript",
|
||||
}
|
|
@ -661,6 +661,7 @@ function __initNodes() {
|
|||
addNodeObject(d3d, "3D Scene", s_node_3d_scene, "Node_3D_Scene", [1, Node_3D_Scene],, "Combine multiple 3D objects into a single junction.").setVersion(11510);
|
||||
addNodeObject(d3d, "3D Repeat", s_node_3d_array, "Node_3D_Repeat", [1, Node_3D_Repeat],, "Repeat the same 3D mesh multiple times.").setVersion(11510);
|
||||
addNodeObject(d3d, "Transform 3D", s_node_image_transform_3d, "Node_3D_Transform_Image", [1, Node_3D_Transform_Image],, "Transform image in 3D space").setVersion(11600);
|
||||
addNodeObject(d3d, "Mesh Export", s_node_3d_obj_export, "Node_3D_Mesh_Export", [1, Node_3D_Mesh_Export],, "Export 3D mesh as .obj file").setVersion(11740);
|
||||
|
||||
ds_list_add(d3d, "Mesh");
|
||||
addNodeObject(d3d, "3D Object", s_node_3d_obj, "Node_3D_Mesh_Obj", [0, Node_create_3D_Obj],, "Load .obj file from your computer as a 3D object.").setVersion(11510);
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
90
sprites/s_node_3d_obj_export/s_node_3d_obj_export.yy
Normal file
90
sprites/s_node_3d_obj_export/s_node_3d_obj_export.yy
Normal file
|
@ -0,0 +1,90 @@
|
|||
{
|
||||
"$GMSprite":"",
|
||||
"%Name":"s_node_3d_obj_export",
|
||||
"bboxMode":0,
|
||||
"bbox_bottom":63,
|
||||
"bbox_left":4,
|
||||
"bbox_right":63,
|
||||
"bbox_top":6,
|
||||
"collisionKind":1,
|
||||
"collisionTolerance":0,
|
||||
"DynamicTexturePage":false,
|
||||
"edgeFiltering":false,
|
||||
"For3D":false,
|
||||
"frames":[
|
||||
{"$GMSpriteFrame":"","%Name":"1fe6f9a1-3122-4252-8359-48f017365596","name":"1fe6f9a1-3122-4252-8359-48f017365596","resourceType":"GMSpriteFrame","resourceVersion":"2.0",},
|
||||
],
|
||||
"gridX":0,
|
||||
"gridY":0,
|
||||
"height":64,
|
||||
"HTile":false,
|
||||
"layers":[
|
||||
{"$GMImageLayer":"","%Name":"c12fe317-c955-41e7-a157-32e91731ee30","blendMode":0,"displayName":"default","isLocked":false,"name":"c12fe317-c955-41e7-a157-32e91731ee30","opacity":100.0,"resourceType":"GMImageLayer","resourceVersion":"2.0","visible":true,},
|
||||
],
|
||||
"name":"s_node_3d_obj_export",
|
||||
"nineSlice":null,
|
||||
"origin":4,
|
||||
"parent":{
|
||||
"name":"3D",
|
||||
"path":"folders/nodes/icons/3D.yy",
|
||||
},
|
||||
"preMultiplyAlpha":false,
|
||||
"resourceType":"GMSprite",
|
||||
"resourceVersion":"2.0",
|
||||
"sequence":{
|
||||
"$GMSequence":"",
|
||||
"%Name":"s_node_3d_obj_export",
|
||||
"autoRecord":true,
|
||||
"backdropHeight":768,
|
||||
"backdropImageOpacity":0.5,
|
||||
"backdropImagePath":"",
|
||||
"backdropWidth":1366,
|
||||
"backdropXOffset":0.0,
|
||||
"backdropYOffset":0.0,
|
||||
"events":{
|
||||
"$KeyframeStore<MessageEventKeyframe>":"",
|
||||
"Keyframes":[],
|
||||
"resourceType":"KeyframeStore<MessageEventKeyframe>",
|
||||
"resourceVersion":"2.0",
|
||||
},
|
||||
"eventStubScript":null,
|
||||
"eventToFunction":{},
|
||||
"length":1.0,
|
||||
"lockOrigin":false,
|
||||
"moments":{
|
||||
"$KeyframeStore<MomentsEventKeyframe>":"",
|
||||
"Keyframes":[],
|
||||
"resourceType":"KeyframeStore<MomentsEventKeyframe>",
|
||||
"resourceVersion":"2.0",
|
||||
},
|
||||
"name":"s_node_3d_obj_export",
|
||||
"playback":1,
|
||||
"playbackSpeed":30.0,
|
||||
"playbackSpeedType":0,
|
||||
"resourceType":"GMSequence",
|
||||
"resourceVersion":"2.0",
|
||||
"showBackdrop":true,
|
||||
"showBackdropImage":false,
|
||||
"timeUnits":1,
|
||||
"tracks":[
|
||||
{"$GMSpriteFramesTrack":"","builtinName":0,"events":[],"inheritsTrackColour":true,"interpolation":1,"isCreationTrack":false,"keyframes":{"$KeyframeStore<SpriteFrameKeyframe>":"","Keyframes":[
|
||||
{"$Keyframe<SpriteFrameKeyframe>":"","Channels":{
|
||||
"0":{"$SpriteFrameKeyframe":"","Id":{"name":"1fe6f9a1-3122-4252-8359-48f017365596","path":"sprites/s_node_3d_obj_export/s_node_3d_obj_export.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",},
|
||||
},"Disabled":false,"id":"68e1dc21-23ce-44b4-ac1c-048da2846c01","IsCreationKey":false,"Key":0.0,"Length":1.0,"resourceType":"Keyframe<SpriteFrameKeyframe>","resourceVersion":"2.0","Stretch":false,},
|
||||
],"resourceType":"KeyframeStore<SpriteFrameKeyframe>","resourceVersion":"2.0",},"modifiers":[],"name":"frames","resourceType":"GMSpriteFramesTrack","resourceVersion":"2.0","spriteId":null,"trackColour":0,"tracks":[],"traits":0,},
|
||||
],
|
||||
"visibleRange":null,
|
||||
"volume":1.0,
|
||||
"xorigin":32,
|
||||
"yorigin":32,
|
||||
},
|
||||
"swatchColours":null,
|
||||
"swfPrecision":0.5,
|
||||
"textureGroupId":{
|
||||
"name":"Default",
|
||||
"path":"texturegroups/Default",
|
||||
},
|
||||
"type":0,
|
||||
"VTile":false,
|
||||
"width":64,
|
||||
}
|
Loading…
Add table
Reference in a new issue