When hiding nodes, the performance seems to slow down quite a lot with larger IFC HVAC models (80000 nodes and upwards). On a standard computer this takes almost 10 seconds. I have two models and want to hide one of them. Currently this is done with rootId. Is there any modifications to be made to make this faster? What would be the fastest way to hide all the nodes?
var vm = new Autodesk.Viewing.Private.VisibilityManager(viewer.impl, viewer.model);
var instanceTree = viewer.model.getData().instanceTree;
var rootId = instanceTree.getRootId();
vm.hide(rootId);
vm.setNodeOff(rootId, true);
When showing parts of the same file, with few thousand nodes this seems to be quite a bit faster. Eventhough the nodes are shown one by one.
var totalNodes = nodesToIsolate.length;
for (var i = 0; i < totalNodes; i++) {
vm.show(nodesToIsolate[i]);
vm.setNodeOff(nodesToIsolate[i], false); // True = hide completely
}
So you are saying that the second approach is quite faster than the first one... in that case what prevents you to use the second approach over the first? You could traverse the model structure from rootId to determine all the node and then use second approach, or am I missing something?
I am guessing that a faster approach would be to affect a custom ShaderMaterial to each fragment of the model and control the visibility from the shader code, however traversing the model to affect the material would also take time, but the operation could potentially be performed at an earlier stage.
Also you could completely unload the model from the scene with viewer.impl.unloadModel(model), obviously if you need to restore it later it will take time.
Related
How to implement Undo Redo operation in flex 4 for maintain history?
I'm working with flex UIComponent and DisplayObjects for creating and editing diagrams,but
in flex there is no way to handle user operation history directly.
there is any idea to achieve this?
You could implement the Command Pattern for all actions with execute and undo methods, and queue them up.
so when the user wants to do some thing - lets say create an AddFiveToTotal class and executes:
public method execute():void{
totalModel.add( 5 );
}
This class would then be stored on a FIFO queue.
if the user needs to undo the command would be popped and the undo function called:
public method undo():void{
totalModel.subtract( 5 );
}
for redoability, don't pop, just iterate the queue
also take a look at the Memento Pattern
If you are using any of the currently popular MVC(S) frameworks you will undoubtably find a util that some one has already created
You can acheive with help of memento pattern. It hard to track all properties better you can what are property need to use for undo/redo operation.
Memento Design pattern
Memento pattern
Demo sample with source code http://www.flairpy.com/mementoPattern/MementoSample.html
There are several ways you can address to this problem. First is to keep the states of your whole canvas in a Vector (I mean have a listener for all the things user can do on the stage and saving the state after a change) and then have an index of current state saved, so that you could move through your Vector and put the needed state on the stage. This is the easiest way to approach undo/redo functionality, but beware that you'll have to make clones of objects a lot and this will become a memory hog if you're going to deal with a lot of objects or a lot of undo/redos.
The second approach is to only keep what changed in that vector, so that you won't have to create and clone a lot of objects, but only save one object in your Vector which will contain all the properties that have changed and their last values. This will get you something like this:
private var mHistory:Vector.<Object> = new Vector.<Object>();
private var mCurrentIndex:int = -1;
public function storeState(state:Object)
{
mHistory.push(state);
mCurrentIndex++;
}
public function undo():void
{
if(mCurrentIndex < 1)
return;
mCurrentIndex--;
//here you could test for values that could have changed
var item:DisplayObject = this.getChildByName(mHistory[mCurrentIndex].name);
if(mHistory[mCurrentIndex].x != undefined)
item.x = mHistory[mCurrentIndex].x;
// etc. you get the point. Note that this is only comfortable if only several things can change
}
And the call for storeState function would be like this:
var state:Object = { name:DisplayObjectName, x:120, y:20 };
storeState(state);
Again, you will have to listen to all movement and changes if you want to record them.
I have been trying to learn actionscript 3 for a while now and there are somethings that get me. Like when should I use a loop(for, while, etc)? I watch videos and read articles on the subject and I always run into this example witch really doesn't help me that much:
for(var i:Number = 0; i < 10; i++)
{
trace(i);
}
If anyone can help me on the subject and maybe let me pick there brain a little I would really appreciate it.
Thank you.
You use loops anytime you need to do repetitive tasks.
So if you had 1000 objects that you needed to perform the same operation on, it will be more practical to use a loop instead of writing variations of the same code 1000 times.
A flash example: Let's say you had 10 movieClips that you wanted to all play on a given action.
you could do this:
mc1.play();
mc2.play();
mc3.play();
mc4.play();
mc5.play();
mc6.play();
mc7.play();
mc8.play();
mc9.play();
mc10.play();
For 10 it's just annoying but not a huge deal. If you had 100, or 1000, or 10000 it would be insane. Plus then what if you need to change your code later?
A better way would be to use a loop. Lets say those 10 clips (or any number of clips) were all the children of a parent object called clips.
for(var i:int=0; i<clips.numChildren;i++){
var mc:MovieClip = clips.getChildAt(i);
mc.play();
}
That code would do the exact same thing. You're looping through all the children of the clips parent, and telling everyone to play. Need to change it to gotoAndPlay(3)? then you just have one line to update.
This is a very simple example (and just one of many reasons you'd use a loop), you can probably guess when you get into working with more complex data and objects how loops help you code repetitive tasks.
In general, I use a for loop when I need an index.
For example I might want an array of indexes that represents which MovieClips in a given array are visible :
var visibleClips:Array = new Array;
for (var index:int = 0;index < arrayOfClips.length;index++)
{
var clip:MovieClip = arrayOfClips[index];
if (clip.visible)
{
visibleClips.push(index);
}
}
A while loop I commonly use for something like removing all the children from a DisplayObject like this :
while (container.numChildren > 0)
{
container.removeChildAt(0);
}
As you can see, I really did not need an index in that situation, so it's simpler to use the while loop.
As my old programming teacher said:
"Use for loops when you know how many iterations you want/need to do"
I.e looping through a list, array, vector etc.
"And use while loops when you are not sure."
I.e looping through a whole file (for reading binary data) or doing continuous events that stops for a certain condition.
That being said you could probably apply both for and while loops for most cases. Personally I mostly use for-loops.
Like prototypical said the while loops is great when removing all children of a container but this could also be achieved using a for loop like:
for(var i:int = 0; i < numChildren; i++)
{
removeChildAt(i); i--;
}
I am uploading files using the upload() method of the FileReference class. I want to display the current connection speed and I was wondering what was a good way to do that.
My current technique is to use a Timer every 1 mili second such as follows:
var speed:Function = function(event:TimerEvent):void {
speed = Math.round((currentBytes - lastBytes) / 1024);
lastBytes = currentBytes;
}
var speedTimer:Timer = new Timer(1000);
speedTimer.addEventListener(TimerEvent.TIMER, uploadSpeed);
and currentBytes gets set into the ProgressEvent.PROGRESS. This technique seems imprecise. I was wondering what other ways I could use to calculate the upload speed while uploading and display it in real time.
Any ideas or opinions are welcomed!
Thank you very much,
Rudy
If that code block is a copy and paste it certainly won't work as you have expected it to. You declare speed as a function within which you appear to redefine it as a number. I appreciate the Flash IDE let's you get away with sketchy grammar, but code like that is going to lead you into all kinds of trouble. Try to be explicit when writing your code.
Try something like this, replacing yourLoader with whatever identifier you assigned to the uploader:
private var speed:Number = 0;
private var lastBytes:uint = 0;
private function uploadSpeed(event:TimerEvent):void
{
speed = Math.round((yourLoader.currentBytes - lastBytes) / 1024);
lastBytes = yourLoader.currentBytes;
}
private var speedTimer:Timer = new Timer(1000);
speedTimer.addEventListener(TimerEvent.TIMER, uploadSpeed);
That should calculate how many bytes moved in 1 second intervals.
Edit:
You might like to make the interval a little smaller than 1000ms and calculate an average speed for your last n samples. That would make the number your users see appear more stable than it probably does right now. Make speed an Array and .push() the latest sample. Use .shift() to drop the oldest samples so that you don't lose too much accuracy. Trial and error will give you a better idea of how many samples to hold and how often to take them.
You can moniter the upload speed on the server and then send that data back to the client. This technique is often used for ajax file upload forms.
I have a Array of Characters objects (extends Sprite).
public static var charlist:Array;
When a Character die, I set a flag to indicate that.
char.die = true;
When I spawn a new player, I check against this flag, to reuse the slot. This is where the problem comes.
What is the best way to do that? Actually I have this approach:
char = new Char();
/* ... */
for (var i:Number = 0; i < Char.charlist.length; i++) {
if (Char.charlist[i].death) {
Char.charlist[i] = char;
return;
}
}
But the problem is that I come from C++ and I think calculating the index every iteration is wasteful.
I would do this, but this doesn't work in AS3, since I can't access by reference the item:
char = new Char();
/* ... */
for (var i:Number = 0; i < Char.charlist.length; i++) {
var char_it:Char = Char.charlist[i];
if (char_it.death) {
char_it = char;
return;
}
}
Just a note: charlist is a static member of class Char.
Do you have any ideas or better approaches?
Thanks!
The "optimized" version doesn't optimize much, I think.
YOur code does not perform 2 accesses in every iteration. It does just when you happen to find a dead Char; and after that you return. So, no big deal, I think.
Personally, I don't think reusing array slots is going to make a big difference either. And, maybe it could be degrade (but the worst part is that your code could be simpler if you avoid it). Suppose you have 100 chars, 60 of which are dead, and you have a loop that runs every frame and performs some check / action on every live char. You'd be looping over 100 chars, when you could loop over 40 if you mantained a list of live objects and a separte list of dead objects, ready to reuse them. Also, the "dead list" could be handled as a stack, so no iteration is needed to get a char.
Anyway, I see 2 things you could easily optimize in your code:
1) retrieve the list length outside the loop:
Do this:
var len:int = Char.charlist.length;
for (var i:Number = 0; i < len; i++) {
Instead of this:
for (var i:Number = 0; i < Char.charlist.length; i++) {
The compiler won't optimize away the call to length (following the ecmascript spec).
2) Avoid static access (for charlist). It's known to be considerably slower than instance access.
Edit:
Re-reading your question, I realize I misunderstood part of it. You're not trying to reuse Char objects, but rather array slots. Still, I don't think reusing array slots is worth it (arrays in Actionscript are non fixed); but something that could help performance is reusing the Char objects themselves. Reseting a Sprite is generally cheaper than creating a new one.
You could manage this with a pool of "dead" objects, from which you can take one and "bring it back to life" when you need, instead of creating a new one.
This post talks about object pools (the blog itself is a good source for Actionscript stuff, especially for performance and data structures topics; worth taking a look):
http://lab.polygonal.de/2008/06/18/using-object-pools/
Why not to use a list instead of array and simply remove dead ones from the list and add new one when needed?
Is there a good reason to try to reuse the slot?
What are you trying to optimize?
Is there a reason you can't just splice out the desired character and push a new character onto the array?
var characters:Array = ["leo", "raph", "don", "mike"];
characters.splice(1, 1);
trace(characters);
characters.push("splinter");
trace(characters);
If you're looking for storage by reference, checkout AS3's Dictionary object or even Flash 10's Vector (if storage is consistent by type; quite fast):
http://www.gskinner.com/blog/archives/2006/07/as3_dictionary.html
When I make the same query twice, the second time it does not return new rows form the database (I guess it just uses the cache).
This is a Windows Form application, where I create the dataContext when the application starts.
How can I force Linq to SQL not to use the cache?
Here is a sample function where I have the problem:
public IEnumerable<Orders> NewOrders()
{
return from order in dataContext.Orders
where order.Status == 1
select order;
}
The simplest way would be to use a new DataContext - given that most of what the context gives you is caching and identity management, it really sounds like you just want a new context. Why did you want to create just the one and then hold onto it?
By the way, for simple queries like yours it's more readable (IMO) to use "normal" C# with extension methods rather than query expressions:
public IEnumerable<Orders> NewOrders()
{
return dataContext.Orders.Where(order => order.Status == 1);
}
EDIT: If you never want it to track changes, then set ObjectTrackingEnabled to false before you do anything. However, this will severely limit it's usefulness. You can't just flip the switch back and forward (having made queries between). Changing your design to avoid the singleton context would be much better, IMO.
It can matter HOW you add an object to the DataContext as to whether or not it will be included in future queries.
Will NOT add the new InventoryTransaction to future in memory queries
In this example I'm adding an object with an ID and then adding it to the context.
var transaction = new InventoryTransaction()
{
AdjustmentDate = currentTime,
QtyAdjustment = 5,
InventoryProductId = inventoryProductId
};
dbContext.InventoryTransactions.Add(transaction);
dbContext.SubmitChanges();
Linq-to-SQL isn't clever enough to see this as needing to be added to the previously cached list of in memory items in InventoryTransactions.
WILL add the new InventoryTransaction to future in memory queries
var transaction = new InventoryTransaction()
{
AdjustmentDate = currentTime,
QtyAdjustment = 5
};
inventoryProduct.InventoryTransactions.Add(transaction);
dbContext.SubmitChanges();
Wherever possible use the collections in Linq-to-SQL when creating relationships and not the IDs.
In addition as Jon says, try to minimize the scope of a DataContext as much as possible.