PDA

View Full Version : Two vertices at same position


renzosanc
05-11-2009, 11:04 PM
Hello,

I would like to know if two vertices are in the same position. The STL Ckeck modifier helps a lot, but I still have two vertices in the same position and the STL Check shows me 0 errors.

So, a script is the solution for my problem. If I use Editable Mesh, my script works fine with:

VertSel = #{}

..

Vertex1=GetVert Obj j
Vertex2=GetVert Obj (j+1)

if Vertex1.x==Vertex2.x and Vertex1.y==Vertex2.y and Vertex1.z==Vertex2.z then
(
append VertSel j
append VertSel (j+1)
)

setvertselection obj VertSel



But, I need to use Editable Poly, however when I use Editable Poly with the variation:

Vertex1=Obj.GetVertex j
Vertex2=Obj.GetVertex j+1

Obj.SetSelection #Vertex VerSel



I get this error:

-- Unable to convert: undefined to type: BitArray

The error is in the line:

Obj.SetSelection #Vertex VerSel

Any idea of this error?

SyncViewS
05-12-2009, 12:10 AM
Hi Renzo,
don't know what's the error cause, but you can get the same results in other ways. I took the liberty to write a useless piece of working code to give you some hints.

The script is not so smart because doesn't test overlapping verts in the whole geometry but only if two verts with adjacent index share the same position. Remeber to use a threshold value for testing because you could miss matching verts because of rounding errors. I hope you don't mind me asking what's your script purpose.

(
obj = selection[1]

local fThresh = 1e-4

local baVertSel = #{}
local p3Vertex1 = [0,0,0]
local p3Vertex2 = [0,0,0]

local iNumVerts = 0

if ((classOf obj) == Editable_Mesh) then
(
iNumVerts = meshOp.getNumVerts obj

for j = 1 to (iNumVerts-1) do
(
p3Vertex1 = meshOp.getVert obj j
p3Vertex2 = meshOp.getVert obj (j+1)

if ((distance p3Vertex1 p3Vertex2) <= fThresh) then
(
baVertSel[j] = true
baVertSel[j+1] = true
)
)
setVertSelection obj baVertSel
forceCompleteRedraw()
)
else if ((classOf obj) == Editable_Poly) then
(
iNumVerts = polyOp.getNumVerts obj

for j = 1 to (iNumVerts-1) do
(
p3Vertex1 = polyOp.getVert obj j
p3Vertex2 = polyOp.getVert obj (j+1)

if ((distance p3Vertex1 p3Vertex2) <= fThresh) then
(
baVertSel[j] = true
baVertSel[j+1] = true
)
)
polyOp.setVertSelection obj baVertSel
forceCompleteRedraw()
)
)
- Enrico

renzosanc
05-12-2009, 01:53 AM
Hi Enrico,

Thank you for your help and for taking the time to write a new code. It was my stupid mistake. In the 'editable mesh' code I am using:

setvertselection obj VertSel

And in the 'editable poly' code I am using:

Obj.SetSelection #Vertex VerSel

So, I was using VerSel instead of VertSel, it was the reason of the error code. Can you beleive that? I spent some hours in that stupid error. Shame on me!!!

I have a question anyway. Why the code with the 'editable mesh' is a lot much faster than the code with 'editable poly'? I am using an object with 1998 vertices and both codes are working now, but if I use an editable mesh, the code run very quickly, but with an editable poly it takes a few seconds.

I hope you don't mind me asking what's your script purpose.
I need to export many objects for stencil shadows for a real time application (game). In order to a mesh to works for stencil shadow needs some features. No open edges, for example. So, I use the STL Check modifier, but also there is an error with stencil shadows if two vertices are in the same position, so I am making this script for that. I need to use Editable Poly because I need to connect and collapse the vertices that are in the same position.


The script is not so smart because doesn't test overlapping verts in the whole geometry but only if two verts with adjacent index share the same position.

I am making the same in my code because the problem with two vertices at the same position happend in adjacent index vertex, and it would take longer time if I test each vertex with all the rest of vertices.


Remeber to use a threshold value for testing because you could miss matching verts because of rounding errors.

Yes, it is a good idea to use a threshold value. Thanks.

EDITED: Using your code, both editable mesh and editable poly works at the same speed, so I guess there is another bug with my code in the editable poly version.

SyncViewS
05-12-2009, 09:38 AM
Hi Renzo,
here is a function to do the job. It cycles over all selected objects and performs two test: find overlapped verts and detect open edges. An autoCollapse trigger allows to perform the collapse during check. I hope is what you need.

function geometryCheck fThresh autoCollapse:false =
(
local objs = selection as Array
local sOpenObjs = ""

local baVertSel = #{}

local ap3VertPos = #()
local baVertEdges = #{}

local iNumVerts = 0
local iNextVert = 0

local baEdgesToCollapse = #{}

for obj in objs do
(
baVertSel = #{}

ap3VertPos = #()
baVertEdges = #{}

baEdgesToCollapse = #{}

if ((classOf obj) == Editable_Mesh) then
(
iNumVerts = meshOp.getNumVerts obj

for i = 1 to iNumVerts do
append ap3VertPos (meshOp.getVert obj i)

for j = iNumVerts to 1 by -1 do
(
baVertEdges = meshOp.getEdgesUsingVert obj j

for iEdge in baVertEdges do
(
iNextVert = (((meshOp.getVertsUsingEdge obj iEdge) - #{j}) as Array)[1]

if ((distance ap3VertPos[j] ap3VertPos[iNextVert]) <= fThresh) then
(
baVertSel[j] = true
baVertSel[iNextVert] = true

if (autoCollapse) then
baEdgesToCollapse[iEdge] = true
)
)
)
setVertSelection obj baVertSel

if (autoCollapse) then
meshOp.collapseEdges obj baEdgesToCollapse


baOpenEdges = meshOp.getOpenEdges obj
if (baOpenEdges.isEmpty == false) then
(
setEdgeSelection obj baOpenEdges
sOpenObjs += ("\n" + obj.name)
)
)
else if ((classOf obj) == Editable_Poly) then
(
iNumVerts = polyOp.getNumVerts obj

for i = 1 to iNumVerts do
append ap3VertPos (polyOp.getVert obj i)

for j = iNumVerts to 1 by -1 do
(
baVertEdges = polyOp.getEdgesUsingVert obj j

for iEdge in baVertEdges do
(
iNextVert = (((polyOp.getVertsUsingEdge obj iEdge) - #{j}) as Array)[1]

if ((distance ap3VertPos[j] ap3VertPos[iNextVert]) <= fThresh) then
(
baVertSel[j] = true
baVertSel[iNextVert] = true

if (autoCollapse) then
baEdgesToCollapse[iEdge] = true
)
)
)
polyOp.setVertSelection obj baVertSel

if (autoCollapse) then
polyOp.collapseEdges obj baEdgesToCollapse

baOpenEdges = polyOp.getOpenEdges obj
if (baOpenEdges.isEmpty == false) then
(
setEdgeSelection obj baOpenEdges
sOpenObjs += ("\n" + obj.name)
)
)
forceCompleteRedraw()
)
if (sOpenObjs != "") then
messageBox ("Following objects have open edges:" + sOpenObjs)

return OK
)
- Enrico

renzosanc
05-12-2009, 06:36 PM
Hi Enrico,

Thank you very much for your help. Finally I will use your code, I found some vertices that are not adjacent and are at the same position. Could you make this change for me please?

I don't need to collapse the open edges, I just need to show the open edges like it is in your code and 'Connect' (in Editable Poly) the vertices that share the same position and then 'Collapse' these vertices. For example, given this list of vertices:

V1 (1, 4, 3)
V2 (1, 4, 3)
V3 (1, 2, 8)
V4 (1, 3, 9)
V5 (1, 3, 9)

I would need to connect and collapse V1 and V2 and then V4 and V5. So finally my object will have 3 vertices instead of 5.
So, how can I group data and make an operation to each group?

SyncViewS
05-12-2009, 07:19 PM
Hi Renzo,
I'm not sure to understand your request since the latest script version seems to already do what you're asking. Right now the algorithm cycles over each vert in geometry and looks for every edge starting from it, then if the length of an edge is less than provided threshold, the two verts of such edge are selected, if autoCollapse is true, they're collapsed too. You don't need to connect verts if they already share an edge before collapsing it.

Maybe you mean you want to collapse verts in a face not sharing an edge? Like, giving numbers to verts in a quad clockwise from 1 to 4, you need to check and collapse overlapping pairs 1-3 or 2-4? In that case you would need a connect before.

Then algorithm searches then for open edges and if found selects them and shows a message box for feedback.

On the verts sample you provided, it should give as is now the result you're looking for. Can you tell me if anything is wrong?

- Enrico

renzosanc
05-13-2009, 04:40 PM
Hi Enrico,

My fault again. I thought that you were collapsing edges because of 'polyOp.collapseEdges' instead of 'polyop.collapseVerts', but I've just tested your script in a model an it is working fine.

I don't know much about 3ds max, I know max script because it is very similar to c++ and the listener helps a lot. :)

When I did this process manually, I remember to find some vertices in the same position that I coudn't collapse unless I use the option 'connect' first. I guess that they were vertices that don't share an edge.

Thank you for all your help. I appreciated that. :)

SyncViewS
05-13-2009, 06:13 PM
Hi Renzo,
here is a small update in the Editable Poly section. It now works on every vert that share a face with the checked one, so even if in a quad two verts are in the opposite position like pairs 1-3 and 2-4, and don't share an edge, if their position matches they're selected, connected and collapsed if autoConnectOption is set to true. Mind that if you run this on nGons like pentagons, you can end up with bad looking topology like a vert in the middle of an edge, because of collapsing effect. Anyway, I hope this works well for you.

function geometryCheck fThresh:1e-4 autoCollapse:false =
(
local objs = selection as Array
local sOpenObjs = ""

local iFlag = bit.set 0 30 true

local baVertSel = #{}

local ap3VertPos = #()
local baVertEdges = #{}

local iNumVerts = 0
local iNextVert = 0

local baEdgesToCollapse = #{}

for obj in objs do
(
baVertSel = #{}

ap3VertPos = #()
baVertEdges = #{}

baEdgesToCollapse = #{}

if ((classOf obj) == Editable_Mesh) then
(
iNumVerts = meshOp.getNumVerts obj

for i = 1 to iNumVerts do
append ap3VertPos (meshOp.getVert obj i)

for j = iNumVerts to 1 by -1 do
(
baVertEdges = meshOp.getEdgesUsingVert obj j

for iEdge in baVertEdges do
(
iNextVert = (((meshOp.getVertsUsingEdge obj iEdge) - #{j}) as Array)[1]

if ((distance ap3VertPos[j] ap3VertPos[iNextVert]) <= fThresh) then
(
baVertSel[j] = true
baVertSel[iNextVert] = true

if (autoCollapse) then
baEdgesToCollapse[iEdge] = true
)
)
)
setVertSelection obj baVertSel

if (autoCollapse) then
meshOp.collapseEdges obj baEdgesToCollapse


baOpenEdges = meshOp.getOpenEdges obj
if (baOpenEdges.isEmpty == false) then
(
setEdgeSelection obj baOpenEdges
sOpenObjs += ("\n" + obj.name)
)
)
else if ((classOf obj) == Editable_Poly) then
(
local baVertFaces = #{}
local baNearVerts = #{}

local iNewEdge = 0

iNumVerts = polyOp.getNumVerts obj

for i = 1 to iNumVerts do
append ap3VertPos (polyOp.getVert obj i)

for j = iNumVerts to 1 by -1 do
(
baVertEdges = polyOp.getEdgesUsingVert obj j
baVertFaces = polyOp.getFacesUsingVert obj j
baNearVerts = (polyOp.getVertsUsingFace obj baVertFaces) - (polyOp.getVertsUsingEdge obj baVertEdges)

for iEdge in baVertEdges do
(
iNextVert = (((polyOp.getVertsUsingEdge obj iEdge) - #{j}) as Array)[1]

if ((distance ap3VertPos[j] ap3VertPos[iNextVert]) <= fThresh) then
(
baVertSel[j] = true
baVertSel[iNextVert] = true

if (autoCollapse) then
polyOp.setEdgeFlags obj iEdge iFlag
)
)
for iVert in baNearVerts do
(
if ((distance ap3VertPos[j] ap3VertPos[iVert]) <= fThresh) then
(
baVertSel[j] = true
baVertSel[iVert] = true

if (autoCollapse) then
(
iNewEdge = polyOp.createEdge obj j iVert
polyOp.setEdgeFlags obj iNewEdge iFlag
)
)
)
)
polyOp.setVertSelection obj baVertSel

if (autoCollapse) then
(
baEdgesToCollapse = polyOp.getEdgesByFlag obj iFlag
polyOp.collapseEdges obj baEdgesToCollapse
)

baOpenEdges = polyOp.getOpenEdges obj
if (baOpenEdges.isEmpty == false) then
(
setEdgeSelection obj baOpenEdges
sOpenObjs += ("\n" + obj.name)
)
)
forceCompleteRedraw()
)
if (sOpenObjs != "") then
messageBox ("Following objects have open edges:" + sOpenObjs)

return OK
)
- Enrico

renzosanc
05-13-2009, 09:10 PM
ok Enrico. Thank you very much!!!

renzosanc
05-14-2009, 01:00 AM
Hey Enrico,

Why sometimes I can not connect and collapse vertices that are in the same position. I've attached an example, if you open the max file there are two vertices on the center of the screen that has the same position, vertex 540 and 547. It is not possible to connect and collapse those two vertices. Why?

BTW, your last script doesn't identify those vertices.

SyncViewS
05-14-2009, 11:23 AM
Hey, I'm sorry but I cannot open Max 2009(?) files. Can you please save it as .obj? Could it be that the tolerance set to 1e-4 is to low? Have you tried to increase it, like 1e-3?

- Enrico

renzosanc
05-14-2009, 05:28 PM
It won't help if I give you the object in obj, because the export to obj fix the problem. I have 1060 vertices in max and 965 vertices when I export it to obj.

However I've just found the problem. I had two polygons in the same place. Like if you create a plane, clone it, and move your clone plane to the same position of your original plane and then attach both planes.

I guess that I can not fix this problem automatically with a script, because in the case of a one plane bigger that a second plane in the same place I would not which plane should I delete. I expected a solution like if I connect and collapse the vertices in the same place, then the overlapping plane deletes automatically.

So, what I will do is to run your script first, and then run a second script that compare all the vertices in the object, so if the second script found any vertex then I know that I have overlapping planes and I could fix the problem manually. Anyway, the overlapping planes is a non common problem. :)

CGTalk Moderation
05-14-2009, 05:28 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.