RuntimeMeshBuilder.cpp
Go to the documentation of this file.
1 // Copyright 2016-2018 Chris Conway (Koderz). All Rights Reserved.
2 
3 #include "RuntimeMeshBuilder.h"
5 #include "RuntimeMeshData.h"
6 
7 
8 template<typename TYPE>
9 FORCEINLINE static TYPE& GetStreamAccess(TArray<uint8>* Data, int32 Index, int32 Stride, int32 Offset)
10 {
11  int32 StartPosition = (Index * Stride + Offset);
12  return *((TYPE*)&(*Data)[StartPosition]);
13 }
14 
15 FORCEINLINE static uint8* GetStreamAccessPointer(TArray<uint8>* Data, int32 Index, int32 Stride, int32 Offset)
16 {
17  int32 StartPosition = (Index * Stride + Offset);
18  return &(*Data)[StartPosition];
19 }
20 
21 template<typename TYPE>
23 {
24  TStaticArray<TYPE, 8> UVs;
25 };
26 
27 static_assert(sizeof(FRuntimeMeshEightUV<FVector2D>) == (8 * sizeof(FVector2D)), "Incorrect size for 8 UV struct");
28 static_assert(sizeof(FRuntimeMeshEightUV<FVector2DHalf>) == (8 * sizeof(FVector2DHalf)), "Incorrect size for 8 UV struct");
29 
30 
32 // FRuntimeMeshVerticesAccessor
33 
34 FRuntimeMeshVerticesAccessor::FRuntimeMeshVerticesAccessor(TArray<uint8>* PositionStreamData, TArray<uint8>* TangentStreamData, TArray<uint8>* UVStreamData, TArray<uint8>* ColorStreamData, bool bInIsReadonly)
35  : bIsInitialized(false)
36  , bIsReadonly(bInIsReadonly)
37  , PositionStream(PositionStreamData)
38  , TangentStream(TangentStreamData), bTangentHighPrecision(false), TangentSize(0), TangentStride(0)
39  , UVStream(UVStreamData), bUVHighPrecision(false), UVChannelCount(0), UVSize(0), UVStride(0)
40  , ColorStream(ColorStreamData)
41 {
42 }
43 
44 FRuntimeMeshVerticesAccessor::FRuntimeMeshVerticesAccessor(bool bInTangentsHighPrecision, bool bInUVsHighPrecision, int32 bInUVCount,
45  TArray<uint8>* PositionStreamData, TArray<uint8>* TangentStreamData, TArray<uint8>* UVStreamData, TArray<uint8>* ColorStreamData, bool bInIsReadonly)
46  : bIsInitialized(false)
47  , bIsReadonly(bInIsReadonly)
48  , PositionStream(PositionStreamData)
49  , TangentStream(TangentStreamData), bTangentHighPrecision(false), TangentSize(0), TangentStride(0)
50  , UVStream(UVStreamData), bUVHighPrecision(false), UVChannelCount(0), UVSize(0), UVStride(0)
51  , ColorStream(ColorStreamData)
52 {
53  Initialize(bInTangentsHighPrecision, bInUVsHighPrecision, bInUVCount);
54 }
55 
57 {
58 }
59 
60 void FRuntimeMeshVerticesAccessor::Initialize(bool bInTangentsHighPrecision, bool bInUVsHighPrecision, int32 bInUVCount)
61 {
62  bIsInitialized = true;
63  const_cast<bool&>(bTangentHighPrecision) = bInTangentsHighPrecision;
64  const_cast<int32&>(TangentSize) = (bTangentHighPrecision ? sizeof(FPackedRGBA16N) : sizeof(FPackedNormal));
65  const_cast<int32&>(TangentStride) = TangentSize * 2;
66 
67  const_cast<bool&>(bUVHighPrecision) = bInUVsHighPrecision;
68  const_cast<int32&>(UVChannelCount) = bInUVCount;
69  const_cast<int32&>(UVSize) = (bUVHighPrecision ? sizeof(FVector2D) : sizeof(FVector2DHalf));
70  const_cast<int32&>(UVStride) = UVSize * UVChannelCount;
71 }
72 
74 {
76  int32 Count = PositionStream->Num() / PositionStride;
77  return Count;
78 }
79 
81 {
83  return UVChannelCount;
84 }
85 
87 {
90  PositionStream->Empty(Slack * PositionStride);
91  TangentStream->Empty(Slack * TangentStride);
92  UVStream->Empty(Slack * UVSize);
93  ColorStream->Empty(Slack * ColorStride);
94 }
95 
97 {
100  PositionStream->SetNumZeroed(NewNum * PositionStride);
101  TangentStream->SetNumZeroed(NewNum * TangentStride);
102  UVStream->SetNumZeroed(NewNum * UVStride);
103  ColorStream->SetNumZeroed(NewNum * ColorStride);
104 }
105 
107 {
109  check(!bIsReadonly);
110  int32 NewIndex = AddSingleVertex();
111 
112  SetPosition(NewIndex, InPosition);
113 
114  return NewIndex;
115 }
116 
118 {
120  return GetStreamAccess<FVector>(PositionStream, Index, PositionStride, 0);
121 }
122 
124 {
127  {
128 #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 20
129  return GetStreamAccess<FRuntimeMeshTangentsHighPrecision>(TangentStream, Index, TangentStride, 0).Normal.ToFVector4();
130 #else
131  return GetStreamAccess<FRuntimeMeshTangentsHighPrecision>(TangentStream, Index, TangentStride, 0).Normal;
132 #endif
133  }
134  else
135  {
136 #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 20
137  return GetStreamAccess<FRuntimeMeshTangents>(TangentStream, Index, TangentStride, 0).Normal.ToFVector4();
138 #else
139  return GetStreamAccess<FRuntimeMeshTangents>(TangentStream, Index, TangentStride, 0).Normal;
140 #endif
141  }
142 }
143 
145 {
148  {
149 #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 20
150  return GetStreamAccess<FRuntimeMeshTangentsHighPrecision>(TangentStream, Index, TangentStride, 0).Tangent.ToFVector4();
151 #else
152  return GetStreamAccess<FRuntimeMeshTangentsHighPrecision>(TangentStream, Index, TangentStride, 0).Tangent;
153 #endif
154  }
155  else
156  {
157 #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 20
158  return GetStreamAccess<FRuntimeMeshTangents>(TangentStream, Index, TangentStride, 0).Tangent.ToFVector4();
159 #else
160  return GetStreamAccess<FRuntimeMeshTangents>(TangentStream, Index, TangentStride, 0).Tangent;
161 #endif
162  }
163 }
164 
166 {
168  return GetStreamAccess<FColor>(ColorStream, Index, ColorStride, 0);
169 }
170 
171 FVector2D FRuntimeMeshVerticesAccessor::GetUV(int32 Index, int32 Channel) const
172 {
174  check(Channel >= 0 && Channel < UVChannelCount);
175  if (bUVHighPrecision)
176  {
177  return GetStreamAccess<FRuntimeMeshEightUV<FVector2D>>(UVStream, Index, UVStride, 0).UVs[Channel];
178  }
179  else
180  {
181  return GetStreamAccess<FRuntimeMeshEightUV<FVector2DHalf>>(UVStream, Index, UVStride, 0).UVs[Channel];
182  }
183 }
184 
186 {
188  GetStreamAccess<FVector>(PositionStream, Index, PositionStride, 0) = Value;
189 }
190 
191 bool FRuntimeMeshVerticesAccessor::SetPositions(const int32 InsertAtIndex, const TArray<FVector>& Positions, const int32 Count, const bool bSizeToFit)
192 {
193  int32 CountClamped = FMath::Clamp(Count, 0, Positions.Num());
194  return SetPositions(InsertAtIndex, Positions.GetData(), CountClamped, bSizeToFit);
195 }
196 
197 bool FRuntimeMeshVerticesAccessor::SetPositions(const int32 InsertAtIndex, const FVector *const Positions, const int32 Count, const bool bSizeToFit)
198 {
200  check(!bIsReadonly);
201  if (InsertAtIndex + Count > NumVertices())
202  {
203  if (bSizeToFit)
204  {
205  SetNumVertices(InsertAtIndex + Count);
206  }
207  else
208  {
209  return false;
210  }
211  }
212 
213  FMemory::Memcpy(GetStreamAccessPointer(PositionStream, InsertAtIndex, PositionStride, 0), Positions, Count * sizeof(*Positions));
214  return true;
215 }
216 
218 {
220  check(!bIsReadonly);
222  {
223  GetStreamAccess<FRuntimeMeshTangentsHighPrecision>(TangentStream, Index, TangentStride, 0).Normal = Value;
224  }
225  else
226  {
227  GetStreamAccess<FRuntimeMeshTangents>(TangentStream, Index, TangentStride, 0).Normal = Value;
228  }
229 }
230 
232 {
234  check(!bIsReadonly);
236  {
237  GetStreamAccess<FRuntimeMeshTangentsHighPrecision>(TangentStream, Index, TangentStride, 0).Tangent = Value;
238  }
239  else
240  {
241  GetStreamAccess<FRuntimeMeshTangents>(TangentStream, Index, TangentStride, 0).Tangent = Value;
242  }
243 }
244 
246 {
248  check(!bIsReadonly);
250  {
251  FRuntimeMeshTangentsHighPrecision& Tangents = GetStreamAccess<FRuntimeMeshTangentsHighPrecision>(TangentStream, Index, TangentStride, 0);
252 #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 20
253  FVector4 NewNormal = Tangents.Normal.ToFVector4();
254 #else
255  FVector4 NewNormal = Tangents.Normal;
256 #endif
257  NewNormal.W = Value.bFlipTangentY ? -1.0f : 1.0f;
258  Tangents.Normal = NewNormal;
259  Tangents.Tangent = Value.TangentX;
260  }
261  else
262  {
263  FRuntimeMeshTangents& Tangents = GetStreamAccess<FRuntimeMeshTangents>(TangentStream, Index, TangentStride, 0);
264 #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 20
265  FVector4 NewNormal = Tangents.Normal.ToFVector4();
266 #else
267  FVector4 NewNormal = Tangents.Normal;
268 #endif
269  NewNormal.W = Value.bFlipTangentY ? -1.0f : 1.0f;
270  Tangents.Normal = NewNormal;
271  Tangents.Tangent = Value.TangentX;
272  }
273 }
274 
276 {
278  check(!bIsReadonly);
279  GetStreamAccess<FColor>(ColorStream, Index, ColorStride, 0) = Value;
280 }
281 
282 bool FRuntimeMeshVerticesAccessor::SetColors(const int32 InsertAtIndex, const TArray<FColor>& Colors, const int32 Count, const bool bSizeToFit)
283 {
284  int32 CountClamped = FMath::Clamp(Count, 0, Colors.Num());
285  return SetColors(InsertAtIndex, Colors.GetData(), CountClamped, bSizeToFit);
286 }
287 
288 bool FRuntimeMeshVerticesAccessor::SetColors(const int32 InsertAtIndex, const FColor *const Colors, const int32 Count, const bool bSizeToFit)
289 {
291  check(!bIsReadonly);
292  if (InsertAtIndex + Count > NumVertices())
293  {
294  if (bSizeToFit)
295  {
296  SetNumVertices(InsertAtIndex + Count);
297  }
298  else
299  {
300  return false;
301  }
302  }
303 
304  FMemory::Memcpy(GetStreamAccessPointer(ColorStream, InsertAtIndex, ColorStride, 0), Colors, Count * sizeof(*Colors));
305  return true;
306 }
307 
308 void FRuntimeMeshVerticesAccessor::SetUV(int32 Index, const FVector2D& Value)
309 {
311  check(!bIsReadonly);
312  check(UVChannelCount > 0);
313  if (bUVHighPrecision)
314  {
315  GetStreamAccess<FRuntimeMeshEightUV<FVector2D>>(UVStream, Index, UVStride, 0).UVs[0] = Value;
316  }
317  else
318  {
319  GetStreamAccess<FRuntimeMeshEightUV<FVector2DHalf>>(UVStream, Index, UVStride, 0).UVs[0] = Value;
320  }
321 }
322 
323 void FRuntimeMeshVerticesAccessor::SetUV(int32 Index, int32 Channel, const FVector2D& Value)
324 {
326  check(!bIsReadonly);
327  check(Channel >= 0 && Channel < UVChannelCount);
328  if (bUVHighPrecision)
329  {
330  GetStreamAccess<FRuntimeMeshEightUV<FVector2D>>(UVStream, Index, UVStride, 0).UVs[Channel] = Value;
331  }
332  else
333  {
334  GetStreamAccess<FRuntimeMeshEightUV<FVector2DHalf>>(UVStream, Index, UVStride, 0).UVs[Channel] = Value;
335  }
336 }
337 
338 bool FRuntimeMeshVerticesAccessor::SetUVs(const int32 InsertAtVertexIndex, const TArray<FVector2D>& UVs, const int32 CountVertices, const bool bSizeToFit)
339 {
340  check(FMath::IsNearlyZero(FMath::Fractional((float)UVs.Num() / (float)UVChannelCount))); // If this triggers, the your uv data are out of alignment.
341  int32 CountClamped = FMath::Clamp(CountVertices, 0, UVs.Num());
342  return SetUVs(InsertAtVertexIndex, UVs.GetData(), CountClamped, bSizeToFit);
343 }
344 
345 
346 bool FRuntimeMeshVerticesAccessor::SetUVs(const int32 InsertAtVertexIndex, const TArray<FVector2DHalf>& UVs, const int32 CountVertices, const bool bSizeToFit)
347 {
348  check(FMath::IsNearlyZero(FMath::Fractional((float)UVs.Num() / (float)UVChannelCount))); // If this triggers, the your uv data are out of alignment.
349  int32 CountClamped = FMath::Clamp(CountVertices, 0, UVs.Num());
350  return SetUVs(InsertAtVertexIndex, UVs.GetData(), CountClamped, bSizeToFit);
351 
352 }
353 
354 bool FRuntimeMeshVerticesAccessor::SetUVs(const int32 InsertAtVertexIndex, const FVector2D *const UVs, const int32 CountVertices, const bool bSizeToFit)
355 {
357  check(!bIsReadonly);
358  check(bUVHighPrecision); // Half precision is not supported by this function
359  if (InsertAtVertexIndex + CountVertices > NumVertices())
360  {
361  if (bSizeToFit)
362  {
363  SetNumVertices(InsertAtVertexIndex + CountVertices);
364  }
365  else
366  {
367  return false;
368  }
369  }
370 
371  FMemory::Memcpy(GetStreamAccessPointer(UVStream, InsertAtVertexIndex, UVStride, 0), UVs, CountVertices * sizeof(*UVs) * UVChannelCount);
372  return true;
373 }
374 
375 bool FRuntimeMeshVerticesAccessor::SetUVs(const int32 InsertAtVertexIndex, const FVector2DHalf *const UVs, const int32 CountVertices, const bool bSizeToFit)
376 {
378  check(!bIsReadonly);
379  check(!bUVHighPrecision); // Only Half precision is supported by this function
380  if (InsertAtVertexIndex + CountVertices > NumVertices())
381  {
382  if (bSizeToFit)
383  {
384  SetNumVertices(InsertAtVertexIndex + CountVertices);
385  }
386  else
387  {
388  return false;
389  }
390  }
391 
392  FMemory::Memcpy(GetStreamAccessPointer(UVStream, InsertAtVertexIndex, UVStride, 0), UVs, CountVertices * sizeof(*UVs) * UVChannelCount);
393  return true;
394 }
395 
397 {
399  check(!bIsReadonly);
401  {
402  FRuntimeMeshTangentsHighPrecision& Tangents = GetStreamAccess<FRuntimeMeshTangentsHighPrecision>(TangentStream, Index, TangentStride, 0);
403  Tangents.Normal = FVector4(Normal, Tangent.bFlipTangentY ? -1 : 1);
404  Tangents.Tangent = Tangent.TangentX;
405  }
406  else
407  {
408  FRuntimeMeshTangents& Tangents = GetStreamAccess<FRuntimeMeshTangents>(TangentStream, Index, TangentStride, 0);
409  Tangents.Normal = FVector4(Normal, Tangent.bFlipTangentY ? -1 : 1);
410  Tangents.Tangent = Tangent.TangentX;
411  }
412 }
413 
414 void FRuntimeMeshVerticesAccessor::SetTangents(int32 Index, FVector TangentX, FVector TangentY, FVector TangentZ)
415 {
417  check(!bIsReadonly);
419  {
420  FRuntimeMeshTangentsHighPrecision& Tangents = GetStreamAccess<FRuntimeMeshTangentsHighPrecision>(TangentStream, Index, TangentStride, 0);
421  Tangents.Normal = FVector4(TangentZ, GetBasisDeterminantSign(TangentX, TangentY, TangentZ));
422  Tangents.Tangent = TangentX;
423  }
424  else
425  {
426  FRuntimeMeshTangents& Tangents = GetStreamAccess<FRuntimeMeshTangents>(TangentStream, Index, TangentStride, 0);
427  Tangents.Normal = FVector4(TangentZ, GetBasisDeterminantSign(TangentX, TangentY, TangentZ));
428  Tangents.Tangent = TangentX;
429  }
430 }
431 
432 
433 
434 
435 
437 {
440 
441  Vertex.Position = GetStreamAccess<FVector>(PositionStream, Index, PositionStride, 0);
442 
444  {
445  FRuntimeMeshTangentsHighPrecision& Tangents = GetStreamAccess<FRuntimeMeshTangentsHighPrecision>(TangentStream, Index, TangentStride, 0);
446 #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 20
447  Vertex.Normal = Tangents.Normal.ToFVector4();
448  Vertex.Tangent = Tangents.Tangent.ToFVector();
449 #else
450  Vertex.Normal = Tangents.Normal;
451  Vertex.Tangent = Tangents.Tangent;
452 #endif
453  }
454  else
455  {
456  FRuntimeMeshTangents& Tangents = GetStreamAccess<FRuntimeMeshTangents>(TangentStream, Index, TangentStride, 0);
457 #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 20
458  Vertex.Normal = Tangents.Normal.ToFVector4();
459  Vertex.Tangent = Tangents.Tangent.ToFVector();
460 #else
461  Vertex.Normal = Tangents.Normal;
462  Vertex.Tangent = Tangents.Tangent;
463 #endif
464  }
465 
466  Vertex.Color = GetStreamAccess<FColor>(ColorStream, Index, ColorStride, 0);
467 
468  Vertex.UVs.SetNum(NumUVChannels());
469  if (bUVHighPrecision)
470  {
471  FRuntimeMeshEightUV<FVector2D>& UVs = GetStreamAccess<FRuntimeMeshEightUV<FVector2D>>(UVStream, Index, UVStride, 0);
472  for (int32 UVIndex = 0; UVIndex < Vertex.UVs.Num(); UVIndex++)
473  {
474  Vertex.UVs[UVIndex] = UVs.UVs[UVIndex];
475  }
476  }
477  else
478  {
479  FRuntimeMeshEightUV<FVector2DHalf>& UVs = GetStreamAccess<FRuntimeMeshEightUV<FVector2DHalf>>(UVStream, Index, UVStride, 0);
480  for (int32 UVIndex = 0; UVIndex < Vertex.UVs.Num(); UVIndex++)
481  {
482  Vertex.UVs[UVIndex] = UVs.UVs[UVIndex];
483  }
484  }
485 
486  return Vertex;
487 }
488 
490 {
492  check(!bIsReadonly);
493 
494  GetStreamAccess<FVector>(PositionStream, Index, PositionStride, 0) = Vertex.Position;
495 
497  {
498  FRuntimeMeshTangentsHighPrecision& Tangents = GetStreamAccess<FRuntimeMeshTangentsHighPrecision>(TangentStream, Index, TangentStride, 0);
499  Tangents.Normal = Vertex.Normal;
500  Tangents.Tangent = Vertex.Tangent;
501  }
502  else
503  {
504  FRuntimeMeshTangents& Tangents = GetStreamAccess<FRuntimeMeshTangents>(TangentStream, Index, TangentStride, 0);
505  Tangents.Normal = Vertex.Normal;
506  Tangents.Tangent = Vertex.Tangent;
507  }
508 
509  GetStreamAccess<FColor>(ColorStream, Index, ColorStride, 0) = Vertex.Color;
510 
511  if (bUVHighPrecision)
512  {
513  FRuntimeMeshEightUV<FVector2D>& UVs = GetStreamAccess<FRuntimeMeshEightUV<FVector2D>>(UVStream, Index, UVStride, 0);
514  for (int32 UVIndex = 0; UVIndex < Vertex.UVs.Num(); UVIndex++)
515  {
516  UVs.UVs[UVIndex] = Vertex.UVs[UVIndex];
517  }
518  }
519  else
520  {
521  FRuntimeMeshEightUV<FVector2DHalf>& UVs = GetStreamAccess<FRuntimeMeshEightUV<FVector2DHalf>>(UVStream, Index, UVStride, 0);
522  for (int32 UVIndex = 0; UVIndex < Vertex.UVs.Num(); UVIndex++)
523  {
524  UVs.UVs[UVIndex] = Vertex.UVs[UVIndex];
525  }
526  }
527 }
528 
530 {
532  check(!bIsReadonly);
533  int32 NewIndex = AddSingleVertex();
534  SetVertex(NewIndex, Vertex);
535  return NewIndex;
536 }
537 
538 
539 
541 {
542  int32 NewIndex = NumVertices();
543 
544  PositionStream->AddZeroed(PositionStride);
545  TangentStream->AddZeroed(TangentStride);
546  UVStream->AddZeroed(UVStride);
547  ColorStream->AddZeroed(ColorStride);
548 
549  return NewIndex;
550 }
551 
552 
553 
554 
555 
557 // FRuntimeMeshIndicesAccessor
558 
559 FRuntimeMeshIndicesAccessor::FRuntimeMeshIndicesAccessor(TArray<uint8>* IndexStreamData, bool bInIsReadonly)
560  : bIsInitialized(false)
561  , bIsReadonly(bInIsReadonly)
562  , IndexStream(IndexStreamData), b32BitIndices(false)
563 {
564 }
565 
566 FRuntimeMeshIndicesAccessor::FRuntimeMeshIndicesAccessor(bool bIn32BitIndices, TArray<uint8>* IndexStreamData, bool bInIsReadonly)
567  : bIsInitialized(false)
568  , bIsReadonly(bInIsReadonly)
569  , IndexStream(IndexStreamData), b32BitIndices(false)
570 {
571  Initialize(bIn32BitIndices);
572 }
573 
575 {
576 }
577 
578 void FRuntimeMeshIndicesAccessor::Initialize(bool bIn32BitIndices)
579 {
580  bIsInitialized = true;
581  b32BitIndices = bIn32BitIndices;
582 
583  check((IndexStream->Num() % (b32BitIndices ? 4 : 2)) == 0);
584 }
585 
587 {
589  return IndexStream->Num() / GetIndexStride();
590 }
591 
593 {
595  check(!bIsReadonly);
596  IndexStream->Empty(Slack * GetIndexStride());
597 }
598 
600 {
602  check(!bIsReadonly);
603  IndexStream->SetNumZeroed(NewNum * GetIndexStride());
604 }
605 
607 {
609  check(!bIsReadonly);
610  int32 NewPosition = NumIndices();
611  IndexStream->AddZeroed(GetIndexStride());
612  SetIndex(NewPosition, NewIndex);
613  return NewPosition;
614 }
615 
616 int32 FRuntimeMeshIndicesAccessor::AddTriangle(int32 Index0, int32 Index1, int32 Index2)
617 {
619  check(!bIsReadonly);
620  int32 NewPosition = NumIndices();
621  IndexStream->AddZeroed(GetIndexStride() * 3);
622  SetIndex(NewPosition + 0, Index0);
623  SetIndex(NewPosition + 1, Index1);
624  SetIndex(NewPosition + 2, Index2);
625  return NewPosition;
626 }
627 
629 {
631  if (b32BitIndices)
632  {
633  return GetStreamAccess<int32>(IndexStream, Index, sizeof(int32), 0);
634  }
635  else
636  {
637  return GetStreamAccess<uint16>(IndexStream, Index, sizeof(uint16), 0);
638  }
639 }
640 
642 {
644  check(!bIsReadonly);
645  if (b32BitIndices)
646  {
647  GetStreamAccess<int32>(IndexStream, Index, sizeof(int32), 0) = Value;
648  }
649  else
650  {
651  GetStreamAccess<uint16>(IndexStream, Index, sizeof(uint16), 0) = Value;
652  }
653 }
654 
655 bool FRuntimeMeshIndicesAccessor::SetIndices(const int32 InsertAtIndex, const TArray<uint16>& Indices, const int32 Count, const bool bSizeToFit)
656 {
657  int32 CountClamped = FMath::Clamp(Count, 0, Indices.Num());
658  return SetIndices(InsertAtIndex, Indices.GetData(), CountClamped, bSizeToFit);
659 }
660 
661 bool FRuntimeMeshIndicesAccessor::SetIndices(const int32 InsertAtIndex, const uint16 *const Indices, const int32 Count, const bool bSizeToFit)
662 {
665  check(!bIsReadonly);
666  if (InsertAtIndex + Count > NumIndices())
667  {
668  if (bSizeToFit)
669  {
670  SetNumIndices(InsertAtIndex + Count);
671  }
672  else
673  {
674  return false;
675  }
676  }
677 
678  FMemory::Memcpy(GetStreamAccessPointer(IndexStream, InsertAtIndex, sizeof(uint16), 0), Indices, Count * sizeof(*Indices));
679  return true;
680 }
681 
682 bool FRuntimeMeshIndicesAccessor::SetIndices(const int32 InsertAtIndex, const TArray<int32>& Indices, const int32 Count, const bool bSizeToFit)
683 {
684  int32 CountClamped = FMath::Clamp(Count, 0, Indices.Num());
685  return SetIndices(InsertAtIndex, Indices.GetData(), CountClamped, bSizeToFit);
686 }
687 
688 bool FRuntimeMeshIndicesAccessor::SetIndices(const int32 InsertAtIndex, const int32 *const Indices, const int32 Count, const bool bSizeToFit)
689 {
692  check(!bIsReadonly);
693  if (InsertAtIndex + Count > NumIndices())
694  {
695  if (bSizeToFit)
696  {
697  SetNumIndices(InsertAtIndex + Count);
698  }
699  else
700  {
701  return false;
702  }
703  }
704 
705  FMemory::Memcpy(GetStreamAccessPointer(IndexStream, InsertAtIndex, sizeof(int32), 0), Indices, Count * sizeof(*Indices));
706  return true;
707 }
708 
710 // FRuntimeMeshAccessor
711 
712 FRuntimeMeshAccessor::FRuntimeMeshAccessor(bool bInTangentsHighPrecision, bool bInUVsHighPrecision, int32 bInUVCount, bool bIn32BitIndices, TArray<uint8>* PositionStreamData,
713  TArray<uint8>* TangentStreamData, TArray<uint8>* UVStreamData, TArray<uint8>* ColorStreamData, TArray<uint8>* IndexStreamData, bool bInIsReadonly)
714  : FRuntimeMeshVerticesAccessor(bInTangentsHighPrecision, bInUVsHighPrecision, bInUVCount, PositionStreamData, TangentStreamData, UVStreamData, ColorStreamData, bInIsReadonly)
715  , FRuntimeMeshIndicesAccessor(bIn32BitIndices, IndexStreamData, bInIsReadonly)
716 {
717 
718 }
719 
721 {
722 }
723 
724 FRuntimeMeshAccessor::FRuntimeMeshAccessor(TArray<uint8>* PositionStreamData, TArray<uint8>* TangentStreamData, TArray<uint8>* UVStreamData, TArray<uint8>* ColorStreamData, TArray<uint8>* IndexStreamData, bool bInIsReadonly)
725  : FRuntimeMeshVerticesAccessor(PositionStreamData, TangentStreamData, UVStreamData, ColorStreamData, bInIsReadonly)
726  , FRuntimeMeshIndicesAccessor(IndexStreamData, bInIsReadonly)
727 {
728 
729 }
730 
731 void FRuntimeMeshAccessor::Initialize(bool bInTangentsHighPrecision, bool bInUVsHighPrecision, int32 bInUVCount, bool bIn32BitIndices)
732 {
733  FRuntimeMeshVerticesAccessor::Initialize(bInTangentsHighPrecision, bInUVsHighPrecision, bInUVCount);
735 }
736 
737 
738 
739 
740 void FRuntimeMeshAccessor::CopyTo(const TSharedPtr<FRuntimeMeshAccessor>& Other, bool bClearDestination) const
741 {
742  if (bClearDestination)
743  {
744  Other->EmptyVertices(NumVertices());
745  Other->EmptyIndices(NumIndices());
746  }
747 
748  // TODO: Make this faster using short paths when the structures are the same.
749 
750  int32 StartVertex = Other->NumVertices();
751  int32 NumVerts = NumVertices();
752  int32 NumUVs = FMath::Min(NumUVChannels(), Other->NumUVChannels());
753 
754  for (int32 Index = 0; Index < NumVerts; Index++)
755  {
756  int32 NewIndex = Other->AddVertex(GetPosition(Index));
757  Other->SetNormal(NewIndex, GetNormal(Index));
758  Other->SetTangent(NewIndex, GetTangent(Index));
759  Other->SetColor(NewIndex, GetColor(Index));
760  for (int32 UVIndex = 0; UVIndex < NumUVs; UVIndex++)
761  {
762  Other->SetUV(NewIndex, UVIndex, GetUV(Index, UVIndex));
763  }
764  }
765 
766  int32 NumInds = NumIndices();
767  for (int32 Index = 0; Index < NumInds; Index++)
768  {
769  Other->AddIndex(GetIndex(Index) + StartVertex);
770  }
771 }
772 
774 // FRuntimeMeshBuilder
775 
776 FRuntimeMeshBuilder::FRuntimeMeshBuilder(bool bInTangentsHighPrecision, bool bInUVsHighPrecision, int32 bInUVCount, bool bIn32BitIndices)
778 {
779  FRuntimeMeshAccessor::Initialize(bInTangentsHighPrecision, bInUVsHighPrecision, bInUVCount, bIn32BitIndices);
780 }
781 
783 {
784 
785 }
786 
787 
789 // FRuntimeMeshScopedUpdater
790 
791 FRuntimeMeshScopedUpdater::FRuntimeMeshScopedUpdater(const FRuntimeMeshDataPtr& InLinkedMeshData, int32 InSectionIndex, ESectionUpdateFlags InUpdateFlags, bool bInTangentsHighPrecision, bool bInUVsHighPrecision, int32 bInUVCount, bool bIn32BitIndices,
792  TArray<uint8>* PositionStreamData, TArray<uint8>* TangentStreamData, TArray<uint8>* UVStreamData, TArray<uint8>* ColorStreamData, TArray<uint8>* IndexStreamData, FRuntimeMeshLockProvider* InSyncObject, bool bIsReadonly)
793  : FRuntimeMeshAccessor(bInTangentsHighPrecision, bInUVsHighPrecision, bInUVCount, bIn32BitIndices, PositionStreamData, TangentStreamData, UVStreamData, ColorStreamData, IndexStreamData, bIsReadonly)
794  , FRuntimeMeshScopeLock(InSyncObject, true)
795  , LinkedMeshData(InLinkedMeshData), SectionIndex(InSectionIndex), UpdateFlags(InUpdateFlags)
796 {
797 
798 }
799 
801 {
802  Cancel();
803 }
804 
805 void FRuntimeMeshScopedUpdater::Commit(bool bNeedsPositionUpdate, bool bNeedsNormalTangentUpdate, bool bNeedsColorUpdate, bool bNeedsUVUpdate, bool bNeedsIndexUpdate)
806 {
807  check(!IsReadonly());
808 
809  ERuntimeMeshBuffersToUpdate BuffersToUpdate;
810  BuffersToUpdate |= bNeedsPositionUpdate ? ERuntimeMeshBuffersToUpdate::PositionBuffer : ERuntimeMeshBuffersToUpdate::None;
811  BuffersToUpdate |= bNeedsNormalTangentUpdate ? ERuntimeMeshBuffersToUpdate::TangentBuffer : ERuntimeMeshBuffersToUpdate::None;
812  BuffersToUpdate |= bNeedsColorUpdate ? ERuntimeMeshBuffersToUpdate::ColorBuffer : ERuntimeMeshBuffersToUpdate::None;
813  BuffersToUpdate |= bNeedsUVUpdate ? ERuntimeMeshBuffersToUpdate::UVBuffer : ERuntimeMeshBuffersToUpdate::None;
814  BuffersToUpdate |= bNeedsIndexUpdate ? ERuntimeMeshBuffersToUpdate::IndexBuffer : ERuntimeMeshBuffersToUpdate::None;
815 
816  LinkedMeshData->EndSectionUpdate(this, BuffersToUpdate);
817 
818  // Release the mesh and lock.
821 }
822 
823 void FRuntimeMeshScopedUpdater::Commit(const FBox& BoundingBox, bool bNeedsPositionUpdate, bool bNeedsNormalTangentUpdate, bool bNeedsColorUpdate, bool bNeedsUVUpdate, bool bNeedsIndexUpdate)
824 {
825  check(!IsReadonly());
826 
827  ERuntimeMeshBuffersToUpdate BuffersToUpdate;
828  BuffersToUpdate |= bNeedsPositionUpdate ? ERuntimeMeshBuffersToUpdate::PositionBuffer : ERuntimeMeshBuffersToUpdate::None;
829  BuffersToUpdate |= bNeedsNormalTangentUpdate ? ERuntimeMeshBuffersToUpdate::TangentBuffer : ERuntimeMeshBuffersToUpdate::None;
830  BuffersToUpdate |= bNeedsColorUpdate ? ERuntimeMeshBuffersToUpdate::ColorBuffer : ERuntimeMeshBuffersToUpdate::None;
831  BuffersToUpdate |= bNeedsUVUpdate ? ERuntimeMeshBuffersToUpdate::UVBuffer : ERuntimeMeshBuffersToUpdate::None;
832  BuffersToUpdate |= bNeedsIndexUpdate ? ERuntimeMeshBuffersToUpdate::IndexBuffer : ERuntimeMeshBuffersToUpdate::None;
833 
834  LinkedMeshData->EndSectionUpdate(this, BuffersToUpdate, &BoundingBox);
835 
836  // Release the mesh and lock.
839 }
840 
842 {
843  // Release the mesh and lock.
846 }
void CopyTo(const TSharedPtr< FRuntimeMeshAccessor > &Other, bool bClearDestination=false) const
FRuntimeMeshVerticesAccessor(bool bInTangentsHighPrecision, bool bInUVsHighPrecision, int32 bInUVCount, TArray< uint8 > *PositionStreamData, TArray< uint8 > *TangentStreamData, TArray< uint8 > *UVStreamData, TArray< uint8 > *ColorStreamData, bool bInIsReadonly=false)
FVector GetPosition(int32 Index) const
int32 AddVertex(FVector InPosition)
int32 GetIndex(int32 Index) const
void Initialize(bool bIn32BitIndices)
FVector4 GetNormal(int32 Index) const
bool SetColors(const int32 InsertAtIndex, const TArray< FColor > &Colors, const int32 Count, const bool bSizeToFit)
void Initialize(bool bInTangentsHighPrecision, bool bInUVsHighPrecision, int32 bInUVCount, bool bIn32BitIndices)
FRuntimeMeshIndicesAccessor(bool bIn32BitIndices, TArray< uint8 > *IndexStreamData, bool bInIsReadonly=false)
FORCEINLINE int32 GetIndexStride() const
void SetVertex(int32 Index, const FRuntimeMeshAccessorVertex &Vertex)
FColor GetColor(int32 Index) const
static FORCEINLINE TYPE & GetStreamAccess(TArray< uint8 > *Data, int32 Index, int32 Stride, int32 Offset)
void Initialize(bool bInTangentsHighPrecision, bool bInUVsHighPrecision, int32 bInUVCount)
TSharedPtr< FRuntimeMeshData, ESPMode::ThreadSafe > FRuntimeMeshDataPtr
void SetColor(int32 Index, const FColor &Value)
void SetNormal(int32 Index, const FVector4 &Value)
TStaticArray< TYPE, 8 > UVs
static const int32 PositionStride
static const textual_icon check
Definition: model-views.h:260
void SetTangent(int32 Index, const FVector &Value)
void SetNormalTangent(int32 Index, FVector Normal, FRuntimeMeshTangent Tangent)
IMGUI_API void Value(const char *prefix, bool b)
Definition: imgui.cpp:9538
ESectionUpdateFlags
void SetUV(int32 Index, const FVector2D &Value)
int32 AddTriangle(int32 Index0, int32 Index1, int32 Index2)
struct Index Index
Definition: sqlite3.c:11789
TArray< FVector2D, TInlineAllocator< RUNTIMEMESH_MAXTEXCOORDS > > UVs
void Commit(bool bNeedsPositionUpdate=true, bool bNeedsNormalTangentUpdate=true, bool bNeedsColorUpdate=true, bool bNeedsUVUpdate=true, bool bNeedsIndexUpdate=true)
FRuntimeMeshScopedUpdater(const FRuntimeMeshDataPtr &InLinkedMeshData, int32 InSectionIndex, ESectionUpdateFlags InUpdateFlags, bool bInTangentsHighPrecision, bool bInUVsHighPrecision, int32 bInUVCount, bool bIn32BitIndices, TArray< uint8 > *PositionStreamData, TArray< uint8 > *TangentStreamData, TArray< uint8 > *UVStreamData, TArray< uint8 > *ColorStreamData, TArray< uint8 > *IndexStreamData, FRuntimeMeshLockProvider *InSyncObject, bool bIsReadonly)
static FORCEINLINE uint8 * GetStreamAccessPointer(TArray< uint8 > *Data, int32 Index, int32 Stride, int32 Offset)
FRuntimeMeshAccessor(bool bInTangentsHighPrecision, bool bInUVsHighPrecision, int32 bInUVCount, bool bIn32BitIndices, TArray< uint8 > *PositionStreamData, TArray< uint8 > *TangentStreamData, TArray< uint8 > *UVStreamData, TArray< uint8 > *ColorStreamData, TArray< uint8 > *IndexStreamData, bool bInIsReadonly=false)
void SetPosition(int32 Index, const FVector &Value)
bool SetUVs(const int32 InsertAtVertexIndex, const TArray< FVector2D > &UVs, const int32 CountVertices, const bool bSizeToFit)
void SetIndex(int32 Index, int32 Value)
FVector2D GetUV(int32 Index, int32 Channel=0) const
virtual ~FRuntimeMeshAccessor() override
ERuntimeMeshBuffersToUpdate
bool SetPositions(const int32 InsertAtIndex, const TArray< FVector > &Positions, const int32 Count, const bool bSizeToFit)
FRuntimeMeshDataPtr LinkedMeshData
void SetTangents(int32 Index, FVector TangentX, FVector TangentY, FVector TangentZ)
FVector GetTangent(int32 Index) const
FRuntimeMeshBuilder(bool bInTangentsHighPrecision, bool bInUVsHighPrecision, int32 bInUVCount, bool bIn32BitIndices)
bool SetIndices(const int32 InsertAtIndex, const TArray< uint16 > &Indices, const int32 Count, const bool bSizeToFit)
FRuntimeMeshAccessorVertex GetVertex(int32 Index) const
int32 AddIndex(int32 NewIndex)
virtual ~FRuntimeMeshBuilder() override


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:41