mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-02-17 16:20:13 +08:00
Initial mesh rendering
This commit is contained in:
parent
49b1da4dd9
commit
5fe1d62424
@ -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'}),
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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({
|
||||
|
@ -1400,6 +1400,7 @@ Interface.definePanels(function() {
|
||||
},
|
||||
menu: new Menu([
|
||||
'add_cube',
|
||||
'add_mesh',
|
||||
'add_group',
|
||||
'_',
|
||||
'sort_outliner',
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user