I need to show a 3D model on a SceneView in my iOS app, after its relative path (String) has been loaded from Firebase and passed to my SCNScene(named: path).
The function that reads the path runs very quickly, but once I try to attach the scene to my SceneView, it takes pretty long before it can actually be displayed (5-6 sec).
The .scn file I'm trying to show is about 20MB, and if I set showStatistics = true, it says my scene contains more than 200K triangles.
I need a help in order to understand how I could strongly reduce the "loading" time of the scene.
I've already tried reducing the number of polygons and also using the SceneView method prepare(_:completionHandler:) in order to render my scene on a background thread and (ideally) speed up the process to display it, but nothing worked for me.
Any help would be really appreciated. Thanks!
Related
I'm facing a problem using SceneKit in my iOS app.
I have a sceneView showing a 3D model (from a .scn file) that the user can customize changing some details like hair color, eyes color and hair style.
What it's happening, is that the memory used by the app goes up to around 250 MB, and it happens exactly when the view starts showing my 3D model.
I programmatically compose the "full" 3D model by adding nodes coming from different scenes.
Just to be a bit more clear, I have one .scn containing the body, another .scn containing the hair style and so on. When the view loads up, I just create a "fullModel" that is a SCNNode() running through each node of the various .scn files and adding them to my fullModel node. Then I add the fullNode to my scene.rootnode
I'm new in iOS programming and I tried so long to understand what'a going on, even using XCode Instruments "Allocations" and "Leaks" functionalities but nothing helped.
Any suggestion on what I could try to solve the high memory usage will be very appreciated!
Thanks a lot!
I am working on a game in which a character runs along the screen and the camera is following the character. For each scene I add all the required assests and place them on scene. I do this behind a loading screen, because SceneKit needs some time to put all the stuff on scene. After like 5 seconds I fade out the screen (which is basically a black UIImage that lays in front of everything) and the game starts. Depending on the current scene, the amout of memory required is between 200MB and 500MB.
Everything runs fine and smoothly, till the character gets close to a new scene asset, (which was already put on scene) and that was placed initially outside the actual frustum of the camera. The character runs towards it, and in the moment in which the asses enters the bounds of the screen, the app stucks for a few frames (the larger the geometry asset, the more frames are dropped).
i.Ex. a Geometry of size 3MB with PBR Textures of 1.5MB in total will drop some 5 to 10 frames as soon as it gets in the frustum of the camera. This happens more or less for all upcoming assets. (no matter, if the asset is an OBJ, a DAE, or a converted SCN file)
There are no crashes, everything is okay, the game continues as expected, but I have these annoying dropouts.
When i.Ex the character dies and the same scene reloads (it reloads completely from scratch) everything runs smoothly the second time and afterwards. No framedrops anymore.
Why is this happen? Is there a way to tell SceneKit to "really" preload everything? (like when the same scene is loaded for the second time)
PS: I currently use a iPhone 11 Pro Max with iOS 14, Xcode 12.2. (I observed this aleady in earlier versions.)
I am new to ARKit. I am trying to add so many new nodes into the sceneview in front of my camera. I wanna add objects like cylinder and sphere with different colors. the problem is my frame speed will drop significantly and my phone starts to lag so much after I add 30 objects to the scene. I searched for a solution so much and I found this function to be helpful. prepare(_:completionHandler:). This was how I was adding my objects to the scene without prepare function.
self.sceneView.scene.rootNode.addChildNode(cylinder)
and now I am using the prepare function like this:
self.sceneView.prepare([cylinder], completionHandler: { (success) in
self.sceneView.scene.rootNode.addChildNode(cylinder)
})
Now frame drops like before, also the app will crash after adding 50 objects to the scene.
I think I am not using it correctly and I don't know how to use it?!
Also, I am thinking what else I can do to better my ARKit app?
How you're adding the objects is independent of the frame rate that you're seeing, and when you use all the memory available. The different method of adding objects can be useful for keeping the UI responsive, but you will need to optimize (or use more powerful hardware) when placing a lot of objects into an ARKit scene.
If you're trying to understand your ARKit performance, the medium article on ARKit 1.5 vs. 2.0 might be useful.
I am creating a web app using THREE JS which contains multiple 3D view.
Here is the code flow.
Created scene.
Created camera and added to the scene
Added light to the scene.
Added WebGLRenderer.
Added 3D objects to the scene.
Removed objects added in step 3 and added 3D objects of some other view.
On repeating steps 5 and 6 several times, GPU memory shoots up and browser becomes unresponsive.
In order to clean memory in three.js. You need to call dispose function for geometry, material and texture explicitly. Here is the explanation from threejs. Hope this helps.
https://threejs.org/docs/#manual/en/introduction/How-to-dispose-of-objects
I am creating a game using cocos2dx 2.1.4. Its FPS drops continuously , and never recover.
Please find the details as follows
Background about the way I am doing things:-
Its game about scrolling down some shapes, each shape is made up of some square blocks.I have 7 kind of blocks. All loaded in a Sprite Sheet and using these blocks from this sprite sheet I create a shape.
A level file is consist of these shapes. I load two levels at the same time one onscreen and another off screen to make it seamless scrolling. For loading two levels at the same time I used two different CCSprite game batch nodes as :-
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("56blackglow.plist");
_gameBatchNode1 = CCSpriteBatchNode::create("56blackglow.png", 200);
_gameBatchNode1->retain();
this->addChild(_gameBatchNode1,kForeground);
_gameBatchNode2= CCSpriteBatchNode::create("56blackglow.png", 200);
_gameBatchNode2->retain();
this->addChild(_gameBatchNode2,kForeground);
The problem I am facing is that as I keep on playing the game frame rate drops continuously , from 60 fps till 10 fps and never recovers or might recover in near future , as I observed for 20 minutes but its too much time to wait.
My observations:-
1> I used Time profiler it shows maximum time is in draw() calls. Also if I play game very fast the peak of time increases in track, that should be fine as I am giving more work to do, but once a peak is attained it remains approximately at that height only, even if I leave the game Idle. Is it normal ? According to me it should have returned to its normal peak once the current work is done.
2> Some where I thought its happening because I used two batch nodes and removing its children on a user touch immediately might causing it slow but then after removing the children it should run normal. to give an idea is it ok to remove 10 children from batch node immediately ? some guys say its very slow process. Just to check if this causing problem , I did :-
Instead of removing them I just set visibility of the children to false.But still FPS drops and never recovers.
Please share your thoughts on this.
Though SpriteBatchNodes are generally quite good for drawing a lot of elements efficiently, I think there are best used for static/not-so-dynamic elements. In your case, if you have a lot of elements which go out of the screen but are still alive the draw() function will have to make some checks, thus hogging your performance (even if you set isVisible(false); explicitly, it still nedds to be checked).
In your case I think it would be better if you simply added new shapes outside of screen via some time-based function, and if they scroll outside of view simply remove them from scene, without using batchNodes.
Just found that with every touch, I am adding 8 new sprites to the layer, and its adding every time I touch . So with time I am giving more and more work to do. This is the problem
Actually I wanted to replace the sprite at 8 places with a touch, the way I was doing every time :-
_colorBottom1=CCSprite::createWithSpriteFrameName(png[0]);
this->addChild(_colorBottom1,kForeground);
_colorBottom1->setPosition(ccp((_colorPanelLeftPad)*_blockWidth,_blockWidth));
It was causing this sprite to be added with every touch.
but it should have been (Replace the texture instead of creating the Sprite again):-
CCSpriteFrame *frame1=CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(png0);
_colorBottom1->setDisplayFrame(frame1);