Initial mesh rendering

This commit is contained in:
JannisX11 2021-07-28 17:49:09 +02:00
parent 49b1da4dd9
commit 5fe1d62424
8 changed files with 292 additions and 23 deletions

View File

@ -308,7 +308,7 @@ class Tool extends Action {
this.modes = data.modes;
this.selectFace = data.selectFace;
this.cursor = data.cursor;
this.selectCubes = data.selectCubes !== false;
this.selectElements = data.selectElements !== false;
this.paintTool = data.paintTool;
this.brushTool = data.brushTool;
this.transformerMode = data.transformerMode;
@ -1378,7 +1378,7 @@ const BARS = {
transformerMode: 'hidden',
toolbar: 'vertex_snap',
category: 'tools',
selectCubes: true,
selectElements: true,
cursor: 'copy',
modes: ['edit'],
keybind: new Keybind({key: 'x'}),

View File

@ -10,7 +10,7 @@ class Mode extends KeybindItem {
this.selected = false
this.default_tool = data.default_tool;
this.selectCubes = data.selectCubes !== false
this.selectElements = data.selectElements !== false
this.center_windows = data.center_windows||[];
this.hide_toolbars = data.hide_toolbars
@ -202,7 +202,7 @@ BARS.defineActions(function() {
},
})
new Mode('display', {
selectCubes: false,
selectElements: false,
default_tool: 'move_tool',
category: 'navigate',
condition: () => Format.display_mode,

View File

@ -840,7 +840,7 @@ new NodePreviewController(Cube, {
this.updateFaces(element);
if (Prop.view_mode === 'textured') {
Canvas.updateUV(element);
this.updateUV(element);
}
mesh.visible = element.visibility;
Canvas.buildOutline(element);

View File

@ -1,8 +1,89 @@
class MeshFace {
constructor(mesh, data) {
this.mesh = mesh;
//this.vertices = [];
//this.normal = [0, 1, 0];
this.texture = false;
this.uv = {};
for (var key in MeshFace.properties) {
MeshFace.properties[key].reset(this);
}
this.extend(data);
}
extend(data) {
for (var key in MeshFace.properties) {
MeshFace.properties[key].merge(this, data)
}
if (data.texture === null) {
this.texture = null;
} else if (data.texture === false) {
this.texture = false;
} else if (Texture.all.includes(data.texture)) {
this.texture = data.texture.uuid;
} else if (typeof data.texture === 'string') {
Merge.string(this, data, 'texture')
}
return this;
}
getSaveCopy() {
var copy = {
uv: this.uv
};
for (var key in MeshFace.properties) {
if (this[key] != MeshFace.properties[key].default) MeshFace.properties[key].copy(this, copy);
}
var tex = this.getTexture()
if (tex === null) {
copy.texture = null;
} else if (tex instanceof Texture) {
copy.texture = Texture.all.indexOf(tex)
}
return copy;
}
getUndoCopy() {
var copy = new MeshFace(this.mesh, this);
delete copy.mesh;
return copy;
}
reset() {
for (var key in Mesh.properties) {
Mesh.properties[key].reset(this);
}
this.texture = false;
return this;
}
getTexture() {
if (Format.single_texture) {
return Texture.getDefault();
}
if (typeof this.texture === 'string') {
return Texture.all.findInArray('uuid', this.texture)
} else {
return this.texture;
}
}
}
new Property(MeshFace, 'array', 'vertices', {default: 0});
new Property(MeshFace, 'vector', 'normal', {default: 0});
class Mesh extends OutlinerElement {
constructor(data, uuid) {
super(data, uuid)
this.vertices = {};
this.faces = [];
if (!data.vertices) {
this.addVertices([1, 1, 1], [1, 1, 0], [1, 0, 1], [1, 0, 0], [0, 1, 1], [0, 1, 0], [0, 0, 1], [0, 0, 0]);
let vertex_keys = Object.keys(this.vertices);
this.faces.push(new MeshFace( this, {vertices: [vertex_keys[0], vertex_keys[1], vertex_keys[2], vertex_keys[3]]} )); // East
this.faces.push(new MeshFace( this, {vertices: [vertex_keys[4], vertex_keys[5], vertex_keys[6], vertex_keys[7]]} )); // West
this.faces.push(new MeshFace( this, {vertices: [vertex_keys[0], vertex_keys[1], vertex_keys[4], vertex_keys[5]]} )); // Up
this.faces.push(new MeshFace( this, {vertices: [vertex_keys[2], vertex_keys[3], vertex_keys[6], vertex_keys[7]]} )); // Down
this.faces.push(new MeshFace( this, {vertices: [vertex_keys[0], vertex_keys[2], vertex_keys[4], vertex_keys[6]]} )); // South
this.faces.push(new MeshFace( this, {vertices: [vertex_keys[1], vertex_keys[3], vertex_keys[5], vertex_keys[7]]} )); // North
}
for (var key in Mesh.properties) {
Mesh.properties[key].reset(this);
}
@ -10,6 +91,42 @@ class Mesh extends OutlinerElement {
this.extend(data)
}
}
get from() {
return this.origin;
}
get vertice_list() {
return Object.keys(this.vertices).map(key => this.vertices[key]);
}
getWorldCenter() {
var m = this.mesh;
var pos = new THREE.Vector3()
let vertice_list = this.vertice_list;
vertice_list.forEach(vector => {
pos.x += vector[0];
pos.y += vector[1];
pos.z += vector[2];
})
pos.x /= vertice_list.length;
pos.y /= vertice_list.length;
pos.z /= vertice_list.length;
if (m) {
var r = m.getWorldQuaternion(new THREE.Quaternion())
pos.applyQuaternion(r)
pos.add(THREE.fastWorldPosition(m, new THREE.Vector3()))
}
return pos;
}
addVertices(...vectors) {
vectors.forEach(vector => {
let key;
while (!key || this.vertices[key]) {
key = bbuid(4);
}
this.vertices[key] = [...vector];
})
}
extend(object) {
for (var key in Mesh.properties) {
Mesh.properties[key].merge(this, object)
@ -39,6 +156,7 @@ class Mesh extends OutlinerElement {
Mesh.prototype.type = 'mesh';
Mesh.prototype.icon = 'fa far fa-gem';
Mesh.prototype.movable = true;
Mesh.prototype.resizable = false;
Mesh.prototype.rotatable = true;
Mesh.prototype.needsUniqueName = false;
Mesh.prototype.menu = new Menu([
@ -102,7 +220,157 @@ new Property(Mesh, 'boolean', 'visibility', {default: true});
OutlinerElement.registerType(Mesh, 'mesh');
new NodePreviewController(Mesh)
new NodePreviewController(Mesh, {
setup(element) {
var mesh = new THREE.Mesh(new THREE.BufferGeometry(1, 1, 1), emptyMaterials[0]);
Project.nodes_3d[element.uuid] = mesh;
mesh.name = element.uuid;
mesh.type = element.type;
mesh.isElement = true;
mesh.geometry.setAttribute('highlight', new THREE.BufferAttribute(new Uint8Array(24).fill(1), 1));
this.updateTransform(element);
this.updateGeometry(element);
this.updateFaces(element);
if (Prop.view_mode === 'textured') {
this.updateUV(element);
}
mesh.visible = element.visibility;
let material = new THREE.PointsMaterial({size: 5, sizeAttenuation: false});
let points = new THREE.Points(mesh.geometry, material)
mesh.add(points);
//Canvas.buildOutline(element);
},
updateGeometry(element) {
let {mesh} = element;
let position_array = [];
let position_indices = [];
let indices = [];
for (let key in element.vertices) {
let vector = element.vertices[key];
position_indices.push(key);
position_array.push(...vector);
}
element.faces.forEach(face => {
if (face.vertices.length == 3) {
// Tri
face.vertices.forEach(key => {
let index = position_indices.indexOf(key);
indices.push(index);
})
} else if (face.vertices.length == 4) {
// Quad
indices.push(position_indices.indexOf(face.vertices[0]));
indices.push(position_indices.indexOf(face.vertices[1]));
indices.push(position_indices.indexOf(face.vertices[2]));
indices.push(position_indices.indexOf(face.vertices[1]));
indices.push(position_indices.indexOf(face.vertices[2]));
indices.push(position_indices.indexOf(face.vertices[3]));
}
})
mesh.geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(position_array), 3));
mesh.geometry.setIndex( indices );
//Canvas.getOutlineMesh(mesh, mesh.outline)
mesh.geometry.computeBoundingBox()
mesh.geometry.computeBoundingSphere()
},
updateFaces(element) {
let {mesh} = element;
let {geometry} = mesh;
/*
if (!geometry.all_faces) geometry.all_faces = geometry.groups.slice();
geometry.groups.empty();
geometry.all_faces.forEach(face => {
let bb_face = element.faces[Canvas.face_order[face.materialIndex]];
if (bb_face && bb_face.texture === null && geometry.groups.includes(face)) {
geometry.groups.remove(face);
} else
if (bb_face && bb_face.texture !== null && !geometry.groups.includes(face)) {
geometry.groups.push(face);
}
})
if (geometry.groups.length == 0) {
// Keep down face if no faces enabled
geometry.groups.push(geometry.all_faces[6], geometry.all_faces[7]);
}
if (Prop.view_mode === 'solid') {
mesh.material = Canvas.solidMaterial
} else if (Prop.view_mode === 'wireframe') {
mesh.material = Canvas.wireframeMaterial
} else if (Format.single_texture && Texture.all.length >= 2 && Texture.all.find(t => t.render_mode == 'layered')) {
mesh.material = Canvas.getLayeredMaterial();
} else if (Format.single_texture) {
let tex = Texture.getDefault();
mesh.material = tex ? tex.getMaterial() : emptyMaterials[element.color];
} else {
var materials = []
Canvas.face_order.forEach(function(face) {
if (cube.faces[face].texture === null) {
materials.push(Canvas.transparentMaterial)
} else {
var tex = cube.faces[face].getTexture()
if (tex && tex.uuid) {
materials.push(Project.materials[tex.uuid])
} else {
materials.push(emptyMaterials[cube.color])
}
}
})
if (materials.allEqual(materials[0])) materials = materials[0];
mesh.material = materials
}*/
},
updateUV(cube, animation = true) {
if (Prop.view_mode !== 'textured') return;
var mesh = cube.mesh
if (mesh === undefined || !mesh.geometry) return;
return;
var stretch = 1
var frame = 0
Canvas.face_order.forEach((face, fIndex) => {
if (cube.faces[face].texture == null) return;
stretch = 1;
frame = 0;
let tex = cube.faces[face].getTexture();
if (tex instanceof Texture && tex.frameCount !== 1) {
stretch = tex.frameCount
if (animation === true && tex.currentFrame) {
frame = tex.currentFrame
}
}
Canvas.updateUVFace(mesh.geometry.attributes.uv, fIndex, cube.faces[face], frame, stretch)
})
mesh.geometry.attributes.uv.needsUpdate = true;
return mesh.geometry;
}
})
BARS.defineActions(function() {
new Action({

View File

@ -1400,6 +1400,7 @@ Interface.definePanels(function() {
},
menu: new Menu([
'add_cube',
'add_mesh',
'add_group',
'_',
'sort_outliner',

View File

@ -347,9 +347,9 @@ class Preview {
this.raycaster.setFromCamera( this.mouse, this.camera );
var objects = []
Cube.all.forEach(cube => {
if (cube.visibility && !cube.locked) {
objects.push(cube.mesh);
Outliner.elements.forEach(element => {
if (element.mesh.geometry && element.visibility && !element.locked) {
objects.push(element.mesh);
}
})
if (Vertexsnap.vertexes.children.length) {
@ -387,17 +387,17 @@ class Preview {
return {
event: event,
type: 'cube',
type: 'element',
intersects: intersects,
face: face,
cube: obj
element: obj
}
} else if (intersect.isVertex) {
return {
event: event,
type: 'vertex',
intersects: intersects,
cube: intersect.cube,
element: intersect.element,
vertex: intersect
}
} else if (intersect.isKeyframe) {
@ -660,7 +660,7 @@ class Preview {
var data = this.raycast(event);
if (data) {
//this.static_rclick = false
if (data.cube && data.cube.locked) {
if (data.element && data.element.locked) {
$('#preview').css('cursor', 'not-allowed')
function resetCursor() {
$('#preview').css('cursor', (Toolbox.selected.cursor ? Toolbox.selected.cursor : 'default'))
@ -668,7 +668,7 @@ class Preview {
}
addEventListeners(document, 'mouseup touchend', resetCursor, false)
} else if (Toolbox.selected.selectCubes && Modes.selected.selectCubes && data.type === 'cube') {
} else if (Toolbox.selected.selectElements && Modes.selected.selectElements && data.type === 'element') {
if (Toolbox.selected.selectFace) {
main_uv.setFace(data.face, false)
}
@ -676,15 +676,15 @@ class Preview {
if (Modes.paint) {
event = 0;
}
if (data.cube.parent.type === 'group' && (
if (data.element.parent.type === 'group' && (
Animator.open ||
event.shiftKey ||
(!Format.rotate_cubes && Format.bone_rig && ['rotate_tool', 'pivot_tool'].includes(Toolbox.selected.id))
)) {
data.cube.parent.select().showInOutliner();
data.element.parent.select().showInOutliner();
} else if (!Animator.open) {
data.cube.select(event)
data.element.select(event)
}
} else if (Animator.open && data.type == 'keyframe') {
if (data.keyframe instanceof Keyframe) {
@ -711,7 +711,7 @@ class Preview {
mousemove(event) {
if (Settings.get('highlight_cubes')) {
var data = this.raycast(event);
if (settings.highlight_cubes.value) updateCubeHighlights(data && data.cube);
if (settings.highlight_cubes.value) updateCubeHighlights(data && data.element);
}
}
mouseup(event) {
@ -748,8 +748,8 @@ class Preview {
Prop.active_panel = 'preview';
if (this.static_rclick && (event.which === 3 || (event.type == 'touchend' && this.rclick_cooldown == true))) {
var data = this.raycast(event)
if (Toolbox.selected.selectCubes && Modes.selected.selectCubes && data && data.cube && !Modes.animate) {
data.cube.showContextMenu(event);
if (Toolbox.selected.selectElements && Modes.selected.selectElements && data && data.element && !Modes.animate) {
data.element.showContextMenu(event);
} else if (data.type == 'keyframe') {
data.keyframe.showContextMenu(event);
@ -853,7 +853,7 @@ class Preview {
ray[uv_axes.v]
)
unselectAll()
elements.forEach(function(cube) {
Outliner.elements.forEach(function(cube) {
if ((event.shiftKey || event.ctrlOrCmd) && scope.selection.old_selected.indexOf(cube) >= 0) {
var isSelected = true

View File

@ -107,7 +107,7 @@ class Property {
if (instance[this.name] instanceof Array == false) {
instance[this.name] = [];
}
instance[this.name].replace(dft);
instance[this.name].replace(dft || []);
} else {
instance[this.name] = dft;
}

View File

@ -217,7 +217,7 @@ const Vertexsnap = {
if (id == 100) {
mesh.rotation.y += Math.PI/4;
}
mesh.cube = cube
mesh.element = cube
mesh.isVertex = true
mesh.vertex_id = id
mesh.material.transparent = true;