Select to view content in your preferred language

Obj File Model Not Anchoring Properly

6653
27
04-01-2021 01:52 PM
RobBever
New Contributor III

Using engine v100.6.0, since as far as I know the 3D rendering speed problem introduced in 100.7.0 and worse in 100.8.0 is not yet resolved.

I have a simple .obj file. I simplified it as much as possible to determine why I was getting the behavior I was getting. Here's the .obj file, I'll also attach:

 

# Cube.obj

g Cube

v -1 1 -1
v 1 1 -1
v 1 1 1
v -1 1 1
v -1 -1 -1
v 1 -1 -1
v 1 -1 1
v -1 -1 1

#top
f 1 4 3 2
#front
f 1 2 6 5
#right
f 2 3 7 6
#back
f 4 8 7 3
#left
f 1 5 8 4
#bottom
f 5 6 7 8

 

So just a 2-unit cube centered at 0, 0, 0. I know there's a simple cube that can be generated; I'm just trying to understand the engine's behavior w.r.t. .obj files so I can make my own .obj files dynamically later.

I'm trying to anchor it at the center. This does not appear to work, either by AnchorPositioner.Center or AnchorPosition.Origin.

It seems clear that both Center and Origin should work the same. Here I've added this .obj file to my scene with its AnchorPosition set to Origin; I've also added a text label "0" at the given point and also I have a cone with AnchorPosition.Top which has its top set to the same point. In this case, the SymbolSizeUnits are set to Meters, and width == height == depth.

RobBever_0-1617309308331.png

Obviously this is not correct. The origin is in the center of the cube. Here I'll try AnchorPosition.Center:

RobBever_1-1617309442889.png

This looks right, although I've had problems with this when the points aren't as regular as this. So that looks correct.

Now we'll try SymbolSizeUnits.Dips, AnchorPosition.Center:

RobBever_2-1617309530093.png

Now we're anchoring to the bottom again for some reason. This behavior is different for SymbolSizeUnits.Dips vs. SymbolSizeUnits.Meters, but shouldn't be.

Now I'll try SymbolSizeUnits.Meters, AnchorPosition.Origin:

RobBever_3-1617309644315.png

RobBever_4-1617309752113.png

This is anchored to the bottom too. It doesn't appear that I can do anything to actually anchor at the center in SymbolSizeUnits.Dips mode. It always appears to use AnchorPosition.Bottom instead.

Is there anything I can do differently to be able to anchor at the center?

It would be ideal if I could use AnchorPosition.Origin, since I can control that, but it doesn't appear to work in any of these cases. It appears to replace Origin with Bottom. Perhaps internally it translates .obj vertices so the bottom is placed at a y value of 0?

Also, can you describe the algorithm used to determine the centroid of the object? I was creating another object and it wasn't at all clear where the centroid was considered to be, and it was causing it to rotate the model away from the point I wanted it to center at.

I tried adding additional unused vertices to "balance" it so the center would be the right point, but it was unsuccessful.

Tags (3)
0 Kudos
27 Replies
RobBever
New Contributor III

I'm glad there was interest in what I found. Thanks for taking a look at it!

I still can't run the test app:

RobBever_0-1617344083761.png

I tried building the main branch rather than master. Both branches fail to run due to (different) missing DLLs.

I could build and run the test app for 100.8.0 just fine, I'm not sure why it won't run now. Do I have to install something new?

I tried upgrading my code to 100.10.0. I'm not sure about the speed yet. I think it's better than 100.8.0, but I can't be sure. The example with the 3D buildings is really good for testing this and I can't run the test app.

I did test the anchor position though. Here it is with my cube, this is Units: Dips, Anchor Position: Origin, with the cube .obj file previously mentioned.

RobBever_1-1617345019146.png

Here's Meters/Origin:

RobBever_2-1617345091540.png

 

Here's Dips/Center:

RobBever_3-1617345178095.png

 

If you zoom in farther, you can get this:

RobBever_4-1617345188258.png

Finally here's Meters/Center:

RobBever_5-1617345270175.png

The behavior seems to be the same in 100.10.0 as it was in 100.6.0.

I hacked the code I added to the symbol example into my code, so here's that in 100.10.0. The blue sphere is at the specified point. From left to right this is Meters/Center, Meters/Origin, Dips/Center, Dips/Origin. Again, the cubes should all be centered in the same place as the sphere, unless I misunderstand:

RobBever_6-1617345860086.png

Zooming in on Dips/Center eventually produces this:

RobBever_7-1617345920330.png

This looks identical to the 100.6.0 behavior. It doesn't seem like any of these are what you'd expect except Meters/Center, and even then it's somewhat hard to work with since I don't know what algorithm you're using to calculate the center point.

I'd really like to be able to use the Dips unit size. That's extremely useful, but I can't use anything but Top or Bottom for the anchor position, which doesn't work well for what I want to do.

Thanks for taking a look for me. Let me know if there's anything I can do differently to get the behavior I'm looking for.

Here's my test code this time:

var overlay = ModelGraphicsOverlay;

const int CUBE_SIZE = 200;

// Meters, Center
MapPoint testPoint = new MapPoint(44.976, 29, 1000, SpatialReferences.Wgs84);
SimpleMarkerSceneSymbol testSymbol = new SimpleMarkerSceneSymbol(SimpleMarkerSceneSymbolStyle.Sphere, System.Drawing.Color.Blue, 100, 100, 100, SceneSymbolAnchorPosition.Center);
Graphic symbolGraphic = new Graphic(testPoint, testSymbol);
overlay.Graphics.Add(symbolGraphic);
// Meters, Center
ModelSceneSymbol mySymbol = ModelSceneSymbol.CreateAsync(new Uri(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location), "Models/Dish.obj"))).Result;
mySymbol.Width = mySymbol.Height = mySymbol.Depth = CUBE_SIZE;
mySymbol.AnchorPosition = SceneSymbolAnchorPosition.Center;
mySymbol.SymbolSizeUnits = SymbolSizeUnits.Meters;
Graphic myGraphic = new Graphic(testPoint, mySymbol);
overlay.Graphics.Add(myGraphic);

// Meters, Origin
testPoint = new MapPoint(44.986, 29, 1000, SpatialReferences.Wgs84);
testSymbol = new SimpleMarkerSceneSymbol(SimpleMarkerSceneSymbolStyle.Sphere, System.Drawing.Color.Blue, 100, 100, 100, SceneSymbolAnchorPosition.Center);
symbolGraphic = new Graphic(testPoint, testSymbol);
overlay.Graphics.Add(symbolGraphic);
// Meters, Origin
mySymbol = ModelSceneSymbol.CreateAsync(new Uri(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location), "Models/Dish.obj"))).Result;
mySymbol.Width = mySymbol.Height = mySymbol.Depth = CUBE_SIZE;
mySymbol.AnchorPosition = SceneSymbolAnchorPosition.Origin;
mySymbol.SymbolSizeUnits = SymbolSizeUnits.Meters;
myGraphic = new Graphic(testPoint, mySymbol);
overlay.Graphics.Add(myGraphic);

// Pixels, Center
testPoint = new MapPoint(44.996, 29, 1000, SpatialReferences.Wgs84);
testSymbol = new SimpleMarkerSceneSymbol(SimpleMarkerSceneSymbolStyle.Sphere, System.Drawing.Color.Blue, 100, 100, 100, SceneSymbolAnchorPosition.Center);
symbolGraphic = new Graphic(testPoint, testSymbol);
overlay.Graphics.Add(symbolGraphic);
// Pixels, Center
mySymbol = ModelSceneSymbol.CreateAsync(new Uri(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location), "Models/Dish.obj"))).Result;
mySymbol.Width = mySymbol.Height = mySymbol.Depth = CUBE_SIZE;
mySymbol.AnchorPosition = SceneSymbolAnchorPosition.Center;
mySymbol.SymbolSizeUnits = SymbolSizeUnits.Dips;
myGraphic = new Graphic(testPoint, mySymbol);
overlay.Graphics.Add(myGraphic);

// Pixels, Origin
testPoint = new MapPoint(45.006, 29, 1000, SpatialReferences.Wgs84);
testSymbol = new SimpleMarkerSceneSymbol(SimpleMarkerSceneSymbolStyle.Sphere, System.Drawing.Color.Blue, 100, 100, 100, SceneSymbolAnchorPosition.Center);
symbolGraphic = new Graphic(testPoint, testSymbol);
overlay.Graphics.Add(symbolGraphic);
// Pixels, Origin
mySymbol = ModelSceneSymbol.CreateAsync(new Uri(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location), "Models/Dish.obj"))).Result;
mySymbol.Width = mySymbol.Height = mySymbol.Depth = CUBE_SIZE;
mySymbol.AnchorPosition = SceneSymbolAnchorPosition.Origin;
mySymbol.SymbolSizeUnits = SymbolSizeUnits.Dips;
myGraphic = new Graphic(testPoint, mySymbol);
overlay.Graphics.Add(myGraphic);

0 Kudos
dotMorten_esri
Esri Notable Contributor

Are you still using packages.config config to reference nuget packages? If so, I would highly recommend right-clicking that file and select to migrate to package references. It takes care of most of these build and deploy issues - especially when upgrading.

0 Kudos
RobBever
New Contributor III

I've been using packages.config, yes. I knew there was a new way for .NET Core, but I didn't realize they made that available for .NET Framework as well.

Thanks for pointing that out, looks like it's not too hard to switch. I'll definitely look at that.

I don't like to use relative paths for the package directory (my project needs it to be linked to "$(SolutionDir)\packages"), so I'll have to see how that gets along with package references.

Please see my results in 100.10.0 once I was able to build and run the example app, which I posted to this thread.

The AnchorPosition issue is the same, the behavior is identical. The 3D framerate is also still much lower than in 100.6.0, see my example videos.

0 Kudos
RobBever
New Contributor III

I realize I couldn't run the .NET Samples WPF app because I was building with VS2017. I built with VS2019 and it worked.

I ran my modified symbology demo that I gave source for above and it looks like this in 100.10.0:

RobBever_0-1617347927390.png

So the same as 100.6.0.

Performance was still much worse in 100.10.0 than in 100.6.0. I've attached example videos. The line of sight Geoelement demo works great for this test. This changed in 100.7.0 I believe, everything after 100.6.0 has much slower framerates in 3D.

0 Kudos
RobBever
New Contributor III

I really want this to work, so I went ahead and made an equivalent .dae file cube and ran my test again. That's another format I could work with. The cube has the same vertices as before, it's a 2-unit cube centered at the origin. So the corners are (-1, 1, 1), (1, 1, 1), (1, 1, -1), (-1, 1, -1), (-1, -1, 1), (1, -1, 1), (1, -1, -1), (-1, -1, -1).

It appears to me that the results are the same. Here I've added Bottom to my list to see how that anchor point compares, and I've added text labels for the different types of anchoring and symbol size units, though you can't typically see them for the Dips-sized ones. The text labels' bottom left corner represent the center point.

RobBever_0-1617743056586.png

These results for .dae files appear to be the same as the results for .obj files. It seems that whatever the issue is, it's consistent. Note again that this is with the test app 100.10.0, I've attached my updated code for that as well. Simply place cube3.dae in your Output\WPF\<build type>\Resources folder to run this code (rename .xaml.cs.txt to .xaml.cs, of course).

Meters/Center continues to work properly, and Meters/Bottom and Pixels/Bottom seem fine, but all the others are off from what you'd expect.

Meters/Origin does not appear correct; the origin is in the center of the cube, but Origin and Bottom appear identical:

RobBever_1-1617743406178.png

Dips/Center once again doesn't seem to actually center. Note that the bottom left of the text represents the anchor point:

RobBever_2-1617743488029.png

Here again, the sphere is centered on the anchor point, this is still Dips/Center:

RobBever_3-1617743513799.png

If I understand the anchor points correctly, the cube should go into the center of the sphere, it shouldn't ever be below it when zooming in with this anchor point.

Pixels/Origin and Pixels/Bottom appear identical:

RobBever_4-1617743637357.png

Surely with the origin being in the center of the cube, you'd expect that they'd be different. I also tried a cube .dae file where the center was (0, -1, 0), such that all the points were at or below a Y value of 0, and the result was the same.

I assume if I had to I could split my model in half and use Bottom on the top half and Top on the bottom half to create one model that's centered at its origin point, but I can't necessarily do that with prefab models, or at least I don't know how.

I tried another test where I had the origin point at (0, 0, 0) and had the vertices be (0, 0, 0), (2, 0, 0), (0, 2, 0), (0, 0, 2) etc., basically the same cube shifted by (1, 1, 1) so its origin is at the center. Here's what that looks like:

RobBever_5-1617744112375.png

RobBever_6-1617744115992.png

It looks exactly the same. The origin of the model appears to not affect how the anchor points work.

It appears that Bottom means Bottom Center, although I don't know how the center point is calculated. I would have guessed it would be more like Bottom Origin. This also means that I can't directly control where the Top and Bottom anchor points are either, since I don't know the calculation of the center point. (Is it calculated only with respect to the points on the plane with the bottom? Or is it the center point of the whole object in X and Z?)

From what I was able to find, supported formats are .obj, .dae, .3ds, and .fbx. So far the anchor points work the same in the first two, but they work as you'd expect with your prebuilt shapes from SimpleMarkerSceneSymbol. Is there any way to get the same behavior you get with SimpleMarkerSceneSymbol shapes for my 3D models?

 

Oops, it won't let me attach the .dae file, here it is, cube3.dae:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
<asset>
<contributor>
<authoring_tool>Google SketchUp 8.0.11752</authoring_tool>
</contributor>
<created>2012-04-27T21:07:03Z</created>
<modified>2012-04-27T21:07:03Z</modified>
<unit meter="0.02539999969303608" name="inch" />
<up_axis>Z_UP</up_axis>
</asset>
<library_visual_scenes>
<visual_scene id="ID1">
<node name="SketchUp">
<node id="ID2" name="instance_0">
<matrix>1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1</matrix>
<instance_node url="#ID3" />
</node>
<!-- <node id="ID28" name="instance_1"> -->
<!-- <matrix>1 0 0 118.1102362204724 0 1 0 118.1102362204724 0 0 1 0 0 0 0 1</matrix> -->
<!-- <instance_node url="#ID3" /> -->
<!-- </node> -->
<!-- <node id="ID29" name="instance_2"> -->
<!-- <matrix>1 0 0 118.1102362204724 0 1 0 -1.4210854715202e-014 0 0 1 0 0 0 0 1</matrix> -->
<!-- <instance_node url="#ID3" /> -->
<!-- </node> -->
</node>
</visual_scene>
</library_visual_scenes>
<library_nodes>
<node id="ID3" name="cube_component">
<instance_geometry url="#ID4">
<bind_material>
<technique_common>
<instance_material symbol="Material2" target="#ID6">
<bind_vertex_input semantic="UVSET0" input_semantic="TEXCOORD" input_set="0" />
</instance_material>
</technique_common>
</bind_material>
</instance_geometry>
</node>
</library_nodes>
<library_geometries>
<geometry id="ID4">
<mesh>
<source id="ID7">
<float_array id="ID10" count="24">
-1 1 -1
1 1 -1
1 1 1
-1 1 1
-1 -1 -1
1 -1 -1
1 -1 1
-1 -1 1
</float_array>
<technique_common>
<accessor count="8" source="#ID10" stride="3">
<param name="X" type="float" />
<param name="Y" type="float" />
<param name="Z" type="float" />
</accessor>
</technique_common>
</source>
<source id="ID8">
<float_array id="ID11" count="48">0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 1</float_array>
<technique_common>
<accessor count="16" source="#ID11" stride="3">
<param name="X" type="float" />
<param name="Y" type="float" />
<param name="Z" type="float" />
</accessor>
</technique_common>
</source>
<vertices id="ID9">
<input semantic="POSITION" source="#ID7" />
<input semantic="NORMAL" source="#ID8" />
</vertices>
<!-- <triangles count="8" material="Material2"> -->
<!-- <input offset="0" semantic="VERTEX" source="#ID9" /> -->
<!-- <p>0 1 2 1 0 3 4 5 6 5 4 7 8 9 10 9 8 11 12 13 14 13 12 15</p> -->
<!-- </triangles> -->
<polylist count="6" material="Material2">
<input semantic="VERTEX" source="#ID9" offset="0" />
<vcount>4 4 4 4 4 4</vcount>
<p>0 3 2 1 0 1 5 4 1 2 6 5 3 7 6 2 0 4 7 3 4 5 6 7</p>
</polylist>
</mesh>
</geometry>
</library_geometries>
<library_materials>
<material id="ID6" name="material">
<instance_effect url="#ID5" />
</material>
<material id="ID13" name="Color_005_">
<instance_effect url="#ID14" />
</material>
<material id="ID21" name="Color_A06_">
<instance_effect url="#ID22" />
</material>
</library_materials>
<library_effects>
<effect id="ID5">
<profile_COMMON>
<technique sid="COMMON">
<lambert>
<diffuse>
<color>1 1 1 1</color>
</diffuse>
</lambert>
</technique>
</profile_COMMON>
</effect>
<effect id="ID14">
<profile_COMMON>
<technique sid="COMMON">
<lambert>
<diffuse>
<color>0.4470588235294118 0.4470588235294118 0.4470588235294118 1</color>
</diffuse>
</lambert>
</technique>
</profile_COMMON>
</effect>
<effect id="ID22">
<profile_COMMON>
<technique sid="COMMON">
<lambert>
<diffuse>
<color>0.8 0 0 1</color>
</diffuse>
</lambert>
</technique>
</profile_COMMON>
</effect>
</library_effects>
<scene>
<instance_visual_scene url="#ID1" />
</scene>
</COLLADA>

0 Kudos
RobBever
New Contributor III

I found a .fbx cube as well. I don't know what the origin is for this cube, but the result is the same:

RobBever_0-1617749875075.png

Here's Dips/Center, still off-center when you zoom in:

RobBever_1-1617749911257.png

I got the example .fbx file here:

https://www.cgtrader.com/free-3d-models/various/various-models/simple-cube-1x1

0 Kudos
RobBever
New Contributor III

I found a .3ds cube. Here's that with my test setup:

RobBever_0-1617769839853.png

I got the cube from here:

https://www.cgtrader.com/free-3d-print-models/games-toys/puzzle/rubiks-cube

So it seems like all the different formats behave the same with respect to the anchor points, although I can't verify where the origin was for the .fbx and .3ds ones.

Another test I did was to try adding a couple of points to the .dae cube, one at the center of the bottom, and one way lower but in the center, to see what that would look like. Here's what the result was with my test setup:

RobBever_1-1617770064088.png

Basically that's just a cube going from (0, 0, 0) to (1, 1, 1) with two additional points, (0.5, 0.5, 0) and (0.5, 0.5, -22), and an additional face going between the last two points.

The cube looks squished because I gave all 3 dimensions the same size value, I expect that. This actually looks more reasonable; Meters/Origin looks good, other than the fact that the bottom corner of the cube is at the origin, so it shouldn't be centered where the sphere is, and Pixels/Origin looks similar and doesn't move around the sphere when you zoom as well.

I'm interested in Pixels/Bottom though. I would expect it to have the bottom of the spike at the center of the sphere at all times, but it doesn't. In that picture you can see the lowest point is below the anchor point, but then if you zoom in you get this:

RobBever_2-1617770307951.png

So now I'm just confused about how any of these anchor points work. Any insights you can give would be very helpful. Thanks.

0 Kudos
RobBever
New Contributor III

I found cubes in .blend, .ply, .stl, and .dxf formats and they all behaved pretty much the same w.r.t. anchor points.

Interesting that they still load fine despite being deprecated.

0 Kudos
RobBever
New Contributor III

Could I please get an update about this? I'd really like to know why the behavior is the way it is. It's very difficult to work with currently because of the inconsistency.

I did quite a bit of work to demonstrate the issue clearly. It would help to know if you see the problem and if there's any possibility it could be changed or at least explained more clearly.

For example, when it says "center," what does that mean? What algorithm does it use to determine where the "center" is, if it's not using the origin point? What algorithm does it use to determine "top"? Is "top" the highest point? What if there are lots of points at the top? Does it average the X and Z values, do some kind of weighted average, or something else?

Any more info I could get would be great. I really tried to demonstrate the issue as clearly as I could, and I think I showed that there was a problem. Thanks.

0 Kudos
radiump10
New Contributor

Hi, this Young from RuntimeSDK. Thanks for your time and effort. Sorry for the bad experience. I tried test it myself and found the inconsistency too. I found some formats like .fbx work for me, but others don't. We believe that the anchor position calculation might have some problems. Unfortunately, at the moment I couldn't tell you exactly how the calculations work and why they are incorrect, because they are old code written before I joined the team. Our team is currently investigating this and will keep you updated. Thanks for your patience.

0 Kudos