Convert Image to SceneKit Node

I have a bitmap image: my bit-map image

(However, this should work with any arbitrary way)

my scene kit node

I want to take my image and make it a 3D SCNNode. I have already done a lot with this code. This takes up every pixel in the image and creates an SCNNode with 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 do takes up a lot of memory! my memory statistics

I am trying to find a way to do this with less memory.

All code and resources can be found at: https://github.com/KonradWright/KNodeFromSprite

+2
source share
3 answers

SCNBox , :

  • GL
  • N 1x1x1 , 1x1xN

Minecraft:

, ( , , ):

#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() .

+4

, Ef Dot:

  • , , . SCNMaterial .
  • , , (SCNGeometryElement) . , ().

, SCNGeometry N N, N - .

  • ( )
  • ( ) .
  • .

, SCNShape.

  • ( ) UIBezierPath a SCNShape .
  • SCNGeometry

, , SCNShape . , . .

+3

GitHub :

https://github.com/nicklockwood/FPSControls

, ( ), , , "" .

, , Ef Dot, .

+1
source

All Articles