2014-10-28 2 views
1

У меня есть массив мерных размеров, который я хочу визуализировать в 3D, и я использую набор сцен под OS X для него. Я сделал это неуклюже, используя каждый столбец как точку на оси X, каждую строку как точку на оси Z и каждое значение как нормированную точку на оси Y - я помещаю сферу на вектор, определенный каждой точкой данных. Он работает, но он выглядит не слишком хорошо.Проблемы с производительностью с scenekit

Я также сделал это, построив сетку линий на основе функции Матфея в Drawing a line between two points using SceneKit (ответ он отправил, а не оригинальный вопрос). Для каждой точки я использую его функцию, чтобы нарисовать две строки: одну между моей текущей точкой и следующей точкой справа, а другую между моей текущей точкой и следующей точкой в ​​направлении фронта (за исключением случаев, когда нет дополнительного столбца/строки, конечно).

Используя второй метод, мои результаты выглядят намного лучше ... однако производительность довольно отвратительная! Для завершения первоначального рендеринга требуется довольно много времени, и если я использую трекпад/мышь, чтобы повернуть или перевести сцену, я мог бы также выпить чашку кофе, пока моя система снова не будет использоваться (и это не так много гипербола). Используя метод сферы, вещи визуализируются и обновляются очень быстро.

Любые советы по улучшению производительности при использовании метода линий? (Обратите внимание, что я не пытаюсь одновременно добавить обе строки и сферы.) Кодируя, единственная разница между подходами заключается в том, какой из следующих методов вызывается (и что для каждой точки addPixelAt ... вызывается один раз , но addLineAt ... вызывается дважды для большинства точек).

enter image description here

- (SCNNode *)addPixelAtRow:(CGFloat)row Column:(CGFloat)column size:(CGFloat)size color:(NSColor *)color 
{ 
    CGFloat radius = 0.5; 

    SCNSphere *ball = [SCNSphere sphereWithRadius:radius*1.5]; 
    SCNMaterial *material = [SCNMaterial material]; 
    [[material diffuse] setContents:color]; 
    [[material specular] setContents:color]; 
    [ball setMaterials:@[material]]; 

    SCNNode *ballNode = [SCNNode nodeWithGeometry:ball]; 
    [ballNode setPosition:SCNVector3Make(column, size, row)]; 

    [_baseNode addChildNode:ballNode]; 
    return ballNode; 
} 

enter image description here

- (SCNNode *)addLineFromRow:(CGFloat)row1 Column:(CGFloat)column1 size:(CGFloat)size1 
         toRow2:(CGFloat)row2 Column2:(CGFloat)column2 size2:(CGFloat)size2 color:(NSColor *)color 
{ 
    SCNVector3 positions[] = { 
     SCNVector3Make(column1, size1, row1), 
     SCNVector3Make(column2, size2, row2) 
    }; 

    int indices[] = {0, 1}; 

    SCNGeometrySource *vertexSource = [SCNGeometrySource geometrySourceWithVertices:positions count:2]; 

    NSData *indexData = [NSData dataWithBytes:indices length:sizeof(indices)]; 

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

    SCNGeometry *line = [SCNGeometry geometryWithSources:@[vertexSource] elements:@[element]]; 
    SCNMaterial *material = [SCNMaterial material]; 
    [[material diffuse] setContents:color]; 
    [[material specular] setContents:color]; 
    [line setMaterials:@[material]]; 

    SCNNode *lineNode = [SCNNode nodeWithGeometry:line]; 

    [_baseNode addChildNode:lineNode]; 
    return lineNode; 
} 
+0

Нам нужно знать больше о проблемах с производительностью и измерениях, которые у вас есть? Слишком много проблем с вызовами? Слишком много треугольников? Процессор слишком много работает? и т. д. –

+0

Кроме того, вы используете линии по отдельности или просто составляете сетку? (Снимок экрана может быть полезен, чтобы знать, что вы делаете, но это не связано с проблемами производительности) –

+0

@ DavidRönnqvist Я не уверен в ответах здесь, но могу сказать, что это не только мое приложение, которое страдает, когда это происходит, это полная система. Я могу сказать, что даже при использовании метода сферы это примерно за секунду, прежде чем я смогу увидеть сцену после создания моего последнего узла. – mah

ответ

3

Из данных, которые вы показали в вашем вопросе, я бы сказал, что ваш основной проблемой является количество вызовов отрисовки. У вас десятки тысяч, это путь слишком много. Вероятно, это должно быть намного ближе к ~ 100.

Причина, по которой у вас так много вызовов вызова, заключается в том, что у вас на вашей сцене столько разных объектов (каждая строка). Лучшее (но более совершенное решение), вероятно, должно было бы создать единый элемент для всей сетки, состоящей из всех строк. Если вы хотите добиться того же рендеринга с этой сеткой (с цветом от холода до тепла в зависимости от высоты), вы можете сделать это в модификаторе шейдера.

Однако в вашем случае я бы начал с выравнивания всех строк (так как это будет наименьшее изменение кода и должно по-прежнему иметь значительное улучшение производительности в вашем случае).

(Оптимизация производительности всегда итерационный процесс. После того, как вы исправить одну вещь, там будет еще одна вещь, которая является наиболее дорогостоящей операцией. Без вашего кода, я могу только сказать, что бы помочь с текущей проблемой производительности)

Создайте пустой узел (не добавляя его в свою сцену) и сгенерируйте все строки, добавив их в этот узел. Затем создайте сплющенную копию этого узла путем вызова flattenedClone на узле, который содержит все строки

SCNNode *nodeWithAllTheLines = [SCNNode node]; 
// create all the lines and add them to it... 
SCNNode *flattenedNode = [nodeWithAllTheLines flattenedClone]; 
[_baseNode addChildNode:flattenedNode]; 

Когда вы сделаете это, вы должны увидеть значительное снижение количества вызовов отрисовки (число после алмаза в статистика) и, надеюсь, большой рост производительности.

+0

Хороший общий совет. Модификатор шейдера, вероятно, лучший способ пойти. Вам даже не нужно создавать пользовательскую геометрию для этого - используйте «SCNPlane» с требуемым разрешением сетки. Для данных карты высот либо передайте массив поплавков в форме шейдера, либо наполните его текстурой и образцом в шейдере. – rickster

+0

@ rickster Да, я забыл, что вы можете изменить геометрию в шейдере фрагмента :) –

+0

Кроме того, даже с уплощенным узлом вы выполняете большую работу по построению геометрий 20k, которые по существу идентичны. Если вы идете на этот подход, вам нужен только один экземпляр «SCNGeometry» (с одним источником и элементом), который содержит строку от, скажем, '{0,0,0}' до '{0,0,1}' в локальное пространство. Затем используйте «позицию», «вращение» и «масштаб» каждого узла для ориентации его сегмента линии. – rickster

Смежные вопросы