Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added "Minecraft Image to Blocks Model" plugin. #614

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -989,5 +989,17 @@
"PBR"
],
"min_version": "4.10.4"
},
"minecraft_image_to_blocks": {
"title": "Image to Blocks Model",
"icon": "logo.png",
"author": "Markus Bordihn (Kaworru)",
"tags": ["Minecraft", "Image", "Blocks"],
"version": "1.0.0",
"min_version": "4.10.4",
"description": "Converts an image into a 3D block model based on pixels with various options",
"website": "https://github.com/MarkusBordihn/Blockbench-Plugin-Minecraft_Image_To_Blocks",
"variant": "both",
"has_changelog": true
}
}
21 changes: 21 additions & 0 deletions plugins/minecraft_image_to_blocks/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# MIT License

Copyright (c) 2024 Markus Bordihn

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
94 changes: 94 additions & 0 deletions plugins/minecraft_image_to_blocks/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# 🎨 Minecraft Image to Blocks Plugin

This [Blockbench](blockbench) plugin lets you **transform images into blocks**!
Whether you're crafting an intricate design or just starting with a base model, this plugin
simplifies the process by converting any image into block structures. 📸➡️🧱

## 🚀 How to Use

Easily turn images into block models, perfect for **initial layouts** or **detailed designs**.
Typically, you'd begin by creating a basic block layout, then fine-tune it into your final Minecraft
model.

### 🖼️ Breaking Down Your Image into Layers

For the best results, try breaking your image into **different layers**.
Let's say you're working with an image of a shield.

![Example of different layers](https://github.com/MarkusBordihn/Blockbench-Plugin-Minecraft_Image_To_Blocks/blob/main/images/soul_shield.png?raw=true)

The **Layer breakdown** might look like this:

- **Layer 1**: The core shape of the shield.

![Example of layer 1](https://github.com/MarkusBordihn/Blockbench-Plugin-Minecraft_Image_To_Blocks/blob/main/images/soul_shield_layer_1.png?raw=true)

- **Layer 2**: Decorative elements, such as symbols or patterns.

![Example of layer 2](https://github.com/MarkusBordihn/Blockbench-Plugin-Minecraft_Image_To_Blocks/blob/main/images/soul_shield_layer_2.png?raw=true)

### 🛠️ Creating the Model

Once you've layered your image, you're ready to generate the **base model**. Follow these steps:

1. Create a new **Java Block/Item** model.
2. Navigate to **File → Import → Import Image to Blocks Model**.
3. Select your image file.

After the image is processed, it will convert into blocks. 🎨✨
Your result should look something like this:

![Example of the generated blocks](https://github.com/MarkusBordihn/Blockbench-Plugin-Minecraft_Image_To_Blocks/blob/main/images/soul_shield_example_base.png?raw=true)

Now you can adjust and modify the blocks to refine your model!

### ✨ Adding Details and Decorations

In this example, I added a few extra blocks to finalize the model with some additional texture. 🌟

![Example of the final model](https://github.com/MarkusBordihn/Blockbench-Plugin-Minecraft_Image_To_Blocks/blob/main/images/soul_shield_example_final.png?raw=true)

Notice that I used the **original texture** for the final look, rather than the individual layers.
Layers are primarily useful for structuring your model's base.

### 🎯 Finalizing the Model

In this case, the final model consists of only **12 blocks**. Be sure to adjust the **position** and
**size** of each block for optimal display in-game.

Here’s how it might look in Minecraft:

![Example of the final model in the game](https://github.com/MarkusBordihn/Blockbench-Plugin-Minecraft_Image_To_Blocks/blob/main/images/soul_shield_example_game.png?raw=true)

## ⚙️ Import Options

This plugin offers a variety of options to customize your block model. **Default settings** work
well for most cases, but here’s what you can tweak:

- **Image**: Select the image file you want to convert.
- **Use Color Values for Merging**: Merge blocks with the same color (works only when "Optimize
Blocks" is enabled).
- **Optimize Blocks**: Reduces block count by optimizing block placement and size.
- **Mapping Texture**: Automatically maps the texture onto the created blocks.

## 🧩 Tips and Tricks

- 🔧 The optimization algorithm is quite powerful, but **manual adjustments** can further improve
results.
- 🚀 Consider using the "Optimize" plugin to reduce the number of **rendered faces** on the final
model, this improves in-game performance.
- 🎯 **Keep it simple**! If your texture is too complex, break it into smaller parts to avoid
performance issues.
- 🖼️ You can import **multiple images** to create more complex models, but be cautious—this can
increase the number of blocks and faces, which could affect performance.

With these steps, you'll have a beautiful, efficient model in no time! Happy building! 🎉

## 📝 Issues and Feedback

Found a bug or have suggestions? 🐛💡 Feel free to report any issues or share your feedback on the
plugin's GitHub page. Your input helps make the plugin even better! 🚀

[blockbench]: https://blockbench.net/

[issue]: https://github.com/MarkusBordihn/Blockbench-Plugin-Minecraft_Image_To_Blocks/issues
15 changes: 15 additions & 0 deletions plugins/minecraft_image_to_blocks/changelog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"1.0.0": {
"title": "1.0.0",
"date": "2024-09-11",
"author": "Markus Bordihn",
"categories": [
{
"title": "New Features",
"list": [
"Initial release"
]
}
]
}
}
Binary file added plugins/minecraft_image_to_blocks/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions plugins/minecraft_image_to_blocks/members.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
maintainers:
- MarkusBordihn

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions plugins/minecraft_image_to_blocks/src/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# MIT License

Copyright (c) 2024 Markus Bordihn

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
25 changes: 25 additions & 0 deletions plugins/minecraft_image_to_blocks/src/fileUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2024 Markus Bordihn
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

export function getFileNameFromPath(filePath) {
filePath = filePath.replace(/\\/g, '/');
const segments = filePath.split('/');
const fileName = segments.pop().split('.')[0];
return fileName.toLowerCase();
}
42 changes: 42 additions & 0 deletions plugins/minecraft_image_to_blocks/src/imageReader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2024 Markus Bordihn
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

import fs from 'fs';

export function readImageFile(filePath, callback) {
if (typeof filePath !== 'string') {
console.error('Invalid file path');
return;
}

fs.readFile(filePath, (err, data) => {
if (err) {
console.error('Error reading file:', err);
return;
}

const base64Image = `data:image/png;base64,${data.toString('base64')}`;
const img = new Image();
img.onload = () => {
console.log('Image loaded successfully');
callback(img);
};
img.src = base64Image;
});
}
100 changes: 100 additions & 0 deletions plugins/minecraft_image_to_blocks/src/imageToBlock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright 2024 Markus Bordihn
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

import {getFileNameFromPath} from "./fileUtils";
import {
adjustProjectTextureSize,
applyTextureToBlocks,
createTextureFromImage
} from "./textureUtils";
import {optimizeBlocks} from "./optimizeBlocks";

export function createBlockModelFromImage(
filePath,
image, useColorForMerging,
shouldOptimizeBlocks,
shouldMapTexture) {
const canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
const ctx = canvas.getContext("2d");

ctx.save();
ctx.translate(0, canvas.height);
ctx.scale(1, -1);
ctx.drawImage(image, 0, 0);

const {data: pixels} = ctx.getImageData(0, 0, canvas.width, canvas.height);
const pixelMatrix = Array.from({length: canvas.height}, (_, y) =>
Array.from({length: canvas.width}, (_, x) => {
const [r, g, b, a] = pixels.slice((y * canvas.width + x) * 4,
(y * canvas.width + x) * 4 + 4);
return a > 0 ? {r, g, b} : null;
})
);

const blocks = shouldOptimizeBlocks
? optimizeBlocks(pixelMatrix, useColorForMerging)
: getBlocks(pixelMatrix, useColorForMerging);

const fileName = getFileNameFromPath(filePath).toLowerCase();
const group = new Group({name: fileName}).init();

if (shouldMapTexture) {
const texture = createTextureFromImage(image, filePath,
`${fileName}_texture`);
adjustProjectTextureSize(texture);
applyTextureToBlocks(blocks, group, texture);
} else {
mapBlocksToCubes(blocks, group);
}

Canvas.updateAll();
Blockbench.showQuickMessage("Block model created successfully!", 2000);
}

function mapBlocksToCubes(blocks, group) {
blocks.forEach(({x, y, width, height, color}) => {
new Cube({
from: [x, y, 0],
to: [x + width, y + height, 1],
color: new THREE.Color(`rgb(${color.r}, ${color.g}, ${color.b})`),
}).addTo(group).init();
});
}

function getBlocks(matrix, useColorForMerging) {
const blocks = [];
const visited = Array.from({length: matrix.length},
() => Array(matrix[0].length).fill(false));

for (let y = 0; y < matrix.length; y++) {
for (let x = 0; x < matrix[0].length; x++) {
if (!visited[y][x] && matrix[y][x]) {
const color = matrix[y][x];
blocks.push({
x, y, width: 1, height: 1,
color: useColorForMerging ? color : {r: 255, g: 255, b: 255},
});
visited[y][x] = true;
}
}
}
return blocks;
}
Loading