【问题标题】:Combining two or more SCNGeometries结合两个或多个 SCNGeometry
【发布时间】:2015-05-01 01:10:07
【问题描述】:

我使用这个方法来抓取 UIImage 并将其转换为 3D 模型。但是,这意味着我添加了很多节点。我在想也许可以通过将所有几何图形添加到单个节点中来优化它。有没有办法做到这一点?

这是代码

static inline SCNNode* S2NNode(const UIImage* sprite) {
  SCNNode *spriteNode = [SCNNode node];
  CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(sprite.CGImage));
  const UInt8* data = CFDataGetBytePtr(pixelData);
  for (int x = 0; x < sprite.size.width; x++)
  {
    for (int y = 0; y < sprite.size.height; y++)
    {
      int pixelInfo = ((sprite.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 - sprite.size.width / 2.0,
                                        y - sprite.size.height / 2.0,
                                        0);
        [spriteNode addChildNode:pixel];
      }
    }
  }
  CFRelease(pixelData);
  //The image is upside down and I have no idea why.
  spriteNode.rotation = SCNVector4Make(1, 0, 0, M_PI);
  return spriteNode;
}

【问题讨论】:

  • 这段代码应该用于小精灵
  • 尽量不要在 CGSizeMake(100,100) 上使用图像
  • 你想做什么?为图像的每个像素制作一个立方体确实对性能没有好处。根据您想要实现的目标,可能还有其他解决方案。
  • 我想为我放置的所有这些立方体设置一个几何图形。所以我想知道是否有一种方法可以将所有这些几何图形添加在一起,这样可能会有助于提高性能。

标签: ios objective-c xcode scenekit


【解决方案1】:

这个答案解决了最初提出的问题——如何合并几何。然而,合并几何似乎并不是解决实际问题的方法——如何获得具有一定厚度的像素化“精灵”,并具有良好的性能。请参阅my other answer


SCNNode 方法flattenedClone 会将节点子节点的所有几何图形组合成具有单个几何图形的单个节点。这将减少场景处理开销并在单个 OpenGL 绘制调用中进行渲染......但它也会使立方体不能独立移动并且都共享相同的材质,因此它们不会是不同的颜色。此外,根据您希望立方体的排列方式,您可能会向 GPU 推送比您需要的更多的顶点数据,这仍然会损害您的性能。

根据您想要的效果,可能会有更好的解决方案。

【讨论】:

  • 你是正确的关于删除独立移动方块的能力。颜色保持不变。然而,它在 GPU 上仍然同样密集。如何从我的 SCNNode 创建顶点数据?
  • 取决于你想用它做什么。提出另一个问题或编辑您的原始问题,并描述您的最终目标——实现目标的步骤可能不会等待您的想法。
  • 你在这里得到的结果只是另一个盒子。但是 SceneKit 不够聪明,无法检测到这一点,并且顶点的数量保持不变。你不能使用一个单独的盒子来将你的纹理与SCNFilterModeNone 映射到上面来实现pixelate 效果吗?
  • 您的建议导致了这一点。 i.imgur.com/OUSq8E2.png 我要找的是。 i.imgur.com/YgkILT2.png 但是我的方法会占用大量内存。
  • 啊,那么您要寻找的是具有一定厚度的“像素化”形状吗?然后丢弃立方体并使用SCNShape。我将很快发布另一个答案,其中包含更多详细信息。
【解决方案2】:

发布一个单独的答案是因为您的 cmets 已经表明您实际寻找的并不是您要问的——我将留下另一个答案,因为它回答了最初提出的问题,即使它不能解决你的问题。


所以,听起来你真正需要的不是一组立方体,每个都可以独立移动并且每个都有自己的颜色,而是将 2D 形状挤压成 3D —— 具体来说,由不透明的形状形成图像的像素:

在这种情况下,制作一堆立方体确实会损害您的性能——以及您的渲染结果。查看此详细信息(来自使用很多立方体方法的版本):

那些小白点来自两个立方体相交处的舍入误差。这里的问题——无论你是否使用flattenedClone——被推送到 GPU 的几何数据描述了一大堆不可见的多边形(因为它们在两个立方体之间)或不相关的(因为共享面两个相邻的立方体也可以是一个多边形)。这是我对很多立方体方法的测试中的性能指标:

这是 408 次绘制,4.9K 多边形,14.7K 顶点。在 iPad Air 上旋转该模型每秒可达到 14 帧——太糟糕了。

您可以使用 SCNShape 类从 Bézier 路径创建拉伸形状。诀窍是从不透明像素的形状中创建最简单的路径。 (你想要的是形成形状轮廓的路径,而不是每个像素的一堆方形路径的联合——否则你就回到立方体问题了。)

这是计算几何的重要部分,但there are solutions out there。还有一些外部工具可以离线为您进行跟踪(其中大多数是为 SpriteKit 制作基于 sprite 的物理主体而设计的,在这成为 iOS 8 / OS X 10.10 中的 SpriteKit 功能之前):here's one

获得路径后,您可以从中创建一个SCNShape,将您的图像纹理映射到形状的正面(如果您愿意,也可以在背面),并为双方:

UIImage *image = [UIImage imageNamed:@"sprite"];
UIBezierPath *path = PathFromImage(image); // Make or load your path here
SCNNode *node = [SCNNode nodeWithGeometry:[SCNShape shapeWithPath:path extrusionDepth:1]];
SCNMaterial *face = [SCNMaterial material];
face.diffuse.contents = image;
face.diffuse.magnificationFilter = SCNFilterModeNone;
SCNMaterial *side = [SCNMaterial material];
side.diffuse.contents = [UIColor blackColor];
side.specular.contents = [UIColor whiteColor];
node.geometry.materials = @[ face, side, side ];

这是使用SCNShape 代替的仪表:

我们将数字减少了两个数量级,相应地帧率也提高了很多——我无法让它在模型旋转时降至 60 fps 以下。

【讨论】:

  • 感谢您花时间向我解释所有这些。我正在尝试修改您的答案,但我对如何使用您提供的工具根据我作为参数传入的图像创建路径感到困惑?
  • 它没有——从任意图像创建路径是一个棘手的问题。如果您有特定的图像要执行此操作,请使用我链接的工具为每个图像创建特定路径。
  • 另外,该特定工具不会输出UIBezierPath 代码,但会输出可用于构建自己的代码的点列表。
  • 在这种情况下,您需要自己的代码(或库)与该工具执行相同的操作 - 如前所述,该问题有解决方案。请参阅this question 以开始使用。
  • 我添加了另一个问题。希望我说得更清楚。在那个。 stackoverflow.com/questions/28824103/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-23
  • 1970-01-01
  • 2011-10-10
  • 1970-01-01
  • 1970-01-01
  • 2013-10-31
  • 2010-10-22
相关资源
最近更新 更多