How to reproduce given viewport maintaining aspect ratio?












0















I have 3D scene rendered in a viewport that fits to the window size. So the viewport (camera) aspect ratio depends on window size. On top of the viewport I draw a frame that has aspect ratio 16:9 and it also fits the viewport and it's centered vertically and horizontally inside the viewport. The purpose of the frame is to show which part of the viewport will be rendered in 16:9 aspect ratio. See screen below:



enter image description here



Now I want to render same 3D scene in the viewport 16:9 that will contain exactly same "pixels" that are contained in orange frame on the screen above. So inside another window I create a viewport that has 16:9 aspect ratio, set the object and camera positions to exactlty same position/orientation as on the previous scene. This time both viewport and camera aspect ratios are 16:9. However pixels rendered inside viewport differ from pixels from orange frame on the first screen (the sticks should be "cut" in half):



enter image description here



I guess I missed some calculations that have to be done to reproduce exact viewport from orange frame but I can't figure out which. The data I have from first viewport:




  • viewport width/height/aspectRatio

  • orange frame width/height and position

  • scene object position

  • camera position/orientation/aspectRatio


The data I have from second viewport:




  • viewport width/height (aspect ratio = 16:9)

  • scene object position (same as in first viewport)

  • camera position (same as in first viewport)


What I need is to reproduce exact amount of first viewport (inside orange frame) in the second viewport.










share|improve this question





























    0















    I have 3D scene rendered in a viewport that fits to the window size. So the viewport (camera) aspect ratio depends on window size. On top of the viewport I draw a frame that has aspect ratio 16:9 and it also fits the viewport and it's centered vertically and horizontally inside the viewport. The purpose of the frame is to show which part of the viewport will be rendered in 16:9 aspect ratio. See screen below:



    enter image description here



    Now I want to render same 3D scene in the viewport 16:9 that will contain exactly same "pixels" that are contained in orange frame on the screen above. So inside another window I create a viewport that has 16:9 aspect ratio, set the object and camera positions to exactlty same position/orientation as on the previous scene. This time both viewport and camera aspect ratios are 16:9. However pixels rendered inside viewport differ from pixels from orange frame on the first screen (the sticks should be "cut" in half):



    enter image description here



    I guess I missed some calculations that have to be done to reproduce exact viewport from orange frame but I can't figure out which. The data I have from first viewport:




    • viewport width/height/aspectRatio

    • orange frame width/height and position

    • scene object position

    • camera position/orientation/aspectRatio


    The data I have from second viewport:




    • viewport width/height (aspect ratio = 16:9)

    • scene object position (same as in first viewport)

    • camera position (same as in first viewport)


    What I need is to reproduce exact amount of first viewport (inside orange frame) in the second viewport.










    share|improve this question



























      0












      0








      0


      0






      I have 3D scene rendered in a viewport that fits to the window size. So the viewport (camera) aspect ratio depends on window size. On top of the viewport I draw a frame that has aspect ratio 16:9 and it also fits the viewport and it's centered vertically and horizontally inside the viewport. The purpose of the frame is to show which part of the viewport will be rendered in 16:9 aspect ratio. See screen below:



      enter image description here



      Now I want to render same 3D scene in the viewport 16:9 that will contain exactly same "pixels" that are contained in orange frame on the screen above. So inside another window I create a viewport that has 16:9 aspect ratio, set the object and camera positions to exactlty same position/orientation as on the previous scene. This time both viewport and camera aspect ratios are 16:9. However pixels rendered inside viewport differ from pixels from orange frame on the first screen (the sticks should be "cut" in half):



      enter image description here



      I guess I missed some calculations that have to be done to reproduce exact viewport from orange frame but I can't figure out which. The data I have from first viewport:




      • viewport width/height/aspectRatio

      • orange frame width/height and position

      • scene object position

      • camera position/orientation/aspectRatio


      The data I have from second viewport:




      • viewport width/height (aspect ratio = 16:9)

      • scene object position (same as in first viewport)

      • camera position (same as in first viewport)


      What I need is to reproduce exact amount of first viewport (inside orange frame) in the second viewport.










      share|improve this question
















      I have 3D scene rendered in a viewport that fits to the window size. So the viewport (camera) aspect ratio depends on window size. On top of the viewport I draw a frame that has aspect ratio 16:9 and it also fits the viewport and it's centered vertically and horizontally inside the viewport. The purpose of the frame is to show which part of the viewport will be rendered in 16:9 aspect ratio. See screen below:



      enter image description here



      Now I want to render same 3D scene in the viewport 16:9 that will contain exactly same "pixels" that are contained in orange frame on the screen above. So inside another window I create a viewport that has 16:9 aspect ratio, set the object and camera positions to exactlty same position/orientation as on the previous scene. This time both viewport and camera aspect ratios are 16:9. However pixels rendered inside viewport differ from pixels from orange frame on the first screen (the sticks should be "cut" in half):



      enter image description here



      I guess I missed some calculations that have to be done to reproduce exact viewport from orange frame but I can't figure out which. The data I have from first viewport:




      • viewport width/height/aspectRatio

      • orange frame width/height and position

      • scene object position

      • camera position/orientation/aspectRatio


      The data I have from second viewport:




      • viewport width/height (aspect ratio = 16:9)

      • scene object position (same as in first viewport)

      • camera position (same as in first viewport)


      What I need is to reproduce exact amount of first viewport (inside orange frame) in the second viewport.







      math three.js 3d






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 20 '18 at 14:50







      user606521

















      asked Nov 20 '18 at 14:23









      user606521user606521

      4,521960137




      4,521960137
























          1 Answer
          1






          active

          oldest

          votes


















          1














          Code in PerspectiveCamera.js suggests that the fov (field of view) in Three.js gives the angle in the vertical direction.



          top = near * Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom


          Say you go with the default of 50°. Then that tan there will be tan(25°) except for JavaScript you actually need to compute that in radians. If you want the width to be 50° instead, you want fov = 2 * atan(tan(50°/2) * 9/16) except you need to convert between degrees and radians. The idea is that you take the tangens, apply the aspect ratio to map it from width (where you want to measure it) to height (where the class expects it), then reverse the tangens computation.



          But perhaps you don't want to specify the angle for the width. Perhaps you want the original scene at a vertical fov of 50°, but still want the adjusted cene to be the 16:9 clipped version of that. In this case you can multiply with the ratio of ratios. So if your original image was 4:3 and the new image is 16:9, multiply by (9/16)/(3/4) also known as (9*4)/(16*3) also known as 3/4 and you convert from original height to width to new height angle in one go.






          share|improve this answer
























          • Hey, thanks, I ended up with slightly different solution that seems to work. In the first viewport I calculate something I call "zScale": blueFrameHeight / orangeFrameHeight. Then in the second viewport after positioning camera I set camera.scale.z = zScale and it just works :). zScale is basically ratio between blue and orange viewport heights. Can you confirm that this works same as you described? I don't know why I need only ratio between heights but it seems to just work for all my cases...

            – user606521
            Nov 21 '18 at 12:43











          • Hmm, my code does not work in some scenarios... So I want to try what you wrote (ratio of ratios). You said I have to multiply by 3/4. But what I need to multiply exactly?

            – user606521
            Nov 22 '18 at 9:28











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53395092%2fhow-to-reproduce-given-viewport-maintaining-aspect-ratio%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          Code in PerspectiveCamera.js suggests that the fov (field of view) in Three.js gives the angle in the vertical direction.



          top = near * Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom


          Say you go with the default of 50°. Then that tan there will be tan(25°) except for JavaScript you actually need to compute that in radians. If you want the width to be 50° instead, you want fov = 2 * atan(tan(50°/2) * 9/16) except you need to convert between degrees and radians. The idea is that you take the tangens, apply the aspect ratio to map it from width (where you want to measure it) to height (where the class expects it), then reverse the tangens computation.



          But perhaps you don't want to specify the angle for the width. Perhaps you want the original scene at a vertical fov of 50°, but still want the adjusted cene to be the 16:9 clipped version of that. In this case you can multiply with the ratio of ratios. So if your original image was 4:3 and the new image is 16:9, multiply by (9/16)/(3/4) also known as (9*4)/(16*3) also known as 3/4 and you convert from original height to width to new height angle in one go.






          share|improve this answer
























          • Hey, thanks, I ended up with slightly different solution that seems to work. In the first viewport I calculate something I call "zScale": blueFrameHeight / orangeFrameHeight. Then in the second viewport after positioning camera I set camera.scale.z = zScale and it just works :). zScale is basically ratio between blue and orange viewport heights. Can you confirm that this works same as you described? I don't know why I need only ratio between heights but it seems to just work for all my cases...

            – user606521
            Nov 21 '18 at 12:43











          • Hmm, my code does not work in some scenarios... So I want to try what you wrote (ratio of ratios). You said I have to multiply by 3/4. But what I need to multiply exactly?

            – user606521
            Nov 22 '18 at 9:28
















          1














          Code in PerspectiveCamera.js suggests that the fov (field of view) in Three.js gives the angle in the vertical direction.



          top = near * Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom


          Say you go with the default of 50°. Then that tan there will be tan(25°) except for JavaScript you actually need to compute that in radians. If you want the width to be 50° instead, you want fov = 2 * atan(tan(50°/2) * 9/16) except you need to convert between degrees and radians. The idea is that you take the tangens, apply the aspect ratio to map it from width (where you want to measure it) to height (where the class expects it), then reverse the tangens computation.



          But perhaps you don't want to specify the angle for the width. Perhaps you want the original scene at a vertical fov of 50°, but still want the adjusted cene to be the 16:9 clipped version of that. In this case you can multiply with the ratio of ratios. So if your original image was 4:3 and the new image is 16:9, multiply by (9/16)/(3/4) also known as (9*4)/(16*3) also known as 3/4 and you convert from original height to width to new height angle in one go.






          share|improve this answer
























          • Hey, thanks, I ended up with slightly different solution that seems to work. In the first viewport I calculate something I call "zScale": blueFrameHeight / orangeFrameHeight. Then in the second viewport after positioning camera I set camera.scale.z = zScale and it just works :). zScale is basically ratio between blue and orange viewport heights. Can you confirm that this works same as you described? I don't know why I need only ratio between heights but it seems to just work for all my cases...

            – user606521
            Nov 21 '18 at 12:43











          • Hmm, my code does not work in some scenarios... So I want to try what you wrote (ratio of ratios). You said I have to multiply by 3/4. But what I need to multiply exactly?

            – user606521
            Nov 22 '18 at 9:28














          1












          1








          1







          Code in PerspectiveCamera.js suggests that the fov (field of view) in Three.js gives the angle in the vertical direction.



          top = near * Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom


          Say you go with the default of 50°. Then that tan there will be tan(25°) except for JavaScript you actually need to compute that in radians. If you want the width to be 50° instead, you want fov = 2 * atan(tan(50°/2) * 9/16) except you need to convert between degrees and radians. The idea is that you take the tangens, apply the aspect ratio to map it from width (where you want to measure it) to height (where the class expects it), then reverse the tangens computation.



          But perhaps you don't want to specify the angle for the width. Perhaps you want the original scene at a vertical fov of 50°, but still want the adjusted cene to be the 16:9 clipped version of that. In this case you can multiply with the ratio of ratios. So if your original image was 4:3 and the new image is 16:9, multiply by (9/16)/(3/4) also known as (9*4)/(16*3) also known as 3/4 and you convert from original height to width to new height angle in one go.






          share|improve this answer













          Code in PerspectiveCamera.js suggests that the fov (field of view) in Three.js gives the angle in the vertical direction.



          top = near * Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom


          Say you go with the default of 50°. Then that tan there will be tan(25°) except for JavaScript you actually need to compute that in radians. If you want the width to be 50° instead, you want fov = 2 * atan(tan(50°/2) * 9/16) except you need to convert between degrees and radians. The idea is that you take the tangens, apply the aspect ratio to map it from width (where you want to measure it) to height (where the class expects it), then reverse the tangens computation.



          But perhaps you don't want to specify the angle for the width. Perhaps you want the original scene at a vertical fov of 50°, but still want the adjusted cene to be the 16:9 clipped version of that. In this case you can multiply with the ratio of ratios. So if your original image was 4:3 and the new image is 16:9, multiply by (9/16)/(3/4) also known as (9*4)/(16*3) also known as 3/4 and you convert from original height to width to new height angle in one go.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 20 '18 at 21:10









          MvGMvG

          39.3k994197




          39.3k994197













          • Hey, thanks, I ended up with slightly different solution that seems to work. In the first viewport I calculate something I call "zScale": blueFrameHeight / orangeFrameHeight. Then in the second viewport after positioning camera I set camera.scale.z = zScale and it just works :). zScale is basically ratio between blue and orange viewport heights. Can you confirm that this works same as you described? I don't know why I need only ratio between heights but it seems to just work for all my cases...

            – user606521
            Nov 21 '18 at 12:43











          • Hmm, my code does not work in some scenarios... So I want to try what you wrote (ratio of ratios). You said I have to multiply by 3/4. But what I need to multiply exactly?

            – user606521
            Nov 22 '18 at 9:28



















          • Hey, thanks, I ended up with slightly different solution that seems to work. In the first viewport I calculate something I call "zScale": blueFrameHeight / orangeFrameHeight. Then in the second viewport after positioning camera I set camera.scale.z = zScale and it just works :). zScale is basically ratio between blue and orange viewport heights. Can you confirm that this works same as you described? I don't know why I need only ratio between heights but it seems to just work for all my cases...

            – user606521
            Nov 21 '18 at 12:43











          • Hmm, my code does not work in some scenarios... So I want to try what you wrote (ratio of ratios). You said I have to multiply by 3/4. But what I need to multiply exactly?

            – user606521
            Nov 22 '18 at 9:28

















          Hey, thanks, I ended up with slightly different solution that seems to work. In the first viewport I calculate something I call "zScale": blueFrameHeight / orangeFrameHeight. Then in the second viewport after positioning camera I set camera.scale.z = zScale and it just works :). zScale is basically ratio between blue and orange viewport heights. Can you confirm that this works same as you described? I don't know why I need only ratio between heights but it seems to just work for all my cases...

          – user606521
          Nov 21 '18 at 12:43





          Hey, thanks, I ended up with slightly different solution that seems to work. In the first viewport I calculate something I call "zScale": blueFrameHeight / orangeFrameHeight. Then in the second viewport after positioning camera I set camera.scale.z = zScale and it just works :). zScale is basically ratio between blue and orange viewport heights. Can you confirm that this works same as you described? I don't know why I need only ratio between heights but it seems to just work for all my cases...

          – user606521
          Nov 21 '18 at 12:43













          Hmm, my code does not work in some scenarios... So I want to try what you wrote (ratio of ratios). You said I have to multiply by 3/4. But what I need to multiply exactly?

          – user606521
          Nov 22 '18 at 9:28





          Hmm, my code does not work in some scenarios... So I want to try what you wrote (ratio of ratios). You said I have to multiply by 3/4. But what I need to multiply exactly?

          – user606521
          Nov 22 '18 at 9:28


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53395092%2fhow-to-reproduce-given-viewport-maintaining-aspect-ratio%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          MongoDB - Not Authorized To Execute Command

          How to fix TextFormField cause rebuild widget in Flutter

          in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith