How I can set repeated texture on an object in Android ArCore Sceneform API?












0















I have successfully made a line between two vectors in the AR Scene.



My code:



private void addLineBetweenPoints(Scene scene, Vector3 from, Vector3 to) {
// prepare an anchor position
Quaternion camQ = scene.getCamera().getWorldRotation();
float f1 = new float{to.x, to.y, to.z};
float f2 = new float{camQ.x, camQ.y, camQ.z, camQ.w};
Pose anchorPose = new Pose(f1, f2);

// make an ARCore Anchor
Anchor anchor = mCallback.getSession().createAnchor(anchorPose);
// Node that is automatically positioned in world space based on the ARCore Anchor.
AnchorNode anchorNode = new AnchorNode(anchor);
anchorNode.setParent(scene);

// Compute a line's length
float lineLength = Vector3.subtract(from, to).length();

// Prepare a sampler
Texture.Sampler sampler = Texture.Sampler.builder()
.setMinFilter(Texture.Sampler.MinFilter.LINEAR_MIPMAP_LINEAR)
.setMagFilter(Texture.Sampler.MagFilter.LINEAR)
.setWrapModeR(Texture.Sampler.WrapMode.REPEAT)
.setWrapModeS(Texture.Sampler.WrapMode.REPEAT)
.setWrapModeT(Texture.Sampler.WrapMode.REPEAT)
.build();

// 1. Make a texture
Texture.builder()
.setSource(() -> getContext().getAssets().open("textures/aim_line.png"))
.setSampler(sampler)
.build().thenAccept(texture -> {
// 2. make a material by the texture
MaterialFactory.makeTransparentWithTexture(getContext(), texture)
.thenAccept(material -> {
// 3. make a model by the material
ModelRenderable model = ShapeFactory.makeCylinder(0.0025f, lineLength,
new Vector3(0f, lineLength / 2, 0f), material);
model.setShadowReceiver(false);
model.setShadowCaster(false);

// make node
Node node = new Node();
node.setRenderable(model);
node.setParent(anchorNode);

// set rotation
final Vector3 difference = Vector3.subtract(to, from);
final Vector3 directionFromTopToBottom = difference.normalized();
final Quaternion rotationFromAToB =
Quaternion.lookRotation(directionFromTopToBottom, Vector3.up());
node.setWorldRotation(Quaternion.multiply(rotationFromAToB,
Quaternion.axisAngle(new Vector3(1.0f, 0.0f, 0.0f), 90)));
});
});
}


It works perfectly, but I have a mistake texture.
In the file "textures/aim_line.png" contains PNG:
(the line's half is transparent the other half is orange.)



aim_line.png



My current result:



current result



But I expected next result:



expected result



So, I have use the Sampler where was wrote "WrapMode.REPEAT" but the texture does not repeat, only stretched.



How I can set repeated texture on an object in Android ArCore Sceneform API?










share|improve this question



























    0















    I have successfully made a line between two vectors in the AR Scene.



    My code:



    private void addLineBetweenPoints(Scene scene, Vector3 from, Vector3 to) {
    // prepare an anchor position
    Quaternion camQ = scene.getCamera().getWorldRotation();
    float f1 = new float{to.x, to.y, to.z};
    float f2 = new float{camQ.x, camQ.y, camQ.z, camQ.w};
    Pose anchorPose = new Pose(f1, f2);

    // make an ARCore Anchor
    Anchor anchor = mCallback.getSession().createAnchor(anchorPose);
    // Node that is automatically positioned in world space based on the ARCore Anchor.
    AnchorNode anchorNode = new AnchorNode(anchor);
    anchorNode.setParent(scene);

    // Compute a line's length
    float lineLength = Vector3.subtract(from, to).length();

    // Prepare a sampler
    Texture.Sampler sampler = Texture.Sampler.builder()
    .setMinFilter(Texture.Sampler.MinFilter.LINEAR_MIPMAP_LINEAR)
    .setMagFilter(Texture.Sampler.MagFilter.LINEAR)
    .setWrapModeR(Texture.Sampler.WrapMode.REPEAT)
    .setWrapModeS(Texture.Sampler.WrapMode.REPEAT)
    .setWrapModeT(Texture.Sampler.WrapMode.REPEAT)
    .build();

    // 1. Make a texture
    Texture.builder()
    .setSource(() -> getContext().getAssets().open("textures/aim_line.png"))
    .setSampler(sampler)
    .build().thenAccept(texture -> {
    // 2. make a material by the texture
    MaterialFactory.makeTransparentWithTexture(getContext(), texture)
    .thenAccept(material -> {
    // 3. make a model by the material
    ModelRenderable model = ShapeFactory.makeCylinder(0.0025f, lineLength,
    new Vector3(0f, lineLength / 2, 0f), material);
    model.setShadowReceiver(false);
    model.setShadowCaster(false);

    // make node
    Node node = new Node();
    node.setRenderable(model);
    node.setParent(anchorNode);

    // set rotation
    final Vector3 difference = Vector3.subtract(to, from);
    final Vector3 directionFromTopToBottom = difference.normalized();
    final Quaternion rotationFromAToB =
    Quaternion.lookRotation(directionFromTopToBottom, Vector3.up());
    node.setWorldRotation(Quaternion.multiply(rotationFromAToB,
    Quaternion.axisAngle(new Vector3(1.0f, 0.0f, 0.0f), 90)));
    });
    });
    }


    It works perfectly, but I have a mistake texture.
    In the file "textures/aim_line.png" contains PNG:
    (the line's half is transparent the other half is orange.)



    aim_line.png



    My current result:



    current result



    But I expected next result:



    expected result



    So, I have use the Sampler where was wrote "WrapMode.REPEAT" but the texture does not repeat, only stretched.



    How I can set repeated texture on an object in Android ArCore Sceneform API?










    share|improve this question

























      0












      0








      0








      I have successfully made a line between two vectors in the AR Scene.



      My code:



      private void addLineBetweenPoints(Scene scene, Vector3 from, Vector3 to) {
      // prepare an anchor position
      Quaternion camQ = scene.getCamera().getWorldRotation();
      float f1 = new float{to.x, to.y, to.z};
      float f2 = new float{camQ.x, camQ.y, camQ.z, camQ.w};
      Pose anchorPose = new Pose(f1, f2);

      // make an ARCore Anchor
      Anchor anchor = mCallback.getSession().createAnchor(anchorPose);
      // Node that is automatically positioned in world space based on the ARCore Anchor.
      AnchorNode anchorNode = new AnchorNode(anchor);
      anchorNode.setParent(scene);

      // Compute a line's length
      float lineLength = Vector3.subtract(from, to).length();

      // Prepare a sampler
      Texture.Sampler sampler = Texture.Sampler.builder()
      .setMinFilter(Texture.Sampler.MinFilter.LINEAR_MIPMAP_LINEAR)
      .setMagFilter(Texture.Sampler.MagFilter.LINEAR)
      .setWrapModeR(Texture.Sampler.WrapMode.REPEAT)
      .setWrapModeS(Texture.Sampler.WrapMode.REPEAT)
      .setWrapModeT(Texture.Sampler.WrapMode.REPEAT)
      .build();

      // 1. Make a texture
      Texture.builder()
      .setSource(() -> getContext().getAssets().open("textures/aim_line.png"))
      .setSampler(sampler)
      .build().thenAccept(texture -> {
      // 2. make a material by the texture
      MaterialFactory.makeTransparentWithTexture(getContext(), texture)
      .thenAccept(material -> {
      // 3. make a model by the material
      ModelRenderable model = ShapeFactory.makeCylinder(0.0025f, lineLength,
      new Vector3(0f, lineLength / 2, 0f), material);
      model.setShadowReceiver(false);
      model.setShadowCaster(false);

      // make node
      Node node = new Node();
      node.setRenderable(model);
      node.setParent(anchorNode);

      // set rotation
      final Vector3 difference = Vector3.subtract(to, from);
      final Vector3 directionFromTopToBottom = difference.normalized();
      final Quaternion rotationFromAToB =
      Quaternion.lookRotation(directionFromTopToBottom, Vector3.up());
      node.setWorldRotation(Quaternion.multiply(rotationFromAToB,
      Quaternion.axisAngle(new Vector3(1.0f, 0.0f, 0.0f), 90)));
      });
      });
      }


      It works perfectly, but I have a mistake texture.
      In the file "textures/aim_line.png" contains PNG:
      (the line's half is transparent the other half is orange.)



      aim_line.png



      My current result:



      current result



      But I expected next result:



      expected result



      So, I have use the Sampler where was wrote "WrapMode.REPEAT" but the texture does not repeat, only stretched.



      How I can set repeated texture on an object in Android ArCore Sceneform API?










      share|improve this question














      I have successfully made a line between two vectors in the AR Scene.



      My code:



      private void addLineBetweenPoints(Scene scene, Vector3 from, Vector3 to) {
      // prepare an anchor position
      Quaternion camQ = scene.getCamera().getWorldRotation();
      float f1 = new float{to.x, to.y, to.z};
      float f2 = new float{camQ.x, camQ.y, camQ.z, camQ.w};
      Pose anchorPose = new Pose(f1, f2);

      // make an ARCore Anchor
      Anchor anchor = mCallback.getSession().createAnchor(anchorPose);
      // Node that is automatically positioned in world space based on the ARCore Anchor.
      AnchorNode anchorNode = new AnchorNode(anchor);
      anchorNode.setParent(scene);

      // Compute a line's length
      float lineLength = Vector3.subtract(from, to).length();

      // Prepare a sampler
      Texture.Sampler sampler = Texture.Sampler.builder()
      .setMinFilter(Texture.Sampler.MinFilter.LINEAR_MIPMAP_LINEAR)
      .setMagFilter(Texture.Sampler.MagFilter.LINEAR)
      .setWrapModeR(Texture.Sampler.WrapMode.REPEAT)
      .setWrapModeS(Texture.Sampler.WrapMode.REPEAT)
      .setWrapModeT(Texture.Sampler.WrapMode.REPEAT)
      .build();

      // 1. Make a texture
      Texture.builder()
      .setSource(() -> getContext().getAssets().open("textures/aim_line.png"))
      .setSampler(sampler)
      .build().thenAccept(texture -> {
      // 2. make a material by the texture
      MaterialFactory.makeTransparentWithTexture(getContext(), texture)
      .thenAccept(material -> {
      // 3. make a model by the material
      ModelRenderable model = ShapeFactory.makeCylinder(0.0025f, lineLength,
      new Vector3(0f, lineLength / 2, 0f), material);
      model.setShadowReceiver(false);
      model.setShadowCaster(false);

      // make node
      Node node = new Node();
      node.setRenderable(model);
      node.setParent(anchorNode);

      // set rotation
      final Vector3 difference = Vector3.subtract(to, from);
      final Vector3 directionFromTopToBottom = difference.normalized();
      final Quaternion rotationFromAToB =
      Quaternion.lookRotation(directionFromTopToBottom, Vector3.up());
      node.setWorldRotation(Quaternion.multiply(rotationFromAToB,
      Quaternion.axisAngle(new Vector3(1.0f, 0.0f, 0.0f), 90)));
      });
      });
      }


      It works perfectly, but I have a mistake texture.
      In the file "textures/aim_line.png" contains PNG:
      (the line's half is transparent the other half is orange.)



      aim_line.png



      My current result:



      current result



      But I expected next result:



      expected result



      So, I have use the Sampler where was wrote "WrapMode.REPEAT" but the texture does not repeat, only stretched.



      How I can set repeated texture on an object in Android ArCore Sceneform API?







      android arcore sceneform






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 22 '18 at 19:32









      Andrew GrowAndrew Grow

      20638




      20638
























          1 Answer
          1






          active

          oldest

          votes


















          2














          Looking at the cylinder model, it has a UV map of 0 to 1. This is used to map the texture onto the mesh. 0,0 is the bottom left of the texture and 1,1 is the top right. The wrapping configuration on the sampler is only used when the UV coordinates on the model are > 1.0. In that case it clamps or repeats based on the setting. Since the cylinder is already constrained to 0,1, the texture is always stretched.



          Your alternatives to fix this are either to model your own cylinder and set the UV coordinates as you need, or to use a custom material to manipulate the UV coordinates before sampling.



          You can use Blender or Maya or another 3D modeling tool make the model.



          The custom material is specific to Sceneform, so here's the steps:




          1. Create a dummy model to use when loading the custom material

          2. Write the custom material that repeats the texture

          3. Load the dummy model at runtime and get the material

          4. Set the parameters on the custom material.


          Create a dummy model



          I used a plane OBJ model I had around. It does not matter what the model is, we just need it to load the material. Create a file in app/sampledata/materials named dummy.obj



          o Plane
          v 0.500000 0.500000 0.000000
          v -0.500000 0.500000 0.000000
          v 0.500000 -0.500000 0.000000
          v -0.500000 -0.500000 0.000000
          vt 0.000000 1.000000
          vt 0.000000 0.000000
          vt 1.000000 0.000000
          vt 1.000000 1.000000
          vn 0.0000 0.0000 1.0000
          usemtl None
          s off
          f 1/1/1 2/2/1 4/3/1 3/4/1


          Write the custom material



          The custom material reference describes each of the elements in the repeating_texture.mat:



          // Sample material for repeating a texture.
          //
          // the repeating factor is given as repeat_x,
          // repeat_y as a factor multipled by the UV
          // coordinate.
          material {
          "name" : "RepeatingTexture",
          parameters : [
          {
          type : sampler2d,
          name : texture
          },

          {
          type: float,
          name:"repeat_x"
          },
          {
          type: float,
          name: "repeat_y"
          }
          ],
          requires : [
          "position",
          "uv0"
          ],

          }
          fragment {
          void material(inout MaterialInputs material) {
          prepareMaterial(material);

          vec2 uv = getUV0();
          uv.x = uv.x * materialParams.repeat_x;
          uv.y = uv.y * materialParams.repeat_y;

          material.baseColor = texture(materialParams_texture, uv).rgba;
          }
          }


          Add the model and material to the build



          This adds the step to compile the model and material into a .sfb file.
          In app/build.gradle add:



          apply plugin: 'com.google.ar.sceneform.plugin'

          sceneform.asset('sampledata/materials/dummy.obj',
          "sampledata/materials/repeating_texture.mat",
          'sampledata/materials/dummy.sfa',
          'src/main/res/raw/material_holder')


          You will also need to add Sceneform to the buildscript class path in the top level build.gradle:



              dependencies {
          classpath 'com.android.tools.build:gradle:3.2.1'
          classpath 'com.google.ar.sceneform:plugin:1.5.1'
          // NOTE: Do not place your application dependencies here; they belong
          // in the individual module build.gradle files
          }
          }


          Load the material at runtime



          In onCreate() call:



          ModelRenderable.builder().setSource(this, R.raw.material_holder)
          .build().thenAccept(
          modelRenderable -> repeatingMaterial = modelRenderable.getMaterial());



          This stores the material in the member field repeatingMaterial.



          Set the parameters on the material



          Modifying your original code to be:



            private void addLineBetweenPoints(AnchorNode from, Vector3 to) {
          // Compute a line's length
          float lineLength = Vector3.subtract(from.getWorldPosition(), to).length();
          // repeat the pattern every 10cm
          float lengthCM = lineLength * 100;

          repeatingMaterial.setFloat("repeat_x", lengthCM/10);
          repeatingMaterial.setFloat("repeat_y", lengthCM/10);
          // 3. make a model by the material
          ModelRenderable model = ShapeFactory.makeCylinder(0.0025f, lineLength,
          new Vector3(0f, lineLength / 2, 0f), repeatingMaterial);
          model.setShadowReceiver(false);
          model.setShadowCaster(false);
          // make node
          Node node = new Node();
          node.setRenderable(model);
          node.setParent(from);
          // set rotation
          final Vector3 difference = Vector3.subtract(from.getWorldPosition(), to);
          final Vector3 directionFromTopToBottom = difference.normalized();
          final Quaternion rotationFromAToB =
          Quaternion.lookRotation(directionFromTopToBottom, Vector3.up());
          node.setWorldRotation(Quaternion.multiply(rotationFromAToB,
          Quaternion.axisAngle(new Vector3(1.0f, 0.0f, 0.0f), 90)));
          }





          share|improve this answer


























          • Thanks a lot, it is an amazing answer! Thank you for the solution, sir. Your help is very important for me.

            – Andrew Grow
            Nov 28 '18 at 7:29











          • How can we change texture in runtime, for example, in each frame to simulate the endless moving(like progress)?

            – Максим Петлюк
            Mar 1 at 18: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%2f53437128%2fhow-i-can-set-repeated-texture-on-an-object-in-android-arcore-sceneform-api%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









          2














          Looking at the cylinder model, it has a UV map of 0 to 1. This is used to map the texture onto the mesh. 0,0 is the bottom left of the texture and 1,1 is the top right. The wrapping configuration on the sampler is only used when the UV coordinates on the model are > 1.0. In that case it clamps or repeats based on the setting. Since the cylinder is already constrained to 0,1, the texture is always stretched.



          Your alternatives to fix this are either to model your own cylinder and set the UV coordinates as you need, or to use a custom material to manipulate the UV coordinates before sampling.



          You can use Blender or Maya or another 3D modeling tool make the model.



          The custom material is specific to Sceneform, so here's the steps:




          1. Create a dummy model to use when loading the custom material

          2. Write the custom material that repeats the texture

          3. Load the dummy model at runtime and get the material

          4. Set the parameters on the custom material.


          Create a dummy model



          I used a plane OBJ model I had around. It does not matter what the model is, we just need it to load the material. Create a file in app/sampledata/materials named dummy.obj



          o Plane
          v 0.500000 0.500000 0.000000
          v -0.500000 0.500000 0.000000
          v 0.500000 -0.500000 0.000000
          v -0.500000 -0.500000 0.000000
          vt 0.000000 1.000000
          vt 0.000000 0.000000
          vt 1.000000 0.000000
          vt 1.000000 1.000000
          vn 0.0000 0.0000 1.0000
          usemtl None
          s off
          f 1/1/1 2/2/1 4/3/1 3/4/1


          Write the custom material



          The custom material reference describes each of the elements in the repeating_texture.mat:



          // Sample material for repeating a texture.
          //
          // the repeating factor is given as repeat_x,
          // repeat_y as a factor multipled by the UV
          // coordinate.
          material {
          "name" : "RepeatingTexture",
          parameters : [
          {
          type : sampler2d,
          name : texture
          },

          {
          type: float,
          name:"repeat_x"
          },
          {
          type: float,
          name: "repeat_y"
          }
          ],
          requires : [
          "position",
          "uv0"
          ],

          }
          fragment {
          void material(inout MaterialInputs material) {
          prepareMaterial(material);

          vec2 uv = getUV0();
          uv.x = uv.x * materialParams.repeat_x;
          uv.y = uv.y * materialParams.repeat_y;

          material.baseColor = texture(materialParams_texture, uv).rgba;
          }
          }


          Add the model and material to the build



          This adds the step to compile the model and material into a .sfb file.
          In app/build.gradle add:



          apply plugin: 'com.google.ar.sceneform.plugin'

          sceneform.asset('sampledata/materials/dummy.obj',
          "sampledata/materials/repeating_texture.mat",
          'sampledata/materials/dummy.sfa',
          'src/main/res/raw/material_holder')


          You will also need to add Sceneform to the buildscript class path in the top level build.gradle:



              dependencies {
          classpath 'com.android.tools.build:gradle:3.2.1'
          classpath 'com.google.ar.sceneform:plugin:1.5.1'
          // NOTE: Do not place your application dependencies here; they belong
          // in the individual module build.gradle files
          }
          }


          Load the material at runtime



          In onCreate() call:



          ModelRenderable.builder().setSource(this, R.raw.material_holder)
          .build().thenAccept(
          modelRenderable -> repeatingMaterial = modelRenderable.getMaterial());



          This stores the material in the member field repeatingMaterial.



          Set the parameters on the material



          Modifying your original code to be:



            private void addLineBetweenPoints(AnchorNode from, Vector3 to) {
          // Compute a line's length
          float lineLength = Vector3.subtract(from.getWorldPosition(), to).length();
          // repeat the pattern every 10cm
          float lengthCM = lineLength * 100;

          repeatingMaterial.setFloat("repeat_x", lengthCM/10);
          repeatingMaterial.setFloat("repeat_y", lengthCM/10);
          // 3. make a model by the material
          ModelRenderable model = ShapeFactory.makeCylinder(0.0025f, lineLength,
          new Vector3(0f, lineLength / 2, 0f), repeatingMaterial);
          model.setShadowReceiver(false);
          model.setShadowCaster(false);
          // make node
          Node node = new Node();
          node.setRenderable(model);
          node.setParent(from);
          // set rotation
          final Vector3 difference = Vector3.subtract(from.getWorldPosition(), to);
          final Vector3 directionFromTopToBottom = difference.normalized();
          final Quaternion rotationFromAToB =
          Quaternion.lookRotation(directionFromTopToBottom, Vector3.up());
          node.setWorldRotation(Quaternion.multiply(rotationFromAToB,
          Quaternion.axisAngle(new Vector3(1.0f, 0.0f, 0.0f), 90)));
          }





          share|improve this answer


























          • Thanks a lot, it is an amazing answer! Thank you for the solution, sir. Your help is very important for me.

            – Andrew Grow
            Nov 28 '18 at 7:29











          • How can we change texture in runtime, for example, in each frame to simulate the endless moving(like progress)?

            – Максим Петлюк
            Mar 1 at 18:28
















          2














          Looking at the cylinder model, it has a UV map of 0 to 1. This is used to map the texture onto the mesh. 0,0 is the bottom left of the texture and 1,1 is the top right. The wrapping configuration on the sampler is only used when the UV coordinates on the model are > 1.0. In that case it clamps or repeats based on the setting. Since the cylinder is already constrained to 0,1, the texture is always stretched.



          Your alternatives to fix this are either to model your own cylinder and set the UV coordinates as you need, or to use a custom material to manipulate the UV coordinates before sampling.



          You can use Blender or Maya or another 3D modeling tool make the model.



          The custom material is specific to Sceneform, so here's the steps:




          1. Create a dummy model to use when loading the custom material

          2. Write the custom material that repeats the texture

          3. Load the dummy model at runtime and get the material

          4. Set the parameters on the custom material.


          Create a dummy model



          I used a plane OBJ model I had around. It does not matter what the model is, we just need it to load the material. Create a file in app/sampledata/materials named dummy.obj



          o Plane
          v 0.500000 0.500000 0.000000
          v -0.500000 0.500000 0.000000
          v 0.500000 -0.500000 0.000000
          v -0.500000 -0.500000 0.000000
          vt 0.000000 1.000000
          vt 0.000000 0.000000
          vt 1.000000 0.000000
          vt 1.000000 1.000000
          vn 0.0000 0.0000 1.0000
          usemtl None
          s off
          f 1/1/1 2/2/1 4/3/1 3/4/1


          Write the custom material



          The custom material reference describes each of the elements in the repeating_texture.mat:



          // Sample material for repeating a texture.
          //
          // the repeating factor is given as repeat_x,
          // repeat_y as a factor multipled by the UV
          // coordinate.
          material {
          "name" : "RepeatingTexture",
          parameters : [
          {
          type : sampler2d,
          name : texture
          },

          {
          type: float,
          name:"repeat_x"
          },
          {
          type: float,
          name: "repeat_y"
          }
          ],
          requires : [
          "position",
          "uv0"
          ],

          }
          fragment {
          void material(inout MaterialInputs material) {
          prepareMaterial(material);

          vec2 uv = getUV0();
          uv.x = uv.x * materialParams.repeat_x;
          uv.y = uv.y * materialParams.repeat_y;

          material.baseColor = texture(materialParams_texture, uv).rgba;
          }
          }


          Add the model and material to the build



          This adds the step to compile the model and material into a .sfb file.
          In app/build.gradle add:



          apply plugin: 'com.google.ar.sceneform.plugin'

          sceneform.asset('sampledata/materials/dummy.obj',
          "sampledata/materials/repeating_texture.mat",
          'sampledata/materials/dummy.sfa',
          'src/main/res/raw/material_holder')


          You will also need to add Sceneform to the buildscript class path in the top level build.gradle:



              dependencies {
          classpath 'com.android.tools.build:gradle:3.2.1'
          classpath 'com.google.ar.sceneform:plugin:1.5.1'
          // NOTE: Do not place your application dependencies here; they belong
          // in the individual module build.gradle files
          }
          }


          Load the material at runtime



          In onCreate() call:



          ModelRenderable.builder().setSource(this, R.raw.material_holder)
          .build().thenAccept(
          modelRenderable -> repeatingMaterial = modelRenderable.getMaterial());



          This stores the material in the member field repeatingMaterial.



          Set the parameters on the material



          Modifying your original code to be:



            private void addLineBetweenPoints(AnchorNode from, Vector3 to) {
          // Compute a line's length
          float lineLength = Vector3.subtract(from.getWorldPosition(), to).length();
          // repeat the pattern every 10cm
          float lengthCM = lineLength * 100;

          repeatingMaterial.setFloat("repeat_x", lengthCM/10);
          repeatingMaterial.setFloat("repeat_y", lengthCM/10);
          // 3. make a model by the material
          ModelRenderable model = ShapeFactory.makeCylinder(0.0025f, lineLength,
          new Vector3(0f, lineLength / 2, 0f), repeatingMaterial);
          model.setShadowReceiver(false);
          model.setShadowCaster(false);
          // make node
          Node node = new Node();
          node.setRenderable(model);
          node.setParent(from);
          // set rotation
          final Vector3 difference = Vector3.subtract(from.getWorldPosition(), to);
          final Vector3 directionFromTopToBottom = difference.normalized();
          final Quaternion rotationFromAToB =
          Quaternion.lookRotation(directionFromTopToBottom, Vector3.up());
          node.setWorldRotation(Quaternion.multiply(rotationFromAToB,
          Quaternion.axisAngle(new Vector3(1.0f, 0.0f, 0.0f), 90)));
          }





          share|improve this answer


























          • Thanks a lot, it is an amazing answer! Thank you for the solution, sir. Your help is very important for me.

            – Andrew Grow
            Nov 28 '18 at 7:29











          • How can we change texture in runtime, for example, in each frame to simulate the endless moving(like progress)?

            – Максим Петлюк
            Mar 1 at 18:28














          2












          2








          2







          Looking at the cylinder model, it has a UV map of 0 to 1. This is used to map the texture onto the mesh. 0,0 is the bottom left of the texture and 1,1 is the top right. The wrapping configuration on the sampler is only used when the UV coordinates on the model are > 1.0. In that case it clamps or repeats based on the setting. Since the cylinder is already constrained to 0,1, the texture is always stretched.



          Your alternatives to fix this are either to model your own cylinder and set the UV coordinates as you need, or to use a custom material to manipulate the UV coordinates before sampling.



          You can use Blender or Maya or another 3D modeling tool make the model.



          The custom material is specific to Sceneform, so here's the steps:




          1. Create a dummy model to use when loading the custom material

          2. Write the custom material that repeats the texture

          3. Load the dummy model at runtime and get the material

          4. Set the parameters on the custom material.


          Create a dummy model



          I used a plane OBJ model I had around. It does not matter what the model is, we just need it to load the material. Create a file in app/sampledata/materials named dummy.obj



          o Plane
          v 0.500000 0.500000 0.000000
          v -0.500000 0.500000 0.000000
          v 0.500000 -0.500000 0.000000
          v -0.500000 -0.500000 0.000000
          vt 0.000000 1.000000
          vt 0.000000 0.000000
          vt 1.000000 0.000000
          vt 1.000000 1.000000
          vn 0.0000 0.0000 1.0000
          usemtl None
          s off
          f 1/1/1 2/2/1 4/3/1 3/4/1


          Write the custom material



          The custom material reference describes each of the elements in the repeating_texture.mat:



          // Sample material for repeating a texture.
          //
          // the repeating factor is given as repeat_x,
          // repeat_y as a factor multipled by the UV
          // coordinate.
          material {
          "name" : "RepeatingTexture",
          parameters : [
          {
          type : sampler2d,
          name : texture
          },

          {
          type: float,
          name:"repeat_x"
          },
          {
          type: float,
          name: "repeat_y"
          }
          ],
          requires : [
          "position",
          "uv0"
          ],

          }
          fragment {
          void material(inout MaterialInputs material) {
          prepareMaterial(material);

          vec2 uv = getUV0();
          uv.x = uv.x * materialParams.repeat_x;
          uv.y = uv.y * materialParams.repeat_y;

          material.baseColor = texture(materialParams_texture, uv).rgba;
          }
          }


          Add the model and material to the build



          This adds the step to compile the model and material into a .sfb file.
          In app/build.gradle add:



          apply plugin: 'com.google.ar.sceneform.plugin'

          sceneform.asset('sampledata/materials/dummy.obj',
          "sampledata/materials/repeating_texture.mat",
          'sampledata/materials/dummy.sfa',
          'src/main/res/raw/material_holder')


          You will also need to add Sceneform to the buildscript class path in the top level build.gradle:



              dependencies {
          classpath 'com.android.tools.build:gradle:3.2.1'
          classpath 'com.google.ar.sceneform:plugin:1.5.1'
          // NOTE: Do not place your application dependencies here; they belong
          // in the individual module build.gradle files
          }
          }


          Load the material at runtime



          In onCreate() call:



          ModelRenderable.builder().setSource(this, R.raw.material_holder)
          .build().thenAccept(
          modelRenderable -> repeatingMaterial = modelRenderable.getMaterial());



          This stores the material in the member field repeatingMaterial.



          Set the parameters on the material



          Modifying your original code to be:



            private void addLineBetweenPoints(AnchorNode from, Vector3 to) {
          // Compute a line's length
          float lineLength = Vector3.subtract(from.getWorldPosition(), to).length();
          // repeat the pattern every 10cm
          float lengthCM = lineLength * 100;

          repeatingMaterial.setFloat("repeat_x", lengthCM/10);
          repeatingMaterial.setFloat("repeat_y", lengthCM/10);
          // 3. make a model by the material
          ModelRenderable model = ShapeFactory.makeCylinder(0.0025f, lineLength,
          new Vector3(0f, lineLength / 2, 0f), repeatingMaterial);
          model.setShadowReceiver(false);
          model.setShadowCaster(false);
          // make node
          Node node = new Node();
          node.setRenderable(model);
          node.setParent(from);
          // set rotation
          final Vector3 difference = Vector3.subtract(from.getWorldPosition(), to);
          final Vector3 directionFromTopToBottom = difference.normalized();
          final Quaternion rotationFromAToB =
          Quaternion.lookRotation(directionFromTopToBottom, Vector3.up());
          node.setWorldRotation(Quaternion.multiply(rotationFromAToB,
          Quaternion.axisAngle(new Vector3(1.0f, 0.0f, 0.0f), 90)));
          }





          share|improve this answer















          Looking at the cylinder model, it has a UV map of 0 to 1. This is used to map the texture onto the mesh. 0,0 is the bottom left of the texture and 1,1 is the top right. The wrapping configuration on the sampler is only used when the UV coordinates on the model are > 1.0. In that case it clamps or repeats based on the setting. Since the cylinder is already constrained to 0,1, the texture is always stretched.



          Your alternatives to fix this are either to model your own cylinder and set the UV coordinates as you need, or to use a custom material to manipulate the UV coordinates before sampling.



          You can use Blender or Maya or another 3D modeling tool make the model.



          The custom material is specific to Sceneform, so here's the steps:




          1. Create a dummy model to use when loading the custom material

          2. Write the custom material that repeats the texture

          3. Load the dummy model at runtime and get the material

          4. Set the parameters on the custom material.


          Create a dummy model



          I used a plane OBJ model I had around. It does not matter what the model is, we just need it to load the material. Create a file in app/sampledata/materials named dummy.obj



          o Plane
          v 0.500000 0.500000 0.000000
          v -0.500000 0.500000 0.000000
          v 0.500000 -0.500000 0.000000
          v -0.500000 -0.500000 0.000000
          vt 0.000000 1.000000
          vt 0.000000 0.000000
          vt 1.000000 0.000000
          vt 1.000000 1.000000
          vn 0.0000 0.0000 1.0000
          usemtl None
          s off
          f 1/1/1 2/2/1 4/3/1 3/4/1


          Write the custom material



          The custom material reference describes each of the elements in the repeating_texture.mat:



          // Sample material for repeating a texture.
          //
          // the repeating factor is given as repeat_x,
          // repeat_y as a factor multipled by the UV
          // coordinate.
          material {
          "name" : "RepeatingTexture",
          parameters : [
          {
          type : sampler2d,
          name : texture
          },

          {
          type: float,
          name:"repeat_x"
          },
          {
          type: float,
          name: "repeat_y"
          }
          ],
          requires : [
          "position",
          "uv0"
          ],

          }
          fragment {
          void material(inout MaterialInputs material) {
          prepareMaterial(material);

          vec2 uv = getUV0();
          uv.x = uv.x * materialParams.repeat_x;
          uv.y = uv.y * materialParams.repeat_y;

          material.baseColor = texture(materialParams_texture, uv).rgba;
          }
          }


          Add the model and material to the build



          This adds the step to compile the model and material into a .sfb file.
          In app/build.gradle add:



          apply plugin: 'com.google.ar.sceneform.plugin'

          sceneform.asset('sampledata/materials/dummy.obj',
          "sampledata/materials/repeating_texture.mat",
          'sampledata/materials/dummy.sfa',
          'src/main/res/raw/material_holder')


          You will also need to add Sceneform to the buildscript class path in the top level build.gradle:



              dependencies {
          classpath 'com.android.tools.build:gradle:3.2.1'
          classpath 'com.google.ar.sceneform:plugin:1.5.1'
          // NOTE: Do not place your application dependencies here; they belong
          // in the individual module build.gradle files
          }
          }


          Load the material at runtime



          In onCreate() call:



          ModelRenderable.builder().setSource(this, R.raw.material_holder)
          .build().thenAccept(
          modelRenderable -> repeatingMaterial = modelRenderable.getMaterial());



          This stores the material in the member field repeatingMaterial.



          Set the parameters on the material



          Modifying your original code to be:



            private void addLineBetweenPoints(AnchorNode from, Vector3 to) {
          // Compute a line's length
          float lineLength = Vector3.subtract(from.getWorldPosition(), to).length();
          // repeat the pattern every 10cm
          float lengthCM = lineLength * 100;

          repeatingMaterial.setFloat("repeat_x", lengthCM/10);
          repeatingMaterial.setFloat("repeat_y", lengthCM/10);
          // 3. make a model by the material
          ModelRenderable model = ShapeFactory.makeCylinder(0.0025f, lineLength,
          new Vector3(0f, lineLength / 2, 0f), repeatingMaterial);
          model.setShadowReceiver(false);
          model.setShadowCaster(false);
          // make node
          Node node = new Node();
          node.setRenderable(model);
          node.setParent(from);
          // set rotation
          final Vector3 difference = Vector3.subtract(from.getWorldPosition(), to);
          final Vector3 directionFromTopToBottom = difference.normalized();
          final Quaternion rotationFromAToB =
          Quaternion.lookRotation(directionFromTopToBottom, Vector3.up());
          node.setWorldRotation(Quaternion.multiply(rotationFromAToB,
          Quaternion.axisAngle(new Vector3(1.0f, 0.0f, 0.0f), 90)));
          }






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 27 '18 at 22:54

























          answered Nov 26 '18 at 18:16









          Clayton WilkinsonClayton Wilkinson

          3,4941921




          3,4941921













          • Thanks a lot, it is an amazing answer! Thank you for the solution, sir. Your help is very important for me.

            – Andrew Grow
            Nov 28 '18 at 7:29











          • How can we change texture in runtime, for example, in each frame to simulate the endless moving(like progress)?

            – Максим Петлюк
            Mar 1 at 18:28



















          • Thanks a lot, it is an amazing answer! Thank you for the solution, sir. Your help is very important for me.

            – Andrew Grow
            Nov 28 '18 at 7:29











          • How can we change texture in runtime, for example, in each frame to simulate the endless moving(like progress)?

            – Максим Петлюк
            Mar 1 at 18:28

















          Thanks a lot, it is an amazing answer! Thank you for the solution, sir. Your help is very important for me.

          – Andrew Grow
          Nov 28 '18 at 7:29





          Thanks a lot, it is an amazing answer! Thank you for the solution, sir. Your help is very important for me.

          – Andrew Grow
          Nov 28 '18 at 7:29













          How can we change texture in runtime, for example, in each frame to simulate the endless moving(like progress)?

          – Максим Петлюк
          Mar 1 at 18:28





          How can we change texture in runtime, for example, in each frame to simulate the endless moving(like progress)?

          – Максим Петлюк
          Mar 1 at 18: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%2f53437128%2fhow-i-can-set-repeated-texture-on-an-object-in-android-arcore-sceneform-api%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

          "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

          Alcedinidae

          RAC Tourist Trophy