图像转换为SceneKit节点 [英] Convert an image to a SceneKit Node
问题描述
我有一个位图图像:
I have a bit-map image:
(然而,这应与任意图像工作)
( However this should work with any arbitrary image )
我想利用我的形象,使之成为3D SCNNode。我已经完成了很多与此code。这需要每个像素的图像,并创建一个SCNBox几何SCNNode。
I want to take my image and make it a 3D SCNNode. I've accomplished that much with this code. That takes each pixel in the image and creates a SCNNode with a SCNBox geometry.
static inline SCNNode* NodeFromSprite(const UIImage* image) {
SCNNode *node = [SCNNode node];
CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
const UInt8* data = CFDataGetBytePtr(pixelData);
for (int x = 0; x < image.size.width; x++)
{
for (int y = 0; y < image.size.height; y++)
{
int pixelInfo = ((image.size.width * y) + x) * 4;
UInt8 alpha = data[pixelInfo + 3];
if (alpha > 3)
{
UInt8 red = data[pixelInfo];
UInt8 green = data[pixelInfo + 1];
UInt8 blue = data[pixelInfo + 2];
UIColor *color = [UIColor colorWithRed:red/255.0f green:green/255.0f blue:blue/255.0f alpha:alpha/255.0f];
SCNNode *pixel = [SCNNode node];
pixel.geometry = [SCNBox boxWithWidth:1.001 height:1.001 length:1.001 chamferRadius:0];
pixel.geometry.firstMaterial.diffuse.contents = color;
pixel.position = SCNVector3Make(x - image.size.width / 2.0,
y - image.size.height / 2.0,
0);
[node addChildNode:pixel];
}
}
}
CFRelease(pixelData);
node = [node flattenedClone];
//The image is upside down and I have no idea why.
node.rotation = SCNVector4Make(1, 0, 0, M_PI);
return node;
}
但问题是,我在做什么占用了办法不多的记忆!
But the problem is that what I'm doing takes up way to much memory!
我试图找到一种方法,使用较少的内存做到这一点。
I'm trying to find a way to do this with less memory.
所有code和资源,可以在这里找到: https://github.com/KonradWright/KNodeFromSprite
All Code and resources can be found at: https://github.com/KonradWright/KNodeFromSprite
推荐答案
现在你绘制每个像素SCNBox某种颜色的,这意味着:
Now you drawing each pixel as SCNBox of certain color, that means:
- 在每框选择一个GL平局
- 的adjancent框之间不必要2隐形面绘制
- 在画的一排同1X1X1箱N将可以得出1x1xN一箱
看起来像普通的Minecraft般的优化问题:
Seems like common Minecraft-like optimization problem:
- 在对待你的形象是3维数组(其中深度通缉图像拉伸深度),再某种颜色的presenting立方体体素的每个元素。
- 使用贪婪网格算法(<一HREF =http://mikolalysenko.github.io/MinecraftMeshes/index.html相对=nofollow>演示)和的自定义SCNGeometry 建立网格SceneKit节点。
- Treat your image is 3-dimensional array (where depth is wanted image extrusion depth), each element representing cube voxel of certain color.
- Use greedy meshing algorithm (demo) and custom SCNGeometry to create mesh for SceneKit node.
伪code为网格算法跳过adjancent立方体面(simplier,但比贪婪的啮合效果较差):
Pseudo-code for meshing algorithm that skips faces of adjancent cubes (simplier, but less effective than greedy meshing):
#define SIZE_X = 16; // image width
#define SIZE_Y = 16; // image height
// pixel data, 0 = transparent pixel
int data[SIZE_X][SIZE_Y];
// check if there is non-transparent neighbour at x, y
BOOL has_neighbour(x, y) {
if (x < 0 || x >= SIZE_X || y < 0 || y >= SIZE_Y || data[x][y] == 0)
return NO; // out of dimensions or transparent
else
return YES;
}
void add_face(x, y orientation, color) {
// add face at (x, y) with specified color and orientation = TOP, BOTTOM, LEFT, RIGHT, FRONT, BACK
// can be (easier and slower) implemented with SCNPlane's: https://developer.apple.com/library/mac/documentation/SceneKit/Reference/SCNPlane_Class/index.html#//apple_ref/doc/uid/TP40012010-CLSCHSCNPlane-SW8
// or (harder and faster) using Custom Geometry: https://github.com/d-ronnqvist/blogpost-codesample-CustomGeometry/blob/master/CustomGeometry/CustomGeometryView.m#L84
}
for (x = 0; x < SIZE_X; x++) {
for (y = 0; y < SIZE_Y; y++) {
int color = data[x][y];
// skip current pixel is transparent
if (color == 0)
continue;
// check neighbour at top
if (! has_neighbour(x, y + 1))
add_face(x,y, TOP, );
// check neighbour at bottom
if (! has_neighbour(x, y - 1))
add_face(x,y, BOTTOM);
// check neighbour at bottom
if (! has_neighbour(x - 1, y))
add_face(x,y, LEFT);
// check neighbour at bottom
if (! has_neighbour(x, y - 1))
add_face(x,y, RIGHT);
// since array is 2D, front and back faces is always visible for non-transparent pixels
add_face(x,y, FRONT);
add_face(x,y, BACK);
}
}
很多依赖于输入图像。如果不是大,没有各种各样的颜色,那我将与 SCNNode
去加入 SCNPlane
的可见面,然后 flattenedClone()
ING的结果。
A lot of depends on input image. If it is not big and without wide variety of colors, it I would go with SCNNode
adding SCNPlane
's for visible faces and then flattenedClone()
ing result.
这篇关于图像转换为SceneKit节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!