2014-10-28 77 views
1

我已經有了一行三維數組值,我想要在3D中進行可視化,並且我在OS X下使用了它的場景套件。我以笨拙的方式將每列用作X軸上的一個點,將每一行作爲Z軸上的一個點,將每個值作爲Y軸上的標準化點 - 我將球放在矢量由每個數據點定義。它有效,但看起來不太好。場景包的性能問題

我也通過在Drawing a line between two points using SceneKit(他發佈的答案,而不是原始問題)基礎上構建基於@ Matthew函數的行網格來完成此操作。對於每個點,我使用他的函數繪製兩條線 - 我的當前點和右下一個點之間的一條線,以及當前點和前一個點之間的另一個點(除非沒有額外的列/行,當然)。

使用第二種方法,我的結果看起來好多了......但是性能相當糟糕!完成初始渲染需要相當長的時間,並且如果我使用觸控板/鼠標旋轉或翻譯場景,我還不如拿一杯咖啡等到我的系統再次可用(並且這不是很多誇張)。使用球體方法,事物渲染和更新速度非常快。

有關如何在使用線條方法時提高性能的任何建議? (請注意,我不想同時添加行和球體)。代碼方面,方法之間的唯一區別是調用以下哪個方法(並且對於每個點,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

我們需要了解更多關於性能問題和測量結果的信息嗎?問題是否有太多的平局?太多的三角形? CPU是否做了太多工作? etc. – 2014-10-28 18:54:16

+0

另外,你是單獨使用線還是他們只是組成一個網格? (截圖可能是有用的,知道自己在做什麼,但它沒有相關的性能問題) – 2014-10-28 18:56:30

+0

@DavidRönnqvist我還不能肯定這裏的答案,但我可以說,它不僅是我的應用程序,它受到當發生這種情況,這是完整的系統。我可以說的是,即使在使用球體方法時,在我創建最後一個節點之後,我仍然可以看到場景大約一秒鐘。 – mah 2014-10-28 18:57:04

回答

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 2014-10-28 21:17:21

+0

@rickster是的,我忘記了你可以修改片段着色器中的幾何體:) – 2014-10-28 21:21:28

+0

另外,即使是扁平化的節點,你也要做大量的工作來構建基本上相同的20k幾何體。如果你採用這種方法,你只需要一個'SCNGeometry'實例(包含一個源和元素),其中包含從{0,0,0}到'{0,0,1}'的行本地空間。然後使用每個節點的'position','rotation'和'scale'來定位它的線段。 – rickster 2014-10-28 21:21:30