iOS ARKit应用

2021-06-16  本文已影响0人  折戟沉沙YY

以前写了一款AR的项目,包括添加,删除,移动旋转一些小功能。不说那些网上很容易搜到的关于API的解释了。

1.创建ARSCNView

-(ARSCNView *)arSCNView{

    if(!_arSCNView) {

        _arSCNView= [[ARSCNViewalloc]initWithFrame:self.view.bounds];

        _arSCNView.delegate=self;

        _arSCNView.session = self.arSession;

        _arSCNView.debugOptions = ARSCNDebugOptionShowFeaturePoints;

        _arSCNView.antialiasingMode = SCNAntialiasingModeMultisampling4X;

        SCNPlane*documentPlane = [SCNPlaneplaneWithWidth:30height:30];

        documentPlane.firstMaterial.diffuse.contents= [UIColorclearColor];

        self.documentNode= [SCNNodenodeWithGeometry:documentPlane];

        self.documentNode.hidden=YES;

        [_arSCNView.scene.rootNode addChildNode:self.documentNode];

        // setup camera

        SCNLookAtConstraint *constraint = [SCNLookAtConstraint lookAtConstraintWithTarget:self.documentNode];

        constraint.gimbalLockEnabled=YES;

        _arSCNView.scene.rootNode.constraints=@[constraint];

    }

    return _arSCNView;

}

- (ARSession *)arSession{

    if(!_arSession) {

        _arSession= [[ARSessionalloc]init];

        _arSession.delegate=self;

    }

    return _arSession;

}

-(ARConfiguration *)arConfiguration{

    if (!_arConfiguration) {

        /*  ARWorldTrackingConfiguration

         * 提供高品质的AR体验,使用后置摄像头精确跟踪设备的位置和方向,并允许进行检测

         */

        ARWorldTrackingConfiguration *arWTConfiguration = [[ARWorldTrackingConfiguration alloc] init];

        arWTConfiguration.planeDetection = ARPlaneDetectionHorizontal;

        arWTConfiguration.lightEstimationEnabled=true;

        _arConfiguration= arWTConfiguration;

    }

    return _arConfiguration;

}

2。添加模型 (目前使用obj模型)

模型的比例调节(    node.transform  =SCNMatrix4MakeScale(0.001,0.001,0.001);)根据自己模型实际大小做调节到合适的大小。此处模型并非为了这个项目,所以比例差距很大。

根据SCNVector3Make 算出模型的位置,这个网上算法解释很多

path:写了一个简单的存储

此处思想: 模型下载完成之前,先给一个模型大小相同的黑框,算是对用户体验的优化,等模型下载完成,在黑框的地方显示出模型,模型出现的角度在制作模型的时候可以跟3D组商量好角度,以便于展示出来之后减少用户操作。材质则直接用SDWebimage存储

-(void)nodeWithMDLObjectWithMaterial:(ARHitTestResult *)hitResult contentFrom:(ShopModel *)sModel{

    SCNBox *cube = [SCNBox boxWithWidth:[sModel.size[0] floatValue] height:[sModel.size[2] floatValue] length:[sModel.size[1] floatValue] chamferRadius:0];

    SCNNode*node = [SCNProductnodeWithGeometry:cube];

    for(SCNMaterial* matincube.materials) {

        mat.diffuse.contents=UIColorFromRGB(0x434C5D);

    }

    node.transform  =SCNMatrix4MakeScale(0.001,0.001,0.001);

    node.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:nil];

    node.physicsBody.mass = 2.0;

    node.physicsBody.damping=0.0;

    node.physicsBody.categoryBitMask = CollisionCategoryCube;

    node.categoryBitMask=MastTypeCube;

    ARFrame* frame =self.arSCNView.session.currentFrame;

    SCNMatrix4mat =SCNMatrix4FromMat4(frame.camera.transform);

    SCNVector3dir =SCNVector3Make(-1* mat.m31, -1* mat.m32, -1* mat.m33);

    node.position = SCNVector3Make(

                                   mat.m41+dir.x,

                                   hitResult.worldTransform.columns[3].y+0.4,  // + insertionYOffset,

                                   mat.m43+-1* mat.m33

                                   );

    node.opacity=0.8;

    [self.gestureControl nodeAddObjectFrom:(SCNProduct*)node andTag:1 andIsHide:NO];

    [self.arSCNView.scene.rootNodeaddChildNode:node];

    [self.nodeArraddObject:node];

//    self.activityIndicator.hidden=NO;

//    [self.activityIndicator startAnimating];

    NSString* strUrl = sModel.texture;

    SDWebImageManager *manager = [SDWebImageManager sharedManager];

    NSString* key = [managercacheKeyForURL:[NSURLURLWithString:strUrl]];

    SDImageCache* cache = [SDImageCache sharedImageCache];

    NSString* path  = [dataPathDic stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.obj",sModel.furID]];

     dispatch_async(dispatch_get_main_queue(), ^{

        if([selfisHaveObj:path] && [cacheimageFromDiskCacheForKey:key]) {

            [self nodeMaterilWithImage:[cache imageFromDiskCacheForKey:key]  andHit:hitResult andPath:path andCube:node];

        }else{

            if(![selfisHaveObj:path]){

                [UtilityFuncDownloadFilesTo:sModel.objandPath:pathfinished:^(NSError*error,NSDictionary*resultDict) {

                    if(!error && resultDict) {

                        // Set the correct content with the Sprite

                        [[SDWebImageDownloadersharedDownloader]downloadImageWithURL:[NSURLURLWithString:sModel.texture]options:SDWebImageDownloaderHighPriorityprogress:nilcompleted:^(UIImage*image,NSData*data,NSError*error,BOOLfinished) {

                            [selfnodeMaterilWithImage:image  andHit:hitResultandPath:pathandCube:node];

                        }];

                    }else{

                        [self.activityIndicatorstartAnimating];

                        self.activityIndicator.hidden=YES;

                    }

                }];

            }else{

                [[SDWebImageDownloadersharedDownloader]downloadImageWithURL:[NSURLURLWithString:sModel.texture]options:SDWebImageDownloaderHighPriorityprogress:nilcompleted:^(UIImage*image,NSData*data,NSError*error,BOOLfinished) {

                    [selfnodeMaterilWithImage:image  andHit:hitResultandPath:pathandCube:node];

                }];

            }

        }

    });

}

-(void)nodeMaterilWithImage:(UIImage*)image  andHit:(ARHitTestResult*)hitResultandPath:(NSString*)pathandCube:(SCNNode*)Knode{

    NSURL*url = [NSURLfileURLWithPath:path];

    MDLAsset*asset = [[MDLAssetalloc]initWithURL:url];

    SCNNode * node = [SCNProduct nodeWithMDLObject:[asset objectAtIndex:0]];

    for(SCNMaterial* materialinnode.geometry.materials) {

        material.diffuse.contents= image;

    }

    node.transform  =SCNMatrix4MakeScale(0.001,0.001,0.001);

    node.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:nil];

    node.physicsBody.mass = 2.0;

    node.physicsBody.damping=0.0;

    node.physicsBody.categoryBitMask = CollisionCategoryCube;

    node.categoryBitMask=MastTypeCube;

    node.position= Knode.position;

    [self.nodeArrremoveObject:Knode];

    [KnoderemoveFromParentNode];

    [self.gestureControl.timer invalidate];

    self.gestureControl.timer=nil;

    [self.arSCNView.scene.rootNodeaddChildNode:node];

    [self.nodeArraddObject:node];

    [self.gestureControl nodeAddObjectFrom:(SCNProduct*)node andTag:2 andIsHide:YES];

}

-(void)deleteFile {

    NSFileManager *fileManager = [NSFileManager defaultManager];

    NSString *folder=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

    NSArray*fileList ;

    fileList =[fileManagercontentsOfDirectoryAtPath:foldererror:NULL];

    for(NSString*fileinfileList) {

        NSLog(@"file=%@",file);

        NSString*path =[folderstringByAppendingPathComponent:file];

        NSLog(@"得到的路径=%@",path);

        [fileManagerremoveItemAtPath:patherror:nil];

    }

}

-(BOOL)isHaveObj:(NSString*)testPath {

    NSFileManager *fileManager = [NSFileManager defaultManager];

    BOOLresult = [fileManagerfileExistsAtPath:testPath];

    returnresult;

}

3。材质的属性设置

+ (SCNMaterial*)materialWithImageName:(NSString*)iamgeName {

    SCNMaterial*mat =materials[@"mat"];

    if(mat) {

        returnmat;

    }

    mat = [SCNMaterialnew];

    mat.lightingModelName = SCNLightingModelPhysicallyBased;

    UIImage* img =[UIImageimageNamed:@"keji"];

    mat.diffuse.contents= img;

    //  mat.diffuse.contents = [UIImage imageNamed:@"1"];

    mat.diffuse.wrapS = SCNWrapModeRepeat;

    mat.diffuse.wrapT = SCNWrapModeRepeat;

    mat.roughness.wrapS = SCNWrapModeRepeat;

    mat.roughness.wrapT = SCNWrapModeRepeat;

    mat.metalness.wrapS = SCNWrapModeRepeat;

    mat.metalness.wrapT = SCNWrapModeRepeat;

    mat.normal.wrapS = SCNWrapModeRepeat;

    mat.normal.wrapT = SCNWrapModeRepeat;

    materials[@"mat"] = mat;

    returnmat;

}

4,模型旋转和移动(大家可以网上搜一下 DHVector2D)

- (void)translate:(SCNVector3)deltaandDis:(CGFloat)disand:(SCNVector3)vecCurrentand:(SCNVector3)vecLast{

    MovementModemode =Translate;

    if (self.activeComponent) {

        mode =self.activeComponent.movementMode;

    }

    if(mode ==Translate) {

        self.selectedProduct.position = SCNVector3Make(self.selectedProduct.position.x + delta.x, self.selectedProduct.worldPosition.y, self.selectedProduct.position.z + delta.z);

        for(GizmoComponent* componentin_gizmoComponents) {

            component.position=SCNVector3Make(self.selectedProduct.position.x, component.position.y,self.selectedProduct.position.z);

        }

    }else{

        floatangle=0;

        for(GizmoComponent* componentin_gizmoComponents) {

            _vector1= [[DHVector2Dalloc]initWithCoordinateExpression:CGPointMake(vecCurrent.x-self.activeComponent.worldPosition.x, vecCurrent.z-self.activeComponent.worldPosition.z)];

            _vector2= [[DHVector2Dalloc]initWithCoordinateExpression:CGPointMake(vecLast.x-self.activeComponent.worldPosition.x, vecLast.z-self.activeComponent.worldPosition.z)];

            angle = [_vector1 antiClockwiseAngleToVector:_vector2];

            NSLog(@"===========angle:%f=============",angle);

            [componentrunAction:[SCNAction rotateByAngle:-angle aroundAxis:SCNVector3Make(0, 1, 0) duration:0]];

        }

        [self.selectedProduct runAction:[SCNAction rotateByAngle:-angle aroundAxis:SCNVector3Make(0, 1, 0) duration:0]];

    }

}

附:第一次写,潦草之处见谅

上一篇下一篇

猜你喜欢

热点阅读