Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dimensions of the NFT marker in the NFTMarkerInfo to fix marker position #42

Open
wants to merge 32 commits into
base: develop
Choose a base branch
from

Conversation

kalwalt
Copy link
Owner

@kalwalt kalwalt commented Feb 3, 2020

Discussion started in issue #41.
List of feature to add:

  • printing in the console of width, height, dpi of the loaded NFT marker.
  • width, height, dpi as data members in the arController struct inside ARToolKitJS.cpp
  • inject width, height, dpi to NFTMarkerInfo to transmit the data through the event mecahnism.

The model is positioned with this formula:

model.position.y = (msg.height / msg.dpi * 2.54 * 10)/2.0;
model.position.x = (msg.width / msg.dpi * 2.54 * 10)/2.0;

@kalwalt kalwalt added C/C++ coding with C and C++ language code design NFT nft markerless technology labels Feb 3, 2020
@kalwalt kalwalt self-assigned this Feb 3, 2020
@kalwalt
Copy link
Owner Author

kalwalt commented Feb 3, 2020

This is the result in the log console, you can see the width height and dpi:

THREE.WebGLRenderer 103
artoolkit.min.js:1 onload callback should be defined
artoolkit.min.js:1 onerror callback should be defined
artoolkit.min.js:1 [warning] *** Camera Parameter resized from 640, 480. ***
artoolkit.min.js:1 [info] Allocated videoFrameSize 307200
artoolkit.min.js:1 [info] Reading /markerNFT_0.fset3
artoolkit.min.js:1 [info]   Assigned page no. 0.
artoolkit.min.js:1 [info]   Done.
artoolkit.min.js:1 [info] Reading /markerNFT_0.fset
artoolkit.min.js:1 [info] 
artoolkit.min.js:1 ### Surface No.1 ###
artoolkit.min.js:1 [info]   Read ImageSet.
artoolkit.min.js:1 [info] Imageset contains 9 images.
artoolkit.min.js:1 [info]     end.
artoolkit.min.js:1 [info]   Read FeatureSet.
artoolkit.min.js:1 [info]     end.
artoolkit.min.js:1 [info] NFT num. of ImageSet: 9
artoolkit.min.js:1 [info] NFT marker width: 893
artoolkit.min.js:1 [info] NFT marker width: 1117
artoolkit.min.js:1 [info] NFT marker dpi: 120
artoolkit.min.js:1 [info]   Done.
artoolkit.min.js:1 [info] points-636
artoolkit.min.js:1 [info] points-648
artoolkit.min.js:1 [info] points-615
artoolkit.min.js:1 [info] points-607
artoolkit.min.js:1 [info] points-590
artoolkit.min.js:1 [info] points-540
artoolkit.min.js:1 [info] points-508
artoolkit.min.js:1 [info] points-437
artoolkit.min.js:1 [info] points-269
artoolkit.min.js:1 [info] Loading of NFT data complete.
artoolkit.worker.js:37 loadNFTMarker ->  0

@kalwalt
Copy link
Owner Author

kalwalt commented Feb 5, 2020

Maybe we could do the calculation of the center of the marker inside the C++ code what do you think @nicolocarpignoli ?

@nicolocarpignoli
Copy link
Collaborator

I think it has to be done outside it. It is enough what you did. We may add on this PR, before merging it, the use of these new parameters, so remove the y = 100 x = 100 from where we decide statically the position, and calculate it dynamically inside the code.

after that we can merge this :D !

@kalwalt
Copy link
Owner Author

kalwalt commented Feb 6, 2020

Maybe we can find the center position from the matrix data, i have an idea in mind, will try tomorrow for sure.

@nicolocarpignoli
Copy link
Collaborator

Ok so after some tests, We found out that width/height of marker are not enough: we also need width/height of 3D objects.

With that, we can fix the center the 3D object at the center of the Marker.

image

Practically talking, we can calculate the blue lines (distances).

If knowing exactly the 3D object position is not doable in a way so that we have certain data, I think it is not a matter on waste other time/effort.

@kalwalt
Copy link
Owner Author

kalwalt commented Feb 9, 2020

@nicolocarpignoli have you tried doing this? If this not works, i'm thinking for another approach. Maybe we can find the center of the marker from the four corners of the markers. If we have the matrix of the marker we can do this. We have already some code like this see

if (!lastmsg) return;
var proj = JSON.parse(lastmsg.proj);
var world = JSON.parse(lastmsg.matrixGL_RH);
var mat = multiplyMatrices(proj, world);
function glpointToCanvas(xyz) {
return {
x: (xyz.x + 1) * 0.5 * pw / pscale * sscale - ox / pscale * sscale,
y: (1 - xyz.y) * 0.5 * ph / pscale * sscale - oy / pscale * sscale,
}
}
function drawpoint(x, y, z) {
var r = transformPoint(mat, {x: x, y: y, z: z});
var c = glpointToCanvas(r);
return c;
}
var width = marker.width;
var height = marker.height;
var dpi = marker.dpi;
var w = width / dpi * 2.54 * 10;
var h = height / dpi * 2.54 * 10;
var p1 = drawpoint(0, 0, 0);
var p2 = drawpoint(w, 0, 0);
var p3 = drawpoint(w, h, 0);
var p4 = drawpoint(0, h, 0);
context_draw.beginPath();
context_draw.moveTo(p1.x, p1.y);
context_draw.lineTo(p2.x, p2.y);
context_draw.lineTo(p3.x, p3.y);
context_draw.lineTo(p4.x, p4.y);
context_draw.closePath();
context_draw.strokeStyle = "red";
context_draw.stroke();
};

@nicolocarpignoli
Copy link
Collaborator

@kalwalt I have tried to calculate the 3D object dimensions and use them, along with NFT marker width height and dpi.

I have to be honest: the calculation I did does not make too much sense to me, it's solely based on empirics.
But it works for Flamingo + Pinball Image. We need other tests before think it is correct. Are you able to do some test with 1-2 different 3D models and 1-2 different images as nft marker?

@nicolocarpignoli
Copy link
Collaborator

I got the 3D model sizes like this (don't know if it's correct)

   var dimensions = new THREE.Box3().setFromObject(model);
            objPositions = {
                width: dimensions.max.x - dimensions.min.x,
                height: dimensions.max.y - dimensions.min.y,
            };

@kalwalt
Copy link
Owner Author

kalwalt commented Feb 10, 2020

i will give a try when i have time. 😄

@kalwalt
Copy link
Owner Author

kalwalt commented Feb 10, 2020

@nicolocarpignoli it seems that for the sphere not works in the same way for the flamingo model. I will try to solve this. In the meantime i will upload another example with a different model.

@ThorstenBux
Copy link

Tested on iOS,

Portrait works awesome and model is in the centre.
Landscape: Model vanishes and I can't find it anymore. (Not sure if that is expected to be like that)

@kalwalt
Copy link
Owner Author

kalwalt commented Mar 29, 2020

Landscape: Model vanishes and I can't find it anymore. (Not sure if that is expected to be like that

That's very bad. I have not checked so much in landscape mode. I assumed that if it works fine on portrait. should work fine also on landcape mode.

@kalwalt
Copy link
Owner Author

kalwalt commented Mar 29, 2020

@ThorstenBux the model is wrong placed when you switch from portrait to landscape mode. The model is placed on the origin of the marker ( the left bottom of it). If you reload the page while in landscape mode the model is correctly placed in the center of the marker. I need to solve this, maybe forcing to update the matrix? or does it is caused by another factor?

@nicolocarpignoli
Copy link
Collaborator

On my Hawuei, it is repositioning good switching from landscape/portrait and back.

Apart from the strange rotation (that we can change from the application, no problem) I see a weird animation flow. It is not the correct one. But I guess it does not have anything to do with this PR

@nicolocarpignoli
Copy link
Collaborator

@kalwalt
Copy link
Owner Author

kalwalt commented Mar 30, 2020

that's good that with the flamingo model switching from portrait to landscape mode and back the position is correct, maybe there are some differences in the code that make react in a different way.

I see a weird animation flow.

it is possible, i will look into this if it is caused by the actual implementation.

i rotated the model on the X axis because this should be the right position. ( you should see in a viewer) but this is less important...

@ThorstenBux
Copy link

ThorstenBux commented Mar 30, 2020 via email

@kalwalt
Copy link
Owner Author

kalwalt commented Mar 30, 2020

i have this problem, the wrong position of the mesh while switching from portrait to landscape mode, also for other examples. I tried to put the code to adjust the position in the loader:

threeGLTFLoader.load("../Data/models/Flamingo.glb", function (gltf) {
// other code...
// width=2100 height=1576 dpi=150
model.position.y = (2100 / 150 * 2.54 * 10)/2.0;
model.position.x = (1576 / 150 * 2.54 * 10)/2.0; 
// other code...
}

but not solve anything...

@kalwalt
Copy link
Owner Author

kalwalt commented Mar 30, 2020

I will try another approach, I will try to do a translation matrix inside the C++, it should be possible manipulating the trans matrix...

@kalwalt
Copy link
Owner Author

kalwalt commented Mar 31, 2020

@kalwalt
Copy link
Owner Author

kalwalt commented Mar 31, 2020

Maybe we can find a simpler solution, we could force a page to reload with location.reload() see this stackoverflow article, maybe creating an EventListener that triggers a reload when changing the window mode?

@kalwalt
Copy link
Owner Author

kalwalt commented Mar 31, 2020

i addedd in the flamingo example before the end of the </script> tag this snippet:

// Listen for orientation changes
window.addEventListener("orientationchange", function() {
  location.reload();
  return false;
}, false);

This make to reload the page when the orientation change and consequently the model is placed correctly. I would prefer to find another solution, as reloading is a waste of time.

@kalwalt
Copy link
Owner Author

kalwalt commented Apr 1, 2020

Inside the found function (flamingo example) i did this, but do not help:

var found = function(msg) {
       if (!msg) {
           world = null;
       } else {
           world = JSON.parse(msg.matrixGL_RH);

           if (!window.firstPositioning) {
               window.firstPositioning = true;
               model.position.y = (msg.height / msg.dpi * 2.54 * 10)/2.0;
               model.position.x = (msg.width / msg.dpi * 2.54 * 10)/2.0;
           }

           window.addEventListener("orientationchange", function() {
             // Announce the new orientation number
             console.log(screen.orientation);
             model.updateWorldMatrix(true, true);          
           }, false);

           console.log("NFT width: ", msg.width);
           console.log("NFT height: ", msg.height);
           console.log("NFT dpi: ", msg.dpi);
           var o_view = scene.getObjectByName('Flamingo');
           console.log(o_view);
       }
   };

@kalwalt
Copy link
Owner Author

kalwalt commented Apr 14, 2020

I think that enter the data ( width, height, dpi of the marker) in the dispatch event, maybe has no sense. It's better maybe if we retrieve these data while we load the NFT marker. See this code: https://github.com/kalwalt/FeatureSET-Display/blob/7aaab29930a2069ad3ea783f4f467f4f8c761fc7/emscripten/ARimageFsetDisplay.cpp#L99
It loads the marker and fill the struct with the data. I thnk that is a better option. Probably i will close this PR and will open a new one.

@evaristoc
Copy link

evaristoc commented Apr 20, 2020

#42 (comment)

Not sure if good idea... If someone has an animation that shouldn't stop no matter the view, reloading could restart the animation instead and the flow of the animation would not be as expected.

@evaristoc
Copy link

#42 (comment)

I guess the marker is still detected after the change in landscape/portrait view?

@kalwalt
Copy link
Owner Author

kalwalt commented Apr 20, 2020

Not sure if good idea... If someone has an animation that shouldn't stop, reloading could restart the animation instead.

@evaristoc i agree with you, i left this idea.

I guess the marker is still detected after the change in landscape/portrait view?

I think yes and the 3d model is always displayed, I think that is something related to updating the matrix but still not found a solution.

@evaristoc
Copy link

And @kalwalt

What do you see in the ARLOGi when log-consoling the same value (#42 (comment))?

@kalwalt
Copy link
Owner Author

kalwalt commented Apr 20, 2020

Hi @kalwalt

what are these values?
https://github.com/kalwalt/FeatureSET-Display/blob/7aaab29930a2069ad3ea783f4f467f4f8c761fc7/emscripten/ARimageFsetDisplay.cpp#L147

Thiis link refer to another project, the Faeture Set displayer, but the values is the width and height of image to be displayed for the size of the pointer.

And @kalwalt

What do you see in the ARLOGi when log-consoling the same value (#42 (comment))?

As i remember, this give always the width and height of the pinball marker. I think that outputting always in the stream these values is not necessary. It would be better retrieve these values only when loading the NFT marker and store them in a variable. I tried for https://github.com/kalwalt/FeatureSET-Display and it worked...

@evaristoc
Copy link

evaristoc commented Apr 20, 2020

this give always the width and height of the pinball marker

So what is the difference between this value and the values of width and height obtained at #42 (comment)?

My question is based on the possibility that the interpretation of width and height might change when changing the view. It might not be the issue based on @nicolocarpignoli video: it appears that the object rotated accordingly. But I want to be sure that is not the problem you are seeing.

Different devices treat the change of view differently.

@evaristoc
Copy link

evaristoc commented May 14, 2020

This formula, @kalwalt :
model.position.y = (msg.height / msg.dpi * 2.54 * 10)/2.0;
model.position.x = (msg.width / msg.dpi * 2.54 * 10)/2.0;

The value of 2.54, what is exactly that? EDIT: 2.54 is the conversion from centimeters to inches. It appears this is a conversion into centimeters?

I am not really sure but I suspect using dot density (dpi == dots per inch) will render different sizes in different devices in the directions of x and y. The larger the dpi, the smaller the relation msg.LENGTH/msg.dpi. I wonder if that explains what happens with the different results from the different tests when comparing different devices? Larger dpis might give a smaller object, if I am correct.

If that is true, the approach might not be generalizable: different devices will see different scenes sizes.

Can anyone confirm this claim?

Regarding the positioning: In my opinion, the ideal would be to calculate the appropriate coordinate system and then render the figure on top on that system. I am not sure if the suggestion by @nicolocarpignoli (#42 (comment)) corresponds to a standard. As I see it, the final result should be a square which center would correspond to the center of the marker, in clip coordinates (2d(-1,1)). As far as I know, keeping aspect ratio of the square is relatively standard too. However, this wouldn't correct for scene size per device if my claim is true.

@h3retic-EEL
Copy link

I premise by thanking you for your efforts, guys.
@kalwalt @nicolocarpignoli Is there any chance to have a nightly ar-with-nft.js build with the image tracking position fixed? Thank you.

@kalwalt
Copy link
Owner Author

kalwalt commented Oct 11, 2021

I premise by thanking you for your efforts, guys. @kalwalt @nicolocarpignoli Is there any chance to have a nightly ar-with-nft.js build with the image tracking position fixed? Thank you.

Thank you @Hadrhune, I'm working to the AR.js feature in this PR AR-js-org/AR.js#114 though i haven't yet a working solution for Aframe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C/C++ coding with C and C++ language code design NFT nft markerless technology
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants