[Closed] Challenge: Win a copy of PolySpeed for script help
I need a new super fast way to do something similar to the detach (and attach) function (it’s horribly slow), and I would be more than grateful if I could get some help. If you come up with a great implementation that I haven’t thought about or a very good one I will award the contributor(s) with a free copy of PolySpeed worth about 160+$.
What I need:
- you have a very large object, Big Object, 300-500k faces. The user selects say 50 faces. This new function should now create a New Object with these faces, and possibly hide or delete the 50 faces from the big object.
How I do it now:
- Just use polyOp.detach. But it’s amazingly slow. Takes 14 seconds on a 300k object on a my machine (1.3GHz)
- A trick I use. I create a snapshot of the Big Object then I delete the inverse of the selection on the New Object, so only the small selection is left. Then I delete the selection on Big Object. This is about 3-4 times faster for large objects but takes more memory and is somewhat unstable.
Ideas for better ways:
3) It has to be faster to rebuild the object from scratch somehow. Perhaps I get all the vertex positions from the selection, create a new object with these vertices and then build the faces. But how do I really build the faces so they look identical? Also how do I get the vertex positions from the faces in a fast way?
3.5) It’s slow to build the vertices directly, it’s much faster if they are already built (precached) so I just need to move them to their correct places. Perhaps I have 1000 faces that are separate and hidden in one object. Then I move them to the correct places, and in the end welds all of them. But how do I move the faces to the same positions as the others. Problem is the vertex positions, can I get them in a fast way on a large object?
I also need a quick way to attach, or update the Big object with all the changes made in the New Object. More of this later, detach is the biggest problem right now.
/Andreas
more about PolySpeed:
www.fusion-wave.com/forum/index.php
Ok this function is pretty fast if you don’t use it too often:
polyOp.getVertsUsingFace $ #{1}
So it’s easy to get all the vertices, I think I need to first build the vertices and then a face from them. The best would be if it’s possible to create the faces directly, or even better if you could just say
“create a face exactly like this on but on another object”
If I use the above function it will still be slow for very large selections. If the user selects 50 faces I have to loop 50 times:
for i=1 to 50 do polyOp.getVertsUsingFace $ #{i}
But if the selection is 4000 polygons and this is not impossible, then we have problems. It takes several seconds to loop this, not sure why the maxScript is normally faster than this.
/Andreas
Hi Andreas, how are you? Still putting in long hours on PolySpeed I see.
I’m considering something along the same lines. First getting the info from the selected faces, then getting the verts that are also connected to unselected faces (for rebuilding). Then building a new mesh.
Haven’t done any speed tests though. I’ll let you know if I make any progress.
- R
what happens if you use the face selection and convert it to Vertices?
such as:
$.ConvertSelection #face #vertex
wouldnt that be faster than looping through each face?
Reconstructing the mesh was the first idea that came to my mind. However, it seems a bit trickier than I first thought. This is what I came up with:
a=polyop.getnumfaces $
ar=#() --init vertex array
ar2=#() --init polygon array
for h=1 to a do --go through all polygons
(
ar[h]=#() --init subarray
b=polyop.getvertsusingface $ #(h) as array
for i=1 to b.count do
(
ar[h][i]=polyop.getvert $ b[i] --store vertex positions to subarray
)
)
for h=1 to ar.count do --go through polygons again
(
ar2=#()
for i=1 to ar[h].count do --create vertices and store index numbers to array
ar2[i]=polyop.createvert $plane01 ar[h][i]
polyop.createpolygon $plane01 ar2 --create a polygon
)
It attempts to recreate selected object inside plane01. The problem with this is that the array used to create polygon is not sorted correctly and the result is quite weird. Try using it to see what I mean. I have only tried it on 100 polygon object and it takes less than second to run. I’m still rather new to maxscript and this is propably the best script I’ve ever made, so yay to me .
Hi all. Nice to see some responses.
Late hours, hehe. Late, tsk, it’s only 02 here, that is nothing…(ehm, friday night though)
I found one flaw with version 1) that i was using so I can make it far faster. What I did was I FIRST inverted the selection then I detached this. But oh boy, it’s far slower to detach many fases than only a few. So if instead only detach the selection it seems to be nearly as fast as my snapshot trick, which is great since I don’t like that one.
To convert from #face to #verts idoes not seem to be a good idea. This is a fairly heavy operation and I think I would have to do it one time for every face. The reason is that otherwise I won’t know what faces are connected to the verts. I will just have a jumble of verts and no way of knowing which I should connect.
I did some speed tests and the detach for a 260k object takes 2300mseconds on my machine.
I can get the vertex info for 100 vertices in 220ms, but then I also have to build them or at least move already existing verts to this position and create the faces.
Another simple, but painful way to speed everything up that I will add later is to have the startobject as a mesh. Detach is WAY faster for editable_meshes. Since you will only model the detail object only the little detail object really need to be a poly object. Will speed up the viewports too. But arg(!) I have to make most of my functions work with editable_mesh as well.
I will try the script above, thanks for the answers everyone, keep em comming
/Andreas
Also is it possible to move say 100 vertices with one line of maxScript code or at least so that the object doesn’t update.
With meshes you can move many verts very fast, since you only update it in the end, with polyobject you don’t seem to be able to do this, or?
/Andreas
Capt S. that is a nice start. Yes it only creates tri faces now it seems.
If we create faces like this we can divide the problem into the following areas:
- figure out the data for creating the object. this would seem to be the vertex positions and also what face they are connected too. This is quite time consuming, we need a fast way for this.
- building the poly_object. As long as the object isn’t too large this should be pretty fast I hope.
/Andreas
It’s lucky that I love optimizing so much. I have done some benchmarks and found a striking difference.
The function GetFaceVerts is 10 times faster than getVertsUsingFace but seem to be practically identically otherwise.
tStart=timeStamp()
for i=1 to 10000 do result[i]=polyOp.getFaceVerts test i
timeStamp()-tStart
–result is 1622ms
tStart=timeStamp()
for i=1 to 10000 do result[i]=polyOp.getVertsUsingFace test i
timeStamp()-tStart
–result is 11036ms
tests that also takes the position:
tStart=timeStamp();
–total=#{}
for i=1 to 10000 do
(
result[i]=polyOp.getFaceVerts test i;
)
for i=1 to 10000 do tPos[i]=polyOp.getVert test i node:test –faster if it’s outside
timeStamp()-tStart
Problems:
There are at least 2 big problems right now.
When we create this new area we should also delete the start selection. But this is very slow. So we almost have to avoid it.
One Idea I had was that we keep the original geometry, but make it hidden. When the user attaches later then I just move the vertices in the big object so that they match those in the little New object. One problem right away then, is that updating the mesh is very slow, since you have to move 1 vertex at a time.
To move 1000 verts on a 260k object (one at a time), took a depressing 20 seconds. I think the edit_mesh has better ways to update the mesh though.
/Andreas
The script actually also creates quads but in such manner that it appears to be 2 tris facing opposite directions…which is bad :p. Getfaceverts is not only faster but it also return the verts in order so when I replace “b=polyop.getvertsusingface $ #(h) as array” with “b=polyop.getfaceverts $ h” the script works. I’ve never noticed there is such function so I couldn’t really use it :).