美文网首页
iOS ARKit应用

iOS ARKit应用

作者: 折戟沉沙YY | 来源:发表于2021-06-16 13:43 被阅读0次

    以前写了一款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]];

        }

    }

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

    相关文章

      网友评论

          本文标题:iOS ARKit应用

          本文链接:https://www.haomeiwen.com/subject/urpxyltx.html