Repeating a texture over a plane in SceneKit

I have a 32x32.png image that I want to repeat through SCNPlane. The code I have (see below) stretches the image so that it matches the size of the plane, rather than repeating itself.

CODE:

let planeGeo = SCNPlane(width: 15, height: 15) let imageMaterial = SCNMaterial() imageMaterial.diffuse.contents = UIImage(named: "art.scnassets/grid.png") planeGeo.firstMaterial = imageMaterial let plane = SCNNode(geometry: planeGeo) plane.geometry?.firstMaterial?.diffuse.wrapS = SCNWrapMode.repeat plane.geometry?.firstMaterial?.diffuse.wrapT = SCNWrapMode.repeat 
+8
source share
4 answers

I fixed it. It looks like the image has been enlarged. If I execute imageMaterial.diffuse.contentsTransform = SCNMatrix4MakeScale(32, 32, 0) , the image repeats.

+9
source

I encountered an identical problem when implementing aircraft visualization in ARKit. I wanted to visualize the detected plane as a checkerboard. I fixed this by creating my own SCNNode called "PlaneNode" with properly configured SCNMaterial . The material uses wrapS, wrapT = .repeat and correctly calculates the scale based on the size of the plane itself.

Looks like that:

enter image description here

Take a look at the code below; inline comments provide explanations.

 class PlaneNode : SCNNode { init(planeAnchor: ARPlaneAnchor) { super.init() // Create the 3D plane geometry with the dimensions reported // by ARKit in the ARPlaneAnchor instance let planeGeometry = SCNPlane(width:CGFloat(planeAnchor.extent.x), height:CGFloat(planeAnchor.extent.z)) // Instead of just visualizing the grid as a gray plane, we will render // it in some Tron style colours. let material = SCNMaterial() material.diffuse.contents = PaintCode.imageOfViewARPlane //the scale gives the number of times the image is repeated //ARKit givest the width and height in meters, in this case we want to repeat //the pattern each 2cm = 0.02m so we divide the width/height to find the number of patterns //we then round this so that we always have a clean repeat and not a truncated one let scaleX = (Float(planeGeometry.width) / 0.02).rounded() let scaleY = (Float(planeGeometry.height) / 0.02).rounded() //we then apply the scaling material.diffuse.contentsTransform = SCNMatrix4MakeScale(scaleX, scaleY, 0) //set repeat mode in both direction otherwise the patern is stretched! material.diffuse.wrapS = .repeat material.diffuse.wrapT = .repeat //apply material planeGeometry.materials = [material]; //make a node for it self.geometry = planeGeometry // Move the plane to the position reported by ARKit position.x = planeAnchor.center.x position.y = 0 position.z = planeAnchor.center.z // Planes in SceneKit are vertical by default so we need to rotate // 90 degrees to match planes in ARKit transform = SCNMatrix4MakeRotation(-Float.pi / 2.0, 1.0, 0.0, 0.0); } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func update(planeAnchor: ARPlaneAnchor) { guard let planeGeometry = geometry as? SCNPlane else { fatalError("update(planeAnchor: ARPlaneAnchor) called on node that has no SCNPlane geometry") } //update the size planeGeometry.width = CGFloat(planeAnchor.extent.x) planeGeometry.height = CGFloat(planeAnchor.extent.z) //and material properties let scaleX = (Float(planeGeometry.width) / 0.02).rounded() let scaleY = (Float(planeGeometry.height) / 0.02).rounded() planeGeometry.firstMaterial?.diffuse.contentsTransform = SCNMatrix4MakeScale(scaleX, scaleY, 0) // Move the plane to the position reported by ARKit position.x = planeAnchor.center.x position.y = 0 position.z = planeAnchor.center.z } } 
+6
source

You can find out from the Scene Kit Viewer. Suppose you have an SCNplane in your scene set.

Create scene file drag plane

What size is 12 inches in meter, it is 0.3048

and select the image in diffuse

enter image description here

Now you have an image with 4 Grid, as shown in the figure.

enter image description here

we want each box to be displayed in every inch, so for 12 inches we need a 12 * 12 box, since we have a 12 inch box

calculate it. First we need to convert 0.3048 meters to inches

that meters / 0.0254 answer 12.

but we need each grid to be displayed in every inch, so we also need to split 12/4 = 3

Now go to the material inspector and change the scale value to 3

You can see 12 boxes for a 12-inch airplane.

Hope this is helpful

0
source

To do this, in the SceneKit editor, select the plane in the scene, and then select the “Material Inspector” tab in the upper right corner. Then in the “Properties” section and where “Diffuse” is written, select a texture. Now, expand the diffuse section by clicking on the carat to the left of "Diffuse" and go down to where it says "Scale." Here you can zoom in to make the texture appear repeating rather than stretched. For this question, the OP would have to set the scale to 32x32.

enter image description here

0
source

Source: https://habr.com/ru/post/1269512/


All Articles