com.google.ar.sceneform.math.Vector3 Java Examples

The following examples show how to use com.google.ar.sceneform.math.Vector3. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Stroke.java    From sceneform-samples with Apache License 2.0 6 votes vote down vote up
public void add(Vector3 pointInWorld) {
  Vector3 pointInLocal = anchorNode.worldToLocalPoint(pointInWorld);
  List<Vector3> points = lineSimplifier.getPoints();
  if (getNumOfPoints() < 1) {
    lineSimplifier.add(pointInLocal);
    return;
  }

  Vector3 prev = points.get(points.size() - 1);
  Vector3 diff = Vector3.subtract(prev, pointInLocal);
  if (diff.length() < MINIMUM_DISTANCE_BETWEEN_POINTS) {
    return;
  }

  lineSimplifier.add(pointInLocal);

  RenderableDefinition renderableDefinition =
      ExtrudedCylinder.makeExtrudedCylinder(CYLINDER_RADIUS, points, material);
  if (shape == null) {
    shape = ModelRenderable.builder().setSource(renderableDefinition).build().join();
    node.setRenderable(shape);
  } else {
    shape.updateFromDefinition(renderableDefinition);
  }
}
 
Example #2
Source File: ARVelocityActivity.java    From science-journal with Apache License 2.0 6 votes vote down vote up
private void calculateSpeed(Pose centerPose, float deltaSeconds) {
  Pose anchorPose =
      arFragment.getArSceneView().getSession().getAllAnchors().iterator().next().getPose();
  Vector3 currPos =
      new Vector3(
          centerPose.tx() - anchorPose.tx(),
          centerPose.ty() - anchorPose.ty(),
          centerPose.tz() - anchorPose.tz());
  delTime += deltaSeconds;

  if (lastPos != null) {
    float distance = Vector3.subtract(currPos, lastPos).length();
    totalDistance += distance;
  }
  lastPos = currPos;

  if (delTime >= INTERVAL_TIME_SECONDS) {
    // Calculate velocity in meters per second.
    float speedValue = totalDistance / delTime;
    velocitySensor.setNextVelocity(speedValue);
    // TODO(b/135678092): Add a string resource for the following
    velocityText.setText(String.format(Locale.getDefault(), "%.2f m/s", speedValue));
    delTime = 0;
    totalDistance = 0;
  }
}
 
Example #3
Source File: ARVelocityActivity.java    From science-journal with Apache License 2.0 6 votes vote down vote up
private void averageVelocityEveryFrame(Pose centerPose, float deltaSeconds) {
  Pose anchorPose =
      arFragment.getArSceneView().getSession().getAllAnchors().iterator().next().getPose();
  Vector3 currPos =
      new Vector3(
          centerPose.tx() - anchorPose.tx(),
          centerPose.ty() - anchorPose.ty(),
          centerPose.tz() - anchorPose.tz());
  positions.add(currPos);
  currIndex++;
  textUpdateTime += deltaSeconds;

  if (currIndex >= INTERVAL_FRAMES) {
    // Calculate velocity over the past second.
    Vector3 displacement = Vector3.subtract(currPos, positions.get(currIndex - INTERVAL_FRAMES));
    float velocityValue = displacement.length() / INTERVAL_TIME_SECONDS;
    velocitySensor.setNextVelocity(velocityValue);

    if (textUpdateTime >= TEXT_UPDATE_TIME_SECONDS) {
      // TODO(b/135678092): Add a string resource for the following
      velocityText.setText(String.format(Locale.getDefault(), "%.2f m/s", velocityValue));
      textUpdateTime = 0;
    }
  }
}
 
Example #4
Source File: ARVelocityActivity.java    From science-journal with Apache License 2.0 6 votes vote down vote up
private void calculateVelocityEveryFrame(Pose centerPose, float deltaSeconds) {
  Pose anchorPose =
      arFragment.getArSceneView().getSession().getAllAnchors().iterator().next().getPose();
  Vector3 currPos =
      new Vector3(
          centerPose.tx() - anchorPose.tx(),
          centerPose.ty() - anchorPose.ty(),
          centerPose.tz() - anchorPose.tz());
  textUpdateTime += deltaSeconds;

  if (lastPos != null) {
    // Calculate velocity in meters per second.
    Vector3 displacement = Vector3.subtract(currPos, lastPos);
    float velocityValue = displacement.length() / deltaSeconds;
    velocitySensor.setNextVelocity(velocityValue);

    if (textUpdateTime >= TEXT_UPDATE_TIME_SECONDS) {
      // TODO(b/135678092): Add a string resource for the following
      velocityText.setText(String.format(Locale.getDefault(), "%.2f m/s", velocityValue));
      textUpdateTime = 0;
    }
  }
  lastPos = currPos;
}
 
Example #5
Source File: ARVelocityActivity.java    From science-journal with Apache License 2.0 6 votes vote down vote up
private void calculateVelocity(Pose centerPose, float deltaSeconds) {
  Pose anchorPose = arFragment.getArSceneView().getSession().getAllAnchors().iterator().next()
      .getPose();
  Vector3 currPos =
      new Vector3(
          centerPose.tx() - anchorPose.tx(),
          centerPose.ty() - anchorPose.ty(),
          centerPose.tz() - anchorPose.tz());
  delTime += deltaSeconds;

  if (lastPos == null) {
    lastPos = currPos;
  } else if (delTime >= INTERVAL_TIME_SECONDS) {
    // Calculate velocity in meters per second.
    Vector3 displacement = Vector3.subtract(currPos, lastPos);
    float velocityValue = displacement.length() / delTime;
    velocitySensor.setNextVelocity(velocityValue);
    // TODO(b/135678092): Add a string resource for the following
    velocityText.setText(String.format(Locale.getDefault(), "%.2f m/s", velocityValue));
    delTime = 0;
    lastPos = currPos;
  }
}
 
Example #6
Source File: LocationNode.java    From ARCore-Location with MIT License 6 votes vote down vote up
private boolean isOverlapping(Node n, Ray ray, Vector3 target, Vector3 cameraPosition) {
    Vector3 nodeDirection = Vector3.subtract(target, cameraPosition);
    ray.setDirection(nodeDirection);

    ArrayList<HitTestResult> hitTestResults = locationScene.mArSceneView.getScene().hitTestAll(ray);
    if (hitTestResults.size() > 0) {

        HitTestResult closestHit = null;
        for (HitTestResult hit : hitTestResults) {
            //Get the closest hit on enabled Node
            if (hit.getNode() != null && hit.getNode().isEnabled()) {
                closestHit = hit;
                break;
            }
        }

        // if closest hit is not the current node, it is hidden behind another node that is closer
        return closestHit != null && closestHit.getNode() != n;
    }
    return false;
}
 
Example #7
Source File: LightingActivity.java    From sceneform-samples with Apache License 2.0 6 votes vote down vote up
private Node createMenuNode(Node node, Vector3 localPosition) {
  Node menu = new Node();
  menu.setParent(node);
  addMenuToNode(menu, localPosition);
  node.setOnTapListener(
      new OnTapListener() {
        @Override
        public void onTap(HitTestResult hitTestResult, MotionEvent motionEvent) {
          menu.setEnabled(!menu.isEnabled());
          if (openMenuNode != null) {
            openMenuNode.setEnabled(false);
            openMenuNode = (openMenuNode == menu) ? null : menu;
          } else {
            openMenuNode = menu;
          }
        }
      });
  return menu;
}
 
Example #8
Source File: LineSimplifier.java    From sceneform-samples with Apache License 2.0 6 votes vote down vote up
private ArrayList<Vector3> smoothPoints(List<Vector3> pointsToSmooth) {
  ArrayList<Vector3> results = new ArrayList<>();
  float maxDistance = 0.0f;
  int index = 0;
  float distance;
  int endIndex = pointsToSmooth.size() - 1;
  for (int i = 0; i < endIndex - 1; i++) {
    distance = getPerpendicularDistance(points.get(0), points.get(endIndex), points.get(i));
    if (distance > maxDistance) {
      index = i;
      maxDistance = distance;
    }
  }
  if (maxDistance > MAXIMUM_SMOOTHING_DISTANCE) {
    ArrayList<Vector3> result1 = smoothPoints(pointsToSmooth.subList(0, index));
    ArrayList<Vector3> result2 = smoothPoints(pointsToSmooth.subList(index + 1, endIndex));
    results.addAll(result1);
    results.addAll(result2);
  } else {
    results.addAll(pointsToSmooth);
  }
  return results;
}
 
Example #9
Source File: LightingActivity.java    From sceneform-samples with Apache License 2.0 6 votes vote down vote up
@SuppressWarnings("FutureReturnValueIgnored")
private void addMenuToNode(Node node, Vector3 localPosition) {
  ViewRenderable.builder()
      .setView(this, R.layout.material_options_view)
      .build()
      .thenAccept(
          viewRenderable -> {
            node.setRenderable(viewRenderable);
            node.setEnabled(false);
            node.setLocalPosition(localPosition);
            node.setWorldScale(new Vector3(.65f, .65f, .5f));
            setupMaterialMenu(viewRenderable, node);
          })
      .exceptionally(
          throwable -> {
            displayError(throwable);
            throw new CompletionException(throwable);
          });
}
 
Example #10
Source File: Stroke.java    From sceneform-samples with Apache License 2.0 5 votes vote down vote up
@Override
public String toString() {
  String result = "Vector3[] strokePoints = {";
  for (Vector3 vector3 : lineSimplifier.getPoints()) {
    result += ("new Vector3(" + vector3.x + "f, " + vector3.y + "f, " + vector3.z + "f),\n ");
  }
  return result.substring(0, result.length() - 3) + "};";
}
 
Example #11
Source File: MainActivity.java    From journaldev with MIT License 5 votes vote down vote up
private void initModel() {
    MaterialFactory.makeTransparentWithColor(this, new Color(android.graphics.Color.RED))
            .thenAccept(
                    material -> {
                        Vector3 vector3 = new Vector3(0.05f, 0.01f, 0.01f);
                        cubeRenderable = ShapeFactory.makeCube(vector3, Vector3.zero(), material);
                        cubeRenderable.setShadowCaster(false);
                        cubeRenderable.setShadowReceiver(false);
                    });
}
 
Example #12
Source File: LightingActivity.java    From sceneform-samples with Apache License 2.0 5 votes vote down vote up
private Node createShapeNode(
    AnchorNode anchorNode, ModelRenderable renderable, Vector3 localPosition) {
  Node shape = new Node();
  shape.setParent(anchorNode);
  shape.setRenderable(renderable);
  shape.setLocalPosition(localPosition);
  return shape;
}
 
Example #13
Source File: LightingActivity.java    From sceneform-samples with Apache License 2.0 5 votes vote down vote up
private void setUpLights() {
  Light.Builder lightBuilder =
      Light.builder(Type.POINT)
          .setFalloffRadius(LIGHT_FALLOFF_RADIUS)
          .setShadowCastingEnabled(false)
          .setIntensity(intensityBar.getProgress());

  for (int i = 0; i < 4; i++) {
    // Sets the color of and creates the light.
    lightBuilder.setColor(ColorConfig.getColor(pointlightColorConfig, i));
    Light light = lightBuilder.build();

    // Create node and set its light.
    Vector3 localPosition =
        new Vector3(-0.4f + (i * .2f), POINTLIGHT_CUBE_HEIGHT_OFFSET_METERS, 0.0f);

    RotatingNode orbit = new RotatingNode();
    orbit.setParent(anchorNode);

    Node lightNode = new Node();
    lightNode.setParent(orbit);
    lightNode.setLocalPosition(localPosition);
    lightNode.setLight(light);
    //  Check if lights are currently switched on or off, and update accordingly.
    lightNode.setEnabled(toggleLights.isChecked());

    pointlightNodes.add(lightNode);
  }

  isLightingInitialized = true;
}
 
Example #14
Source File: LineSimplifier.java    From sceneform-samples with Apache License 2.0 5 votes vote down vote up
private void smoothPoints() {
  List<Vector3> pointsToSmooth =
      points.subList(points.size() - POINT_SMOOTHING_INTERVAL - 1, points.size() - 1);
  ArrayList<Vector3> newlySmoothedPoints = smoothPoints(pointsToSmooth);
  points.subList(points.size() - POINT_SMOOTHING_INTERVAL - 1, points.size() - 1).clear();
  points.addAll(points.size() - 1, newlySmoothedPoints);
  smoothedPoints.addAll(newlySmoothedPoints);
}
 
Example #15
Source File: ExtrudedCylinder.java    From sceneform-samples with Apache License 2.0 5 votes vote down vote up
private static void updateEndPointUV(List<Vertex> vertices) {
  // Update UV coordinates of ending vertices
  for (int edgeIndex = 0; edgeIndex <= NUMBER_OF_SIDES; edgeIndex++) {
    int vertexIndex = vertices.size() - edgeIndex - 1;
    Vertex currentVertex = vertices.get(vertexIndex);
    currentVertex.setUvCoordinate(
        new UvCoordinate(
            currentVertex.getUvCoordinate().x,
            (Vector3.subtract(
                        vertices.get(vertexIndex).getPosition(),
                        vertices.get(vertexIndex - NUMBER_OF_SIDES - 1).getPosition())
                    .length()
                + vertices.get(vertexIndex - NUMBER_OF_SIDES - 1).getUvCoordinate().y)));
  }
}
 
Example #16
Source File: RotatingNode.java    From sceneform-samples with Apache License 2.0 4 votes vote down vote up
@Override
public void onUpdate(FrameTime frameTime) {
  float speed = (degreesPerSecond * frameTime.getDeltaSeconds());
  Quaternion deltaRot = Quaternion.axisAngle(Vector3.up(), speedMultiplier * speed);
  setLocalRotation(Quaternion.multiply(getLocalRotation(), deltaRot));
}
 
Example #17
Source File: LineSimplifier.java    From sceneform-samples with Apache License 2.0 4 votes vote down vote up
public List<Vector3> getPoints() {
  return points;
}
 
Example #18
Source File: LineSimplifier.java    From sceneform-samples with Apache License 2.0 4 votes vote down vote up
private float getPerpendicularDistance(Vector3 start, Vector3 end, Vector3 point) {
  Vector3 crossProduct =
      Vector3.cross(Vector3.subtract(point, start), Vector3.subtract(point, end));
  float result = crossProduct.length() / Vector3.subtract(end, start).length();
  return result;
}
 
Example #19
Source File: LocationNode.java    From ARCore-Location with MIT License 4 votes vote down vote up
@Override
public void onUpdate(FrameTime frameTime) {

    // Typically, getScene() will never return null because onUpdate() is only called when the node
    // is in the scene.
    // However, if onUpdate is called explicitly or if the node is removed from the scene on a
    // different thread during onUpdate, then getScene may be null.


    for (Node n : getChildren()) {
        if (getScene() == null) {
            return;
        }

        Vector3 cameraPosition = getScene().getCamera().getWorldPosition();
        Vector3 nodePosition = n.getWorldPosition();

        // Compute the difference vector between the camera and anchor
        float dx = cameraPosition.x - nodePosition.x;
        float dy = cameraPosition.y - nodePosition.y;
        float dz = cameraPosition.z - nodePosition.z;

        // Compute the straight-line distance.
        double distanceInAR = Math.sqrt(dx * dx + dy * dy + dz * dz);
        setDistanceInAR(distanceInAR);

        if (locationScene.shouldOffsetOverlapping()) {
            if (locationScene.mArSceneView.getScene().overlapTestAll(n).size() > 0) {
                setHeight(getHeight() + 1.2F);
            }
        }

        if (locationScene.shouldRemoveOverlapping()) {
            Ray ray = new Ray();
            ray.setOrigin(cameraPosition);

            float xDelta = (float) (distanceInAR * Math.sin(Math.PI / 15)); //12 degrees
            Vector3 cameraLeft = getScene().getCamera().getLeft().normalized();

            Vector3 left = Vector3.add(nodePosition, cameraLeft.scaled(xDelta));
            Vector3 center = nodePosition;
            Vector3 right = Vector3.add(nodePosition, cameraLeft.scaled(-xDelta));

            boolean isOverlapping = isOverlapping(n, ray, left, cameraPosition)
                    || isOverlapping(n, ray, center, cameraPosition)
                    || isOverlapping(n, ray, right, cameraPosition);

            if (isOverlapping) {
                setEnabled(false);
            } else {
                setEnabled(true);
            }
        }
    }

    if (!locationScene.minimalRefreshing())
        scaleAndRotate();


    if (renderEvent != null) {
        if (this.isTracking() && this.isActive() && this.isEnabled())
            renderEvent.render(this);
    }
}
 
Example #20
Source File: LineSimplifier.java    From sceneform-samples with Apache License 2.0 4 votes vote down vote up
public void add(Vector3 point) {
  points.add(point);
  if (points.size() - smoothedPoints.size() > POINT_SMOOTHING_INTERVAL) {
    smoothPoints();
  }
}
 
Example #21
Source File: LocationNode.java    From ARCore-Location with MIT License 4 votes vote down vote up
public void scaleAndRotate() {
    for (Node n : getChildren()) {
        int markerDistance = (int) Math.ceil(
                LocationUtils.distance(
                        locationMarker.latitude,
                        locationScene.deviceLocation.currentBestLocation.getLatitude(),
                        locationMarker.longitude,
                        locationScene.deviceLocation.currentBestLocation.getLongitude(),
                        0,
                        0)
        );
        setDistance(markerDistance);

        // Limit the distance of the Anchor within the scene.
        // Prevents uk.co.appoly.arcorelocation.rendering issues.
        int renderDistance = markerDistance;
        if (renderDistance > locationScene.getDistanceLimit())
            renderDistance = locationScene.getDistanceLimit();

        float scale = 1F;
        final Vector3 cameraPosition = getScene().getCamera().getWorldPosition();
        Vector3 direction = Vector3.subtract(cameraPosition, n.getWorldPosition());

        switch (scalingMode) {
            case FIXED_SIZE_ON_SCREEN:
                scale = (float) Math.sqrt(direction.x * direction.x
                        + direction.y * direction.y + direction.z * direction.z);
                break;
            case GRADUAL_TO_MAX_RENDER_DISTANCE:
                float scaleDifference = gradualScalingMaxScale - gradualScalingMinScale;
                scale = (gradualScalingMinScale + ((locationScene.getDistanceLimit() - markerDistance) * (scaleDifference / locationScene.getDistanceLimit()))) * renderDistance;
                break;
            case GRADUAL_FIXED_SIZE:
                scale = (float) Math.sqrt(direction.x * direction.x
                        + direction.y * direction.y + direction.z * direction.z);
                float gradualScale = gradualScalingMaxScale - gradualScalingMinScale;
                gradualScale = gradualScalingMaxScale - (gradualScale / renderDistance * markerDistance);
                scale *= Math.max(gradualScale, gradualScalingMinScale);
                break;
        }

        scale *= scaleModifier;

        //Log.d("LocationScene", "scale " + scale);
        n.setWorldPosition(new Vector3(n.getWorldPosition().x, getHeight(), n.getWorldPosition().z));
        Quaternion lookRotation = Quaternion.lookRotation(direction, Vector3.up());
        n.setWorldRotation(lookRotation);
        n.setWorldScale(new Vector3(scale, scale, scale));
    }
}
 
Example #22
Source File: ExtrudedCylinder.java    From sceneform-samples with Apache License 2.0 4 votes vote down vote up
private static void makeDisk(
    List<Vertex> vertices,
    List<Integer> triangleIndices,
    List<Vector3> points,
    int centerPointIndex,
    Direction direction) {

  Vector3 centerPoint = points.get(centerPointIndex);
  Vector3 nextPoint = points.get(centerPointIndex + (direction == Direction.UP ? 1 : -1));
  Vector3 normal = Vector3.subtract(centerPoint, nextPoint).normalized();
  Vertex center =
      Vertex.builder()
          .setPosition(centerPoint)
          .setNormal(normal)
          .setUvCoordinate(new UvCoordinate(.5f, .5f))
          .build();
  int centerIndex = vertices.size();
  vertices.add(center);

  int vertexPosition = centerPointIndex * (NUMBER_OF_SIDES + 1);
  for (int edge = 0; edge <= NUMBER_OF_SIDES; edge++) {
    Vertex edgeVertex = vertices.get(vertexPosition + edge);
    float theta = (float) (2 * Math.PI * edge / NUMBER_OF_SIDES);
    UvCoordinate uvCoordinate =
        new UvCoordinate((float) (Math.cos(theta) + 1f) / 2, (float) (Math.sin(theta) + 1f) / 2);
    Vertex topVertex =
        Vertex.builder()
            .setPosition(edgeVertex.getPosition())
            .setNormal(normal)
            .setUvCoordinate(uvCoordinate)
            .build();
    vertices.add(topVertex);

    if (edge != NUMBER_OF_SIDES) {
      // Add disk triangle, using direction to check which side the triangles should face
      if (direction == Direction.UP) {
        triangleIndices.add(centerIndex);
        triangleIndices.add(centerIndex + edge + 1);
        triangleIndices.add(centerIndex + edge + 2);
      } else {
        triangleIndices.add(centerIndex);
        triangleIndices.add(centerIndex + edge + 2);
        triangleIndices.add(centerIndex + edge + 1);
      }
    }
  }
}
 
Example #23
Source File: ExtrudedCylinder.java    From sceneform-samples with Apache License 2.0 4 votes vote down vote up
private static void updateConnectingPoints(
    List<Vertex> vertices, List<Vector3> points, List<Quaternion> rotations, float radius) {
  // Loop over each segment of cylinder, connecting the ends of this segment to start of the next.
  int currentSegmentVertexIndex = NUMBER_OF_SIDES + 1;
  int nextSegmentVertexIndex = currentSegmentVertexIndex + NUMBER_OF_SIDES + 1;

  for (int segmentIndex = 0; segmentIndex < points.size() - 2; segmentIndex++) {
    Vector3 influencePoint = points.get(segmentIndex + 1);

    Quaternion averagedRotation =
        lerp(rotations.get(segmentIndex), rotations.get(segmentIndex + 1), .5f);
    Vector3 rightDirection =
        Quaternion.rotateVector(averagedRotation, Vector3.right()).normalized();
    Vector3 upDirection = Quaternion.rotateVector(averagedRotation, Vector3.up()).normalized();

    for (int edgeIndex = 0; edgeIndex <= NUMBER_OF_SIDES; edgeIndex++) {
      // Connect bottom vertex of current edge to the top vertex of the edge on next segment.
      float theta = (float) (2 * Math.PI) * edgeIndex / NUMBER_OF_SIDES;
      float cosTheta = (float) Math.cos(theta);
      float sinTheta = (float) Math.sin(theta);

      // Create new position
      Vector3 position =
          Vector3.add(
              rightDirection.scaled(radius * cosTheta), upDirection.scaled(radius * sinTheta));
      Vector3 normal = position.normalized();
      position.set(Vector3.add(position, influencePoint));

      // Update position, UV, and normals of connecting vertices
      int previousSegmentVertexIndex = currentSegmentVertexIndex - NUMBER_OF_SIDES - 1;
      Vertex updatedVertex =
          Vertex.builder()
              .setPosition(position)
              .setNormal(normal)
              .setUvCoordinate(
                  new UvCoordinate(
                      vertices.get(currentSegmentVertexIndex).getUvCoordinate().x,
                      (Vector3.subtract(
                                  position,
                                  vertices.get(previousSegmentVertexIndex).getPosition())
                              .length()
                          + vertices.get(previousSegmentVertexIndex).getUvCoordinate().y)))
              .build();

      vertices.set(currentSegmentVertexIndex, updatedVertex);
      vertices.remove(nextSegmentVertexIndex);
      currentSegmentVertexIndex++;
    }
    currentSegmentVertexIndex = nextSegmentVertexIndex;
    nextSegmentVertexIndex += NUMBER_OF_SIDES + 1;
  }
}
 
Example #24
Source File: ExtrudedCylinder.java    From sceneform-samples with Apache License 2.0 4 votes vote down vote up
private static void generateVerticesFromPoints(
    Vector3 desiredUp,
    List<Vertex> vertices,
    List<Quaternion> rotations,
    Vector3 firstPoint,
    Vector3 secondPoint,
    float radius) {

  final Vector3 difference = Vector3.subtract(firstPoint, secondPoint);
  Vector3 directionFromTopToBottom = difference.normalized();
  Quaternion rotationFromAToB = Quaternion.lookRotation(directionFromTopToBottom, desiredUp);

  // cosTheta0 provides the angle between the rotations
  if (!rotations.isEmpty()) {
    double cosTheta0 = dot(rotations.get(rotations.size() - 1), rotationFromAToB);
    // Flip end rotation to get shortest path if needed
    if (cosTheta0 < 0.0) {
      rotationFromAToB = negated(rotationFromAToB);
    }
  }
  rotations.add(rotationFromAToB);

  directionFromTopToBottom =
      Quaternion.rotateVector(rotationFromAToB, Vector3.forward()).normalized();
  Vector3 rightDirection =
      Quaternion.rotateVector(rotationFromAToB, Vector3.right()).normalized();
  Vector3 upDirection = Quaternion.rotateVector(rotationFromAToB, Vector3.up()).normalized();
  desiredUp.set(upDirection);

  List<Vertex> bottomVertices = new ArrayList<>();

  final float halfHeight = difference.length() / 2;
  final Vector3 center = Vector3.add(firstPoint, secondPoint).scaled(.5f);

  final float thetaIncrement = (float) (2 * Math.PI) / NUMBER_OF_SIDES;
  float theta = 0;
  float cosTheta = (float) Math.cos(theta);
  float sinTheta = (float) Math.sin(theta);
  float uStep = (float) 1.0 / NUMBER_OF_SIDES;

  // Generate edge vertices along the sides of the cylinder.
  for (int edgeIndex = 0; edgeIndex <= NUMBER_OF_SIDES; edgeIndex++) {
    // Create top edge vertex
    Vector3 topPosition =
        Vector3.add(
            directionFromTopToBottom.scaled(-halfHeight),
            Vector3.add(
                rightDirection.scaled(radius * cosTheta), upDirection.scaled(radius * sinTheta)));
    Vector3 normal =
        Vector3.subtract(topPosition, directionFromTopToBottom.scaled(-halfHeight)).normalized();
    topPosition = Vector3.add(topPosition, center);
    UvCoordinate uvCoordinate = new UvCoordinate(uStep * edgeIndex, 0);

    Vertex vertex =
        Vertex.builder()
            .setPosition(topPosition)
            .setNormal(normal)
            .setUvCoordinate(uvCoordinate)
            .build();
    vertices.add(vertex);

    // Create bottom edge vertex
    Vector3 bottomPosition =
        Vector3.add(
            directionFromTopToBottom.scaled(halfHeight),
            Vector3.add(
                rightDirection.scaled(radius * cosTheta), upDirection.scaled(radius * sinTheta)));
    normal =
        Vector3.subtract(bottomPosition, directionFromTopToBottom.scaled(halfHeight))
            .normalized();
    bottomPosition = Vector3.add(bottomPosition, center);
    float vHeight = halfHeight * 2;
    uvCoordinate = new UvCoordinate(uStep * edgeIndex, vHeight);

    vertex =
        Vertex.builder()
            .setPosition(bottomPosition)
            .setNormal(normal)
            .setUvCoordinate(uvCoordinate)
            .build();
    bottomVertices.add(vertex);

    theta += thetaIncrement;
    cosTheta = (float) Math.cos(theta);
    sinTheta = (float) Math.sin(theta);
  }
  vertices.addAll(bottomVertices);
}
 
Example #25
Source File: ExtrudedCylinder.java    From sceneform-samples with Apache License 2.0 4 votes vote down vote up
/**
 * Creates a {@link ModelRenderable} in the shape of a cylinder with the give specifications.
 *
 * @param radius the radius of the constructed cylinder
 * @param points the list of points the extruded cylinder will be constructed around
 * @param material the material to use for rendering the cylinder
 * @return renderable representing a cylinder with the given parameters
 */
@SuppressWarnings("AndroidApiChecker")
// CompletableFuture requires api level 24
public static RenderableDefinition makeExtrudedCylinder(
    float radius, List<Vector3> points, Material material) {
  AndroidPreconditions.checkMinAndroidApiLevel();

  if (points.size() < 2) {
    return null;
  }

  ArrayList<Vertex> vertices = new ArrayList<>();
  ArrayList<Integer> triangleIndices = new ArrayList<>();
  ArrayList<Quaternion> rotations = new ArrayList<>();
  Vector3 desiredUp = Vector3.up();

  for (int point = 0; point < points.size() - 1; point++) {
    generateVerticesFromPoints(
        desiredUp, vertices, rotations, points.get(point + 1), points.get(point), radius);
  }

  updateConnectingPoints(vertices, points, rotations, radius);
  generateTriangleIndices(triangleIndices, points.size());
  updateEndPointUV(vertices);

  // Add start cap
  makeDisk(vertices, triangleIndices, points, 0, Direction.UP);
  // Add end cap
  makeDisk(vertices, triangleIndices, points, points.size() - 1, Direction.DOWN);

  Submesh submesh =
      Submesh.builder().setTriangleIndices(triangleIndices).setMaterial(material).build();

  RenderableDefinition renderableDefinition =
      RenderableDefinition.builder()
          .setVertices(vertices)
          .setSubmeshes(Arrays.asList(submesh))
          .build();

  return renderableDefinition;
}