Skip to content

Commit

Permalink
fixed #18374: 2D Node with MotionStreak and Rigidbody has wrong offset
Browse files Browse the repository at this point in the history
  • Loading branch information
dumganhar committed Feb 26, 2025
1 parent ee686d8 commit ec20bed
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 26 deletions.
43 changes: 34 additions & 9 deletions cocos/2d/renderer/render-draw-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ import { Sampler, Texture } from '../../gfx';
import { Model } from '../../render-scene/scene';
import { Material } from '../../asset/assets';

const bitIndexForIsMeshBuffer = 0;
const bitIndexForIsVertexPositionInWorld = 1;

export enum AttrUInt8ArrayView {
DrawInfoType,
VertDirty,
IsMeshBuffer,
BooleanValues, // 0 index bit: for IsMeshBuffer, 1 index bit: for isVertexPositionInWorld, remain 6 bits are reserved.
Stride,
Count
}
Expand All @@ -60,6 +63,14 @@ export enum RenderDrawInfoType {
SUB_NODE,
}

function setBitInTypedArray (arr: TypedArray, index: number, bitPosition: number): void {
arr[index] |= (1 << bitPosition);
}

function clearBitInTypedArray (arr: TypedArray, index: number, bitPosition: number): void {
arr[index] &= ~(1 << bitPosition);
}

/** @mangle */
export class RenderDrawInfo {
protected _accId = -1;
Expand Down Expand Up @@ -130,7 +141,7 @@ export class RenderDrawInfo {
this._vertDirty = false;
}

public setAccId (accId): void {
public setAccId (accId: number): void {
if (JSB) {
if (this._accId !== accId) {
this._uint16SharedBuffer[AttrUInt16ArrayView.AccessorID] = accId;
Expand All @@ -139,7 +150,7 @@ export class RenderDrawInfo {
this._accId = accId;
}

public setBufferId (bufferId): void {
public setBufferId (bufferId: number): void {
if (JSB) {
if (this._bufferId !== bufferId) {
this._uint16SharedBuffer[AttrUInt16ArrayView.BufferID] = bufferId;
Expand All @@ -149,7 +160,7 @@ export class RenderDrawInfo {
this._bufferId = bufferId;
}

public setAccAndBuffer (accId, bufferId): void {
public setAccAndBuffer (accId: number, bufferId: number): void {
if (JSB) {
if (this._accId !== accId || this._bufferId !== bufferId) {
this._uint16SharedBuffer[AttrUInt16ArrayView.AccessorID] = accId;
Expand All @@ -161,14 +172,14 @@ export class RenderDrawInfo {
this._accId = accId;
}

public setVertexOffset (vertexOffset): void {
public setVertexOffset (vertexOffset: number): void {
this._vertexOffset = vertexOffset;
if (JSB) {
this._uint32SharedBuffer[AttrUInt32ArrayView.VertexOffset] = vertexOffset;
}
}

public setIndexOffset (indexOffset): void {
public setIndexOffset (indexOffset: number): void {
this._indexOffset = indexOffset;
if (JSB) {
this._uint32SharedBuffer[AttrUInt32ArrayView.IndexOffset] = indexOffset;
Expand Down Expand Up @@ -199,14 +210,14 @@ export class RenderDrawInfo {
}
}

public setVBCount (vbCount): void {
public setVBCount (vbCount: number): void {
if (JSB) {
this._uint32SharedBuffer[AttrUInt32ArrayView.VBCount] = vbCount;
}
this._vbCount = vbCount;
}

public setIBCount (ibCount): void {
public setIBCount (ibCount: number): void {
if (JSB) {
this._uint32SharedBuffer[AttrUInt32ArrayView.IBCount] = ibCount;
}
Expand All @@ -228,11 +239,25 @@ export class RenderDrawInfo {

public setIsMeshBuffer (isMeshBuffer: boolean): void {
if (JSB) {
this._uint8SharedBuffer[AttrUInt8ArrayView.IsMeshBuffer] = isMeshBuffer ? 1 : 0;
if (isMeshBuffer) {
setBitInTypedArray(this._uint8SharedBuffer, AttrUInt8ArrayView.BooleanValues, bitIndexForIsMeshBuffer);
} else {
clearBitInTypedArray(this._uint8SharedBuffer, AttrUInt8ArrayView.BooleanValues, bitIndexForIsMeshBuffer);
}
}
this._isMeshBuffer = isMeshBuffer;
}

public setVertexPositionInWorld (isVertexPositionInWorld: boolean): void {
if (JSB) {
if (isVertexPositionInWorld) {
setBitInTypedArray(this._uint8SharedBuffer, AttrUInt8ArrayView.BooleanValues, bitIndexForIsVertexPositionInWorld);
} else {
clearBitInTypedArray(this._uint8SharedBuffer, AttrUInt8ArrayView.BooleanValues, bitIndexForIsVertexPositionInWorld);
}
}
}

public setMaterial (material: Material): void {
if (JSB) {
if (this._material !== material) {
Expand Down
10 changes: 0 additions & 10 deletions cocos/particle-2d/motion-streak-2d-assembler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,6 @@ class MotionStreakAssembler implements IAssembler {
}
}

updateRenderData (comp: MotionStreak): void {
if (JSB) {
// A dirty hack
// The world matrix was updated in advance and needs to be avoided at the cpp level
// Need a flag to explicitly not update the world transform to solve this problem
comp.renderData!.renderDrawInfo.setVertDirty(false);
comp.node.hasChangedFlags = 0;
}
}

fillBuffers (comp: MotionStreak, renderer: IBatcher): void {
const renderData = comp.renderData!;
const chunk = renderData.chunk;
Expand Down
5 changes: 4 additions & 1 deletion cocos/particle-2d/motion-streak-2d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
*/

import { ccclass, executeInEditMode, serializable, playOnFocus, menu, help, editable, type } from 'cc.decorator';
import { EDITOR_NOT_IN_PREVIEW } from 'internal:constants';
import { EDITOR_NOT_IN_PREVIEW, JSB } from 'internal:constants';
import { UIRenderer } from '../2d/framework';
import { Texture2D } from '../asset/assets/texture-2d';
import type { IBatcher } from '../2d/renderer/i-batcher';
Expand Down Expand Up @@ -195,6 +195,9 @@ export class MotionStreak extends UIRenderer {
if (this._assembler && this._assembler.createData) {
this._renderData = this._assembler.createData(this) as RenderData;
this._renderData.material = this.material;
if (JSB) {
this._renderData.renderDrawInfo.setVertexPositionInWorld(true);
}
this._updateColor();
}
}
Expand Down
9 changes: 6 additions & 3 deletions native/cocos/2d/renderer/Batcher2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,13 @@ CC_FORCE_INLINE void Batcher2d::handleComponentDraw(RenderEntity* entity, Render
}

if (!drawInfo->getIsMeshBuffer()) {
if (node->getChangedFlags() || node->isTransformDirty() || drawInfo->getVertDirty()) {
fillVertexBuffers(entity, drawInfo);
drawInfo->setVertDirty(false);
if (!drawInfo->isVertexPositionInWorld()) {
if (node->getChangedFlags() || node->isTransformDirty() || drawInfo->getVertDirty()) {
fillVertexBuffers(entity, drawInfo);
drawInfo->setVertDirty(false);
}
}

if (entity->getVBColorDirty()) {
fillColors(entity, drawInfo);
}
Expand Down
3 changes: 3 additions & 0 deletions native/cocos/2d/renderer/RenderDrawInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ void mat4ToFloatArray(const cc::Mat4& mat, float* out, index_t ofs = 0) {
}

RenderDrawInfo::RenderDrawInfo() {
_drawInfoAttrs._isMeshBuffer = 0;
_drawInfoAttrs._isVertexPositionInWorld = 0;
_drawInfoAttrs._padding = 0;
_attrSharedBufferActor.initialize(&_drawInfoAttrs, sizeof(_drawInfoAttrs));
}

Expand Down
14 changes: 11 additions & 3 deletions native/cocos/2d/renderer/RenderDrawInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,15 @@ class RenderDrawInfo final {
_drawInfoAttrs._dataHash = dataHash;
}

inline bool getIsMeshBuffer() const { return _drawInfoAttrs._isMeshBuffer; }
inline bool getIsMeshBuffer() const {
return _drawInfoAttrs._isMeshBuffer != 0;
}
inline void setIsMeshBuffer(bool isMeshBuffer) {
_drawInfoAttrs._isMeshBuffer = isMeshBuffer;
_drawInfoAttrs._isMeshBuffer = isMeshBuffer ? 1 : 0;
}

inline bool isVertexPositionInWorld() const {
return _drawInfoAttrs._isVertexPositionInWorld != 0;
}

inline uint8_t getStride() const { return _drawInfoAttrs._stride; }
Expand Down Expand Up @@ -256,7 +262,9 @@ class RenderDrawInfo final {
struct DrawInfoAttrs {
RenderDrawInfoType _drawInfoType{RenderDrawInfoType::COMP};
bool _vertDirty{false};
bool _isMeshBuffer{false};
uint8_t _isMeshBuffer: 1;
uint8_t _isVertexPositionInWorld: 1;
uint8_t _padding: 6;
uint8_t _stride{0};
uint16_t _bufferId{0};
uint16_t _accId{0};
Expand Down

0 comments on commit ec20bed

Please sign in to comment.