2017-10-18 14 views
2

Si vous utilisez iOS Metal et que vous avez des modèles d'objets programmatiques personnalisés, et (comme moi) vos modèles ont cessé de fonctionner avec l'arrivée de Metal2 et iOS 11, alors vous avez probablement démarré regarder comment générer par programme un MDLMesh. La documentation d'Apple indique: «En règle générale, vous obtenez des maillages en parcourant la hiérarchie d'objets d'un objet MDLAsset, mais vous pouvez également créer des maillages à partir de vos propres données de sommet ou créer des maillages paramétriques. Malheureusement, il n'offre aucune instruction ou code d'exemple.Génération par programmation d'objets MDLMesh utilisant initWithVertexBuffers

Vous trouvez rapidement les deux appels d'initialisation MDLMesh, initWithVertexBuffer et initWithVertexBuffers. Tout aussi rapidement, vous ne trouverez aucun exemple de code ou de discussion sur le web ... au moins je n'ai pas réussi à en trouver.

Comme il n'est pas intuitivement évident pour cet observateur occasionnel comment cela doit être fait, des échantillons de code sont demandés ici.

+0

Il n'y a rien de mal à répondre à votre propre question - c'est assez commun ici. Vous devriez aller de l'avant avec cela (et assurez-vous de le marquer comme accepté). – user5226582

Répondre

3

Il y a beaucoup d'exemples créant un MDLMesh en utilisant l'une des méthodes paramétriques d'usine pour exemple, un cube:

[MDLMesh newBoxWithDimensions:... 

L'utilisation la plus simple de ceux-ci, pour un « plan » (un rectangle), je généré rect 1x1 avec le nombre minimum de sommets:

MDLMesh *mdlMesh = [MDLMesh newPlaneWithDimensions:(vector_float2){1.0, 1.0} 
              segments:(vector_uint2){1, 1} 
             geometryType:MDLGeometryTypeTriangles 
             allocator:metalAllocator]; 

J'ai ensuite utilisé le débogueur de Xcode pour enquêter sur ce que le résultat MDLMesh ressemblait, comme un moyen de guider ma création d'un objet encore plus simple, un triangle équilatéral programmatique .

Le code suivant fonctionne pour moi. Je suis sûr que les gens avec plus de connaissances en métal que moi peuvent offrir de meilleures solutions. Mais cela, nous l'espérons vous aider à démarrer, dans un semblant de la bonne direction ...

donc jusqu'à ce qu'il y est une nouvelle méthode paramétrique d'usine pour

[MDLMesh newEquilateralTriangleWithEdgeLength:... 

le code suivant semble faire l'affaire ...

static const float equilateralTriangleVertexData[] = 
{ 
     0.000000, 0.577350, 0.0, 
    -0.500000, -0.288675, 0.0, 
     0.500000, -0.288675, 0.0, 
}; 

static const vector_float3 equilateralTriangleVertexNormalsData[] = 
{ 
    { 0.0, 0.0, 1.0 }, 
    { 0.0, 0.0, 1.0 }, 
    { 0.0, 0.0, 1.0 }, 
}; 

static const vector_float2 equilateralTriangleVertexTexData[] = 
{ 
    { 0.50, 1.00 }, 
    { 0.00, 0.00 }, 
    { 1.00, 0.00 }, 
}; 

int numVertices = 3; 

int lenBufferForVertices_position   = sizeof(equilateralTriangleVertexData); 
int lenBufferForVertices_normal   = numVertices * sizeof(vector_float3); 
int lenBufferForVertices_textureCoordinate = numVertices * sizeof(vector_float2); 

MTKMeshBuffer *mtkMeshBufferForVertices_position   = (MTKMeshBuffer *)[metalAllocator newBuffer:lenBufferForVertices_position   type:MDLMeshBufferTypeVertex]; 
MTKMeshBuffer *mtkMeshBufferForVertices_normal   = (MTKMeshBuffer *)[metalAllocator newBuffer:lenBufferForVertices_normal   type:MDLMeshBufferTypeVertex]; 
MTKMeshBuffer *mtkMeshBufferForVertices_textureCoordinate = (MTKMeshBuffer *)[metalAllocator newBuffer:lenBufferForVertices_textureCoordinate type:MDLMeshBufferTypeVertex]; 

// Now fill the Vertex buffers with vertices. 

NSData *nsData_position   = [NSData dataWithBytes:equilateralTriangleVertexData  length:lenBufferForVertices_position]; 
NSData *nsData_normal   = [NSData dataWithBytes:equilateralTriangleVertexNormalsData length:lenBufferForVertices_normal]; 
NSData *nsData_textureCoordinate = [NSData dataWithBytes:equilateralTriangleVertexTexData  length:lenBufferForVertices_textureCoordinate]; 

[mtkMeshBufferForVertices_position   fillData:nsData_position   offset:0]; 
[mtkMeshBufferForVertices_normal   fillData:nsData_normal   offset:0]; 
[mtkMeshBufferForVertices_textureCoordinate fillData:nsData_textureCoordinate offset:0]; 

NSArray <id<MDLMeshBuffer>> *arrayOfMeshBuffers = [NSArray arrayWithObjects:mtkMeshBufferForVertices_position, mtkMeshBufferForVertices_normal, mtkMeshBufferForVertices_textureCoordinate, nil]; 

static uint16_t indices[] = 
{ 
    0, 1, 2, 
}; 

int numIndices = 3; 

int lenBufferForIndices = numIndices * sizeof(uint16_t); 
MTKMeshBuffer *mtkMeshBufferForIndices = (MTKMeshBuffer *)[metalAllocator newBuffer:lenBufferForIndices type:MDLMeshBufferTypeIndex]; 

NSData *nsData_indices = [NSData dataWithBytes:indices length:lenBufferForIndices]; 
[mtkMeshBufferForIndices fillData:nsData_indices offset:0]; 

MDLScatteringFunction *scatteringFunction = [MDLPhysicallyPlausibleScatteringFunction new]; 
MDLMaterial *material = [[MDLMaterial alloc] initWithName:@"plausibleMaterial" scatteringFunction:scatteringFunction]; 

// Not allowed to create an MTKSubmesh directly, so feed an MDLSubmesh to an MDLMesh, and then use that to load an MTKMesh, which makes the MTKSubmesh from it. 
MDLSubmesh *submesh = [[MDLSubmesh alloc] initWithName:@"summess" // Hackspeke for @"submesh" 
              indexBuffer:mtkMeshBufferForIndices 
              indexCount:numIndices 
              indexType:MDLIndexBitDepthUInt16 
              geometryType:MDLGeometryTypeTriangles 
               material:material]; 

NSArray <MDLSubmesh *> *arrayOfSubmeshes = [NSArray arrayWithObjects:submesh, nil]; 

MDLMesh *mdlMesh = [[MDLMesh alloc] initWithVertexBuffers:arrayOfMeshBuffers 
               vertexCount:numVertices 
               descriptor:mdlVertexDescriptor 
               submeshes:arrayOfSubmeshes]; 
+0

La définition de equilateralTriangleVertexData a été modifiée, car le triangle ne sortait pas correctement lorsqu'il s'agissait d'un tableau de vector_float3. Dunno pourquoi, mais en faisant un tableau de travaux flottants. Les autres données semblent être correctes comme elles l'étaient. –