0

I have an array with SCNVector3 vertices that describes trajectory path. And I want to draw its path.

- (SCNNode *)lineNodeFromVertices:(SCNVector3 *)vertices count:(NSUInteger)count
{
    NSInteger numberOfVertices = (count - 1) * 2;
    int *verticesSequence = calloc(numberOfVertices, sizeof(int));

    for (int index = 0; index < count; index ++)
    {
        if (index > 0 && index < count - 1)
        {
            verticesSequence[index * 2 - 1] = index;
            verticesSequence[index * 2] = index;
        }
        else if (index == 0)
        {
            verticesSequence[0] = index;
        }
        else if (index == count - 1)
        {
            verticesSequence[index * 2 - 1] = index;
        }
    }

    NSData *sequenceData = [NSData dataWithBytes:verticesSequence
                                          length:sizeof(verticesSequence)];

    free(verticesSequence);

    SCNGeometryElement *element = [SCNGeometryElement geometryElementWithData:sequenceData                                                                primitiveType:SCNGeometryPrimitiveTypeLine
                                                               primitiveCount:(count - 1)
                                                                bytesPerIndex:sizeof(int)];

    SCNGeometrySource *source = [SCNGeometrySource geometrySourceWithVertices:vertices
                                                                        count:count];

    SCNGeometry *line = [SCNGeometry geometryWithSources:@[source]
                                                elements:@[element]];

    return [SCNNode nodeWithGeometry:line];
}

When I pass dynamically created array as a parameter for creating SCNGeometryElement it doesn't work.

But it works fine when I pass array with predefined number of elements. Something like:

// Sample data
SCNVector3 vertices[] =
{
    SCNVector3Make(1.0, 1.5, 0.5),
    SCNVector3Make(0.8, 1.0, 0.2),
    SCNVector3Make(0.4, 2.0, 1.2),
    SCNVector3Make(0.0, 2.5, 2.7),
    SCNVector3Make(-0.2, 2.0, 4.0),
    SCNVector3Make(-0.4, 0.5, 5.0),
    SCNVector3Make(-0.3, 3.0, 3.0)
};

int count = sizeof(vertices) / sizeof(vertices[0]);

// Array with predefined vertices sequence 
int verticesSequence[] =
{
    0, 1,
    1, 2,
    2, 3,
    3, 4,
    4, 5,
    5, 6
};

NSData *sequenceData = [NSData dataWithBytes:verticesSequence
                                      length:sizeof(verticesSequence)];

SCNGeometryElement *element = [SCNGeometryElement geometryElementWithData:sequenceData                                                            primitiveType:SCNGeometryPrimitiveTypeLine
                                                           primitiveCount:(count - 1)
                                                            bytesPerIndex:sizeof(int)];

SCNGeometrySource *source = [SCNGeometrySource geometrySourceWithVertices:vertices
                                                                    count:count];

SCNGeometry *line = [SCNGeometry geometryWithSources:@[source]
                                            elements:@[element]];

[self.rootSceneNode addChildNode:[SCNNode nodeWithGeometry:line]];

Does there exist other way to create line node with non-predefined number of vertices?

  • I think you need to show one _small_ piece of example data that works and one that does not work. – David Rönnqvist May 27 '15 at 16:29
  • @DavidRönnqvist I added some more information. The first part of code sample doesn't work and the second one works fine. –  May 27 '15 at 19:36

1 Answers1

2

The problem you are facing is that the size of an int pointer is the size of the pointer itself, not the memory it points to.

So when dynamically allocating memory, the size (when I ran it) is 8

int *verticesSequence = calloc(numberOfVertices, sizeof(int));
sizeof(verticesSequence); // 8

Compared to then predefined array, that has a size of 48 (when I ran it)

int verticesSequence[] = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6 };
sizeof(verticesSequence); // 48

This leads to a problem that when you are creating an NSData object, you only get the first 8 bytes of it.

Instead, what you want is the size of the allocated memory (sizeof(int) * numberOfVertices)

sizeof(int)*numberOfVertices; // 48

I gave a similar explanation for Swift in this answer.


So, change the NSData creation to use that

NSData *sequenceData = [NSData dataWithBytes:verticesSequence
                                      length:sizeof(int)*numberOfVertices];
Community
  • 1
  • 1
David Rönnqvist
  • 56,267
  • 18
  • 167
  • 205