PDA

Volledige versie bekijken : Papervision Line3D performance


ath92
%Europe/Berlin %827 %2010, 19:52
Eindelijk weer eens een AS-gerelateerde vraag van mij kant aan de actionscript-guru's op dit forum.

Dit keer werk mijn script volledig, alleen wordt het binnen 20 seconden al aardig traag. Ik denk zelf dat dit iets met garbage-collection te maken heeft, iemand die mij hier wat meer over kan vertellen (en over hoe ik dit probleem kan oplossen?)

Hier de source:

public class Strings extends BasicView
{
public var lineContainer:Lines3D = new Lines3D();
public var angles:Array = new Array();

private var numberOfSegments:uint = 6;
private var numberOfStrings:uint = 6;

private var lineMat:LineMaterial = new LineMaterial(0x000, 1);
private var v1:Vertex3D = new Vertex3D();
private var v2:Vertex3D = new Vertex3D();
private var line:Line3D;
public function Strings():void
{
init();
singleRender();
addEventListener(Event.ENTER_FRAME, tick);
}

private function init():void
{
for(var i:uint=0; i < numberOfSegments; i++){
angles[i] = 0;
}
scene.addChild(lineContainer);
}

private function tick(e:Event):void
{
for(var n:int = numberOfStrings-1; n>-1; n--){
if(n==0){
angles[0] = angles[0] + (Math.random()*0.2-0.1)*3.14;
} else {
angles[n] = angles[uint(n-1)];
}
//trace(angles[n]);
}

lineContainer.removeAllLines();
for(var i:uint = 0; i < numberOfSegments; i++){
for(var j:uint = 0; j<numberOfStrings; j++){
v1 = new Vertex3D(int(i*100-300), Math.cos(angles[i]) * int(j*30-75), Math.sin(angles[i]) * int(j*30-75));
v2 = new Vertex3D(int(i*100-200), Math.cos(angles[i+1]) * int(j*30-75), Math.sin(angles[i+1]) * int(j*30-75));

line = new Line3D(lineContainer, lineMat , 1, v1, v2);
lineContainer.addLine(line);
}
}


//render it all
camera.zoom = 100;
singleRender();

}
}

en hier wat het wordt:
http://www.ath92.nl/strings

Ik snap trouwens dat wat ik nu heb gemaakt ook zonder papervision had gekund, maar het is voor latere dingen belangrijk dat het wel in PV3D staat.

mknol
%Europe/Berlin %865 %2010, 20:46
Ik ben niet bekend met papervision, maar er vallen me een aantal dingen op.
Ten eerste maak je elk frame 72 nieuwe Vertex3D objecten aan, terwijl het aantal 72 blijft. Ook maak je elk frame 36 Line3D objecten aan, terwijl dit volgens mij ook niet hoeft. Het aanmaken van zoveel objecten elk frame lijkt me overbodig, je kan ze eenmalig aanmaken en daarna hergebruiken (in een Array/Vector).

Ook ga je elk frame de zoom opnieuw instellen, eenmalig lijkt me al goed. Maar dit lijkt me geen showstopper.

Als laatste moet je even nagaan of removeAllLines wel echt alle lines weghaalt. trace/zoek eens of de lines echt weg/undefined zijn. Anders gaat wss het exponentieel fout.

Wat doet de singleRender() functie trouwens?

Ook zou ik eens nadenken of Strings een goede class beschrijving is (lijkt verwarrend mbt een String).

ath92
%Europe/Berlin %967 %2010, 23:12
Met een aantal veranderingen heb ik de performance in ieder geval ruim voldoende gekregen, met dank aan je tips! Ik heb alle vertices en lines nu in arrays gezet, dus die worden nu niet telkens weer opnieuw aangemaakt. In plaats daarvan worden nu dus de x, y en z positie van de vertices veranderd, en vervolgens de vertices per Line3D geupdate.

Achteraf had ik er misschien iets meer tijd aan kunnen besteden om zelf op dit idee te komen :P In ieder geval post ik nog even de updates:


public class Strings extends BasicView
{
public var lineContainer:Lines3D = new Lines3D();
public var angles:Array = new Array();
public var startVertices:Array = new Array();
public var endVertices:Array = new Array();
public var lines:Array = new Array();

private var numberOfSegments:uint = 6;
private var numberOfStrings:uint = 6;

private var lineMat:LineMaterial = new LineMaterial(0x000, 1);
public function Strings():void
{
init();
singleRender();
addEventListener(Event.ENTER_FRAME, tick);
}

private function init():void
{
for(var j:uint = 0; j < numberOfStrings; j++){
startVertices[j] = new Array();
endVertices[j] = new Array();
lines[j] = new Array();
for(var i:uint=0; i < numberOfSegments; i++){
angles[i] = 0;
startVertices[j][i] = new Vertex3D(int(j*100-300), 0, 0);
endVertices[j][i] = new Vertex3D(int((j+1)*100-300), 0, 0);
lines[j][i] = new Line3D(lineContainer, lineMat, 1, startVertices[j][i], endVertices[j][i]);
}
}

scene.addChild(lineContainer);
}

private function tick(e:Event):void
{
for(var n:int = numberOfStrings-1; n>-1; n--){
if(n==0){
angles[0] = angles[0] + (Math.random()*0.2-0.1)*3.14;
} else {
angles[n] = angles[uint(n-1)];
}
//trace(angles[n]);
}

lineContainer.removeAllLines();
for(var i:uint = 0; i < numberOfSegments; i++){
for(var j:uint = 0; j<numberOfStrings; j++){

with(startVertices[i][j]){
x = int(i*100-300);
y = Math.cos(angles[i]) * int(j*30-75);
z = Math.sin(angles[i]) * int(j*30-75);
}

with(endVertices[i][j]){
x = int((i+1)*100-300);
y = Math.cos(angles[i+1]) * int(j*30-75);
z = Math.sin(angles[i+1]) * int(j*30-75);
}

lines[i][j].v0 = startVertices[i][j];
lines[i][j].v1 = endVertices[i][j];

lineContainer.addLine(lines[i][j]);
}
}


//render it all
camera.zoom = 100;
singleRender();

}
}


Oh trouwens, de naam Strings is inderdaad verwarrend, zal het nog een keer veranderen in Lines ofzo. Ik had ook maar even snel wat gekozen. singleRender() is gewoon een functie van BasicView (welke door mijn klasse wordt ge-extend), die alles één keer rendert (heb me daar verder ook niet in verdiept). removeLines heb ik nog niet aangepast, maar ik ga er eigenlijk maar vanuit dat deze inderdaad alles verwijdert (anders kom ik daar later nog wel achter, en weet ik ook meteen waar het aan ligt :))