flat assembler
Message board for the users of flat assembler.

Index > Tutorials and Examples > Box3D shared and static support for fasm2:

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
bitRAKE



Joined: 21 Jul 2003
Posts: 4560
Location: vpcmpistri
bitRAKE 02 Jul 2026, 01:55
Box3D v0.1.0 was released, and I wanted to play with it. So, here is fasm2 support and an example. The coding style follows the OpenGL example in fasm2 - no fancy stuff. There are some notes on using the library in relation to assembly; as well as instruction on how to build the libraries from the source repo. (Okay not to trust my binaries, or maybe you want double precision.)

Who doesn't want to blow up a digital pyramid?

_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.
Post 02 Jul 2026, 01:55
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4560
Location: vpcmpistri
bitRAKE 02 Jul 2026, 07:28
+ benchmark example, 10k cubes rubbing together, multi-threaded. Scaling is 5x at 8 threads. It also makes the determinism apparent -- multiple runs from the same initial conditions always reach the same state.

+ Instructions for producing a native build (+30%).
Post 02 Jul 2026, 07:28
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 2079
Roman 25 Jul 2026, 17:56
Respect ! Cool demos !

How you write box3D structs for fasm? Using some tools(notepad++ and python) or all write hands ?
Post 25 Jul 2026, 17:56
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4560
Location: vpcmpistri
bitRAKE 25 Jul 2026, 21:42
Roman wrote:
How you write box3D structs for fasm? Using some tools(notepad++ and python) or all write hands ?
100% AI. But the AI is writing scripts for LLVM tools to extract and validate the results - the AI is not directly converting the H-files. Then I have the AI build tests and examples to validate the final result as well. In this case the AI was GPT 5.6.

_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.
Post 25 Jul 2026, 21:42
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 2079
Roman 26 Jul 2026, 06:31
I am looking how did get all functions from dll file.
And create text all dll functions.

I found this fasm variant
https://github.com/RootDmytro/dll2inc

I do this example 32bits. In run.bat write your dll and get all functions import names !
Enjoy !
I tested only 32bits dll. Work fine.


Description:
Download
Filename: dll2inc.zip
Filesize: 20.47 KB
Downloaded: 29 Time(s)

Post 26 Jul 2026, 06:31
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4560
Location: vpcmpistri
bitRAKE 26 Jul 2026, 17:24
I like "dumpbin /EXPORTS" if I'm automating.
Post 26 Jul 2026, 17:24
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 1228
Location: Russia
macomics 26 Jul 2026, 19:10
Roman wrote:
I am looking how did get all functions from dll file.
And create text all dll functions.

I found this fasm variant
https://github.com/RootDmytro/dll2inc

I do this example 32bits. In run.bat write your dll and get all functions import names !
Enjoy !
I tested only 32bits dll. Work fine.
Here is my version of the same thing, but made purely on the basis of fasm as processor.
Post 26 Jul 2026, 19:10
View user's profile Send private message Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 2079
Roman 26 Jul 2026, 20:33
bitRAKE you implement b3MakeMatrixFromQuat for fasm ?
b3MakeMatrixFromQuat not exist in box3D.dll.

I looking fast avx variant convert quaternion to matrix3x3.
Post 26 Jul 2026, 20:33
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4560
Location: vpcmpistri
bitRAKE 27 Jul 2026, 03:22
Thanks for the bug report.
Code:
; b3MakeMatrixFromQuat dst_matrix_addr,q_addr
; Destination must not overlap q.
; The 36-byte result is emitted as two 16-byte stores and one scalar store.
; Clobbers: XMM0-XMM3, EAX
macro b3MakeMatrixFromQuat dst*,q*
        ; xmm0 = [x,y,z,w]. A b3Quat is exactly 16 bytes, so this load is bounded.
        movups xmm0,xword [q]

        ; [yy,xy,xz,xy] +/- [zz,zw,yw,zw]
        pshufd xmm1,xmm0,01h                   ; [y,x,x,x]
        pshufd xmm2,xmm0,65h                   ; [y,y,z,y]
        mulps xmm1,xmm2
        pshufd xmm2,xmm0,09Ah                  ; [z,z,y,z]
        pshufd xmm3,xmm0,0FEh                  ; [z,w,w,w]
        mulps xmm2,xmm3
        pcmpeqd xmm3,xmm3
        pslld xmm3,31
        pslldq xmm3,8                           ; negate lanes 2 and 3
        xorps xmm2,xmm3
        addps xmm1,xmm2
        addps xmm1,xmm1
        psrldq xmm3,12                          ; negate diagonal lane 0
        xorps xmm1,xmm3
        mov eax,3F800000h
        movd xmm3,eax
        addps xmm1,xmm3
        movups xword [dst],xmm1                 ; cx.xyz, cy.x

        ; [xx,yz,xz,yz] +/- [zz,xw,yw,xw]
        pshufd xmm1,xmm0,44h                   ; [x,y,x,y]
        pshufd xmm2,xmm0,0A8h                  ; [x,z,z,z]
        mulps xmm1,xmm2
        pshufd xmm2,xmm0,12h                   ; [z,x,y,x]
        pshufd xmm3,xmm0,0FEh                  ; [z,w,w,w]
        mulps xmm2,xmm3
        pcmpeqd xmm3,xmm3
        pslld xmm3,31
        pslldq xmm3,12                          ; negate lane 3
        xorps xmm2,xmm3
        addps xmm1,xmm2
        addps xmm1,xmm1
        psrldq xmm3,12                          ; negate diagonal lane 0
        xorps xmm1,xmm3
        movd xmm3,eax
        addps xmm1,xmm3
        movups xword [dst+16],xmm1              ; cy.yz, cz.xy

        ; cz.z = 1 - 2*(xx+yy)
        movaps xmm1,xmm0
        mulss xmm1,xmm0
        pshufd xmm2,xmm0,55h                   ; [y,y,y,y]
        mulss xmm2,xmm2
        addss xmm1,xmm2
        addss xmm1,xmm1
        movd xmm2,eax
        subss xmm2,xmm1
        movss dword [dst+32],xmm2
end macro    
Over 100 inline functions exist -- many of them seem obvious to me.
Post 27 Jul 2026, 03:22
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 2079
Roman 27 Jul 2026, 03:41
Last right ?
Quote:

; cz.z = 1 - 2*(xx+yy)
movaps xmm1,xmm0
mulss xmm1,xmm0
pshufd xmm2,xmm0,55h ; [y,y,y,y]
mulss xmm2,xmm2
addss xmm1,xmm2
addss xmm1,xmm1
movd xmm2,eax
subss xmm2,xmm1
movss dword [dst+32],xmm2

Why ? Why not movups xword [dst+32],xmm2 ?

Origin function Box3D
Code:
B3_FORCE_INLINE b3Matrix3 b3MakeMatrixFromQuat( b3Quat q )
{
        float xx = q.v.x * q.v.x;
        float yy = q.v.y * q.v.y;
        float zz = q.v.z * q.v.z;
        float xy = q.v.x * q.v.y;
        float xz = q.v.x * q.v.z;
        float xw = q.v.x * q.s;
        float yz = q.v.y * q.v.z;
        float yw = q.v.y * q.s;
        float zw = q.v.z * q.s;
;return 9 floats
        return ( b3Matrix3 ){
                { 1.0f - 2.0f * ( yy + zz ), 2.0f * ( xy + zw ), 2.0f * ( xz - yw ) },
                { 2.0f * ( xy - zw ), 1.0f - 2.0f * ( xx + zz ), 2.0f * ( yz + xw ) },
                { 2.0f * ( xz + yw ), 2.0f * ( yz - xw ), 1.0f - 2.0f * ( xx + yy ) },
        };
}    
Post 27 Jul 2026, 03:41
View user's profile Send private message Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 2079
Roman 27 Jul 2026, 07:01
Thanks BitRake. Now worked perfect ! I tested in directx11.
My variant for matrix4x4

Code:
SSE_quat2mat4:
 dst@rreg  equ edx
 ; xmm0 = [x,y,z,w]. A b3Quat is exactly 16 bytes, so this load is bounded.
        movups xmm0,xword [eax]

        ; [yy,xy,xz,xy] +/- [zz,zw,yw,zw]
        pshufd xmm1,xmm0,01h                   ; [y,x,x,x]
        pshufd xmm2,xmm0,65h                   ; [y,y,z,y]
        mulps xmm1,xmm2
        pshufd xmm2,xmm0,09Ah                  ; [z,z,y,z]
        pshufd xmm3,xmm0,0FEh                  ; [z,w,w,w]
        mulps xmm2,xmm3
        pcmpeqd xmm3,xmm3
        pslld xmm3,31
        pslldq xmm3,8                           ; negate lanes 2 and 3
        xorps xmm2,xmm3
        addps xmm1,xmm2
        addps xmm1,xmm1
        psrldq xmm3,12                          ; negate diagonal lane 0
        xorps xmm1,xmm3
        mov eax,3F800000h
        movd xmm3,eax
        addps xmm1,xmm3
        movups xword [dst@rreg],xmm1                 ; cx.xyz, cy.x
        ;convert mat4x4
        mov ecx,[dst@rreg+12]
        mov dword [dst@rreg+12],0
        mov [dst@rreg+16],ecx

        ; [xx,yz,xz,yz] +/- [zz,xw,yw,xw]
        pshufd xmm1,xmm0,44h                   ; [x,y,x,y]
        pshufd xmm2,xmm0,0A8h                  ; [x,z,z,z]
        mulps xmm1,xmm2
        pshufd xmm2,xmm0,12h                   ; [z,x,y,x]
        pshufd xmm3,xmm0,0FEh                  ; [z,w,w,w]
        mulps xmm2,xmm3
        pcmpeqd xmm3,xmm3
        pslld xmm3,31
        pslldq xmm3,12                          ; negate lane 3
        xorps xmm2,xmm3
        addps xmm1,xmm2
        addps xmm1,xmm1
        psrldq xmm3,12                          ; negate diagonal lane 0
        xorps xmm1,xmm3
        movd xmm3,eax
        addps xmm1,xmm3
        ;movups xword [dst@rreg+16],xmm1              ; cy.yz, cz.xy
        ;convert mat4x4
        movups xword [dst@rreg+20],xmm1
        mov ecx,[dst@rreg+20+12-4]
        mov ebx,[dst@rreg+20+12]
        mov [dst@rreg+32],ecx
        mov [dst@rreg+36],ebx
mov dword [dst@rreg+20+12-4],0

        ; cz.z = 1 - 2*(xx+yy)
        movaps xmm1,xmm0
        mulss xmm1,xmm0
        pshufd xmm2,xmm0,55h                   ; [y,y,y,y]
        mulss xmm2,xmm2
        addss xmm1,xmm2
        addss xmm1,xmm1
        movd xmm2,eax
        subss xmm2,xmm1
        movss dword [dst@rreg+32+8],xmm2
        ret     
Post 27 Jul 2026, 07:01
View user's profile Send private message Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 2079
Roman 29 Jul 2026, 12:01
BitRake how did you get vertices from BoxHull ?
I mean show box in opengl render the same size as BoxHull created Box3D
Post 29 Jul 2026, 12:01
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4560
Location: vpcmpistri
bitRAKE 29 Jul 2026, 16:38
The benchmark does not extract render vertices from `b3BoxHull`. It uses a shared unit-cube OpenGL mesh and makes it match the physics hull through per-instance scale and transform data.

The flow is:

1. One render mesh is created with corners from `-1` to `+1` on each axis in (benchmark.asm:127).

2. Physics boxes are created with half-extents:
Code:
b3MakeBoxHull cubeHull, 0.5, 0.5, 0.5    
`cHalf` is `0.5`, so the physical cube’s full dimensions are `1 × 1 × 1`. See (benchmark.asm:632) and [the constants](benchmark.asm:798).

3. Each render instance stores: position.xyz | quaternion.xyzw | halfExtents.xyz | color.rgb
The OpenGL attribute layout is configured in (benchmark.asm:366).

4. Initial position and rotation come from `b3BodyDef`. The benchmark generates the grid position and random rotation, then copies those values into the corresponding render-instance record before creating the body. The instance index is stored in `bdef.userData`. See (benchmark.asm:672) and (benchmark.asm:724).

5. After each simulation step, `b3World_GetBodyEvents` returns only the bodies that moved. Each event contains:
Code:
   userData
   transform.p
   transform.q    

`userData` selects the instance slot, and the new position/quaternion replace the first 28 bytes of that record. The half-extents and color remain unchanged. See (benchmark.asm:403).

6. The vertex shader constructs the final world-space vertex:
Code:
   world = bodyPosition + rotate(bodyQuaternion, unitCubeVertex * halfExtents);    

That is implemented directly in (benchmark_vs.glsl:15).

So the box does not change size during simulation. Box3D is moving and rotating a rigid hull; only its body transform changes.

For the benchmark cube:
Code:
unit render vertex:  (-1 .. +1)
half extents:         (0.5, 0.5, 0.5)
local rendered box:   (-0.5 .. +0.5)
physics hull:         (-0.5 .. +0.5)    

The ground uses exactly the same unit mesh, but its instance half-extents are `(100, 0.5, 100)`, matching its `b3MakeBoxHull` arguments. Its center is `(0, -0.5, 0)`, placing the upper face at `y = 0`.

If you genuinely want the vertices from `b3BoxHull`, the position data is not in `boxVertices`; those are topology records. Use the hull points:
Code:
b3BoxHull box = b3MakeBoxHull(hx, hy, hz);

const b3HullData* hull = &box.base;
const b3Vec3* points = b3GetHullPoints(hull);

for (int i = 0; i < hull->vertexCount; ++i)
{
    b3Vec3 localVertex = points[i];
}    


`b3GetHullPoints` resolves the embedded point array in (collision.h:145). To build triangles for an arbitrary hull, traverse its faces and half-edges; the repository renderer demonstrates that in (box3d\samples\gfx\debug_shapes.c:296). Transform each resulting local vertex using the body’s current position and quaternion.

_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.
Post 29 Jul 2026, 16:38
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 2079
Roman 29 Jul 2026, 17:00
Hm.
In b3HullData exist vertexOffset.
I thinked b3CreateCylinder created vertices and indices.
And my idea was get vertices and indices and create Directx 11 mesh for render.

I looking and not see vertex data and indices data. Only points
Code:
b3HullData* b3CreateCylinder( float height, float radius, float yOffset, int sides )
{
        B3_ASSERT( height > 0.0f );
        B3_ASSERT( radius > 0.0f );
        B3_ASSERT( 3 <= sides && sides <= 32 );

        int pointCount = 2 * sides;
        b3Vec3* points = (b3Vec3*)b3Alloc( pointCount * sizeof( b3Vec3 ) );
        B3_ASSERT( points != NULL );

        float alpha = 0.0f;
        float deltaAlpha = 2.0f * B3_PI / sides;

        for ( int index = 0; index < sides; ++index )
        {
                float sinAlpha = b3Sin( alpha );
                float cosAlpha = b3Cos( alpha );

                points[2 * index + 0] = (b3Vec3){ radius * cosAlpha, yOffset, radius * sinAlpha };
                points[2 * index + 1] = (b3Vec3){ radius * cosAlpha, yOffset + height, radius * sinAlpha };

                alpha += deltaAlpha;
        }

        b3HullData* hull = b3CreateHull( points, pointCount, pointCount );
        B3_ASSERT( hull->vertexCount == pointCount );
        B3_ASSERT( hull->edgeCount == 6 * sides );
        B3_ASSERT( hull->faceCount == sides + 2 );

        b3Free( points, pointCount * sizeof( b3Vec3 ) );

        return hull;
}       
Post 29 Jul 2026, 17:00
View user's profile Send private message Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 2079
Roman 30 Jul 2026, 06:14
For my cylinder (height=3.5, radius=5, yOffset = 0 , sides=6) b3CreateCylinder created 12 points.
How i understood 6 points top cylinder and 6 points bottom cylinder.
But i get points shuffled !
Image

How generated triangles indices for cylinder ?


Last edited by Roman on 30 Jul 2026, 08:13; edited 3 times in total
Post 30 Jul 2026, 06:14
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4560
Location: vpcmpistri
bitRAKE 30 Jul 2026, 06:57
You can make triangles or quads. For triangles, it's just two points from the top and one point from the bottom; then one point from the top and two points from the bottom -- all the way around the circles.

_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.
Post 30 Jul 2026, 06:57
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 2079
Roman 30 Jul 2026, 07:56
I found Frank Luna cylinder.
http://richardssoftware.net/Home/Post/7
Code:
void GeometryGenerator::CreateCylinder(float bottomRadius, float topRadius, float height, UINT sliceCount, UINT
stackCount, MeshData& meshData)
{
meshData.Vertices.clear();
meshData.Indices.clear();
//
// Build Stacks.
//
float stackHeight = height / stackCount;
// Amount to increment radius as we move up each stack
// level from bottom to top.
float radiusStep = (topRadius - bottomRadius) / stackCount;
UINT ringCount = stackCount+1;
// Compute vertices for each stack ring starting at
// the bottom and moving up.
for(UINT i = 0; i < ringCount; ++i)
{
float y = -0.5f*height + i*stackHeight;
float r = bottomRadius + i*radiusStep;
// vertices of ring
float dTheta = 2.0f*XM_PI/sliceCount;
for(UINT j = 0; j <= sliceCount; ++j)
{
Vertex vertex;
float c = cosf(j*dTheta);
float s = sinf(j*dTheta);
vertex.Position = XMFLOAT3(r*c, y, r*s);
vertex.TexC.x = (float)j/sliceCount;
vertex.TexC.y = 1.0f - (float)i/stackCount;
// Cylinder can be parameterized as follows, where we
// introduce v parameter that goes in the same direction
// as the v tex-coord so that the bitangent goes in the
// same direction as the v tex-coord.
// Let r0 be the bottom radius and let r1 be the
// top radius.
// y(v) = h - hv for v in [0,1].
// r(v) = r1 + (r0-r1)v
//
// x(t, v) = r(v)*cos(t)
// y(t, v) = h - hv
// z(t, v) = r(v)*sin(t)
//
// dx/dt = -r(v)*sin(t)
// dy/dt = 0
// dz/dt = +r(v)*cos(t)
//
// dx/dv = (r0-r1)*cos(t)
// dy/dv = -h
// dz/dv = (r0-r1)*sin(t)
// TangentU us unit length.
vertex.TangentU = XMFLOAT3(-s, 0.0f, c);
float dr = bottomRadius-topRadius;
XMFLOAT3 bitangent(dr*c, -height, dr*s);
XMVECTOR T = XMLoadFloat3(&vertex.TangentU);
XMVECTOR B = XMLoadFloat3(&bitangent);
XMVECTOR N = XMVector3Normalize(XMVector3Cross(T, B));
XMStoreFloat3(&vertex.Normal, N);
meshData.Vertices.push_back(vertex);
}
}



// Add one because we duplicate the first and last vertex per ring
// since the texture coordinates are different.
UINT ringVertexCount = sliceCount+1;
// Compute indices for each stack.
for(UINT i = 0; i < stackCount; ++i)
{
for(UINT j = 0; j < sliceCount; ++j)
{
meshData.Indices.push_back(i*ringVertexCount + j);
meshData.Indices.push_back((i+1)*ringVertexCount + j);
meshData.Indices.push_back((i+1)*ringVertexCount + j+1);
meshData.Indices.push_back(i*ringVertexCount + j);
meshData.Indices.push_back((i+1)*ringVertexCount + j+1);
meshData.Indices.push_back(i*ringVertexCount + j+1);
}
}
BuildCylinderTopCap(bottomRadius, topRadius,
height, sliceCount, stackCount, meshData);
BuildCylinderBottomCap(bottomRadius, topRadius,
height, sliceCount, stackCount, meshData);
}

void GeometryGenerator::BuildCylinderTopCap(float bottomRadius,
float topRadius, float height, UINT sliceCount,
UINT stackCount, MeshData& meshData)
{
UINT baseIndex = (UINT)meshData.Vertices.size();
float y = 0.5f*height;
float dTheta = 2.0f*XM_PI/sliceCount;
// Duplicate cap ring vertices because the texture coordinates
// and normals differ.
for(UINT i = 0; i <= sliceCount; ++i)
{
float x = topRadius*cosf(i*dTheta);
float z = topRadius*sinf(i*dTheta);
// Scale down by the height to try and make top cap
// texture coord area proportional to base.
float u = x/height + 0.5f;
float v = z/height + 0.5f;
meshData.Vertices.push_back(
Vertex(x, y, z,
0.0f, 1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
u, v));
}
// Cap center vertex.
meshData.Vertices.push_back(
Vertex(0.0f, y, 0.0f,
0.0f, 1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.5f, 0.5f));
// Index of center vertex.
UINT centerIndex = (UINT)meshData.Vertices.size()-1;
for(UINT i = 0; i < sliceCount; ++i)
{
meshData.Indices.push_back(centerIndex);
meshData.Indices.push_back(baseIndex + i+1);
meshData.Indices.push_back(baseIndex + i);
}
}

    


Last edited by Roman on 31 Jul 2026, 07:57; edited 1 time in total
Post 30 Jul 2026, 07:56
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4560
Location: vpcmpistri
bitRAKE 30 Jul 2026, 08:18
Here's a parametric shape generator. The AI was too extra: 10 base shapes, 7 exporters, 3D display, normals/UV/indexing machinery -- I didn't ask for all that.


Description: parametric shape generator, HTML/JS
Download
Filename: triangles.7z
Filesize: 13.11 KB
Downloaded: 23 Time(s)


_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.
Post 30 Jul 2026, 08:18
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 2079
Roman 30 Jul 2026, 17:35
cool , but I writed my fasm code.

Code:
myVrtx_Stride  = 32  ;my mesh have pos.xyz,TextureUV.xy,Normals.xyz = 32 bytes one vertex

macro msseSin t {
 movss [FourRadians],xmm0
 addss xmm0,[pfl0@@_5]
 movss [FourRadians+4],xmm0     ;cos
 call sse@Sin
}

;u = x/height + 0.5f;
;v = z/height + 0.5f;
macro mgen@UVs t {   ;for Cap top & bottom
                     movss xmm0,[t-32]
                     divss xmm0,[edi]         ;height
                     addss xmm0,[pf@@@05]
                     movss dword [t-20],xmm0

                     movss xmm0,[t-32+8]
                     divss xmm0,[edi]         ;height
                     addss xmm0,[pf@@@05]
                     movss dword [t-16],xmm0
      }
macro mgen@XYUVs t {   ;for cylindr tube
                     movss xmm0,[t-32]
                     divss xmm0,[edi]         ;height
                     addss xmm0,[pf@@@05]
                     mulss xmm0,[pf@@@05+4]
                     movss dword [t-20],xmm0

                     movss xmm0,[t-32+8-4]
                     divss xmm0,[edi]         ;height
                     addss xmm0,[pf@@@05]
                     mulss xmm0,[pf@@@05+4]
                     movss dword [t-16],xmm0
      }                               

macro pushFirstVrtxNul to,stride  {
 mov dword [to],0
 movss xmm0,[edi+4]     ;get ofstY
 movss dword [to+4],xmm0
 mov dword [to+8],0
 add to,stride
}

macro push2Bufer b,stride,x1,x2,x3 {
   movss dword [b],x1
   movss dword [b+4],x2
   movss dword [b+8],x3
   add   b,stride
}
;for( DWORD i = 0; i < Sides; i++ ) {
;   FLOAT theta = ( 2 * D3DX_PI * i ) / Sides;
;
;    pVertices[2 * i + 0].position = D3DXVECTOR3(radius*sinf( theta ), ofstY, radius*cosf( theta ) );
;    pVertices[2 * i + 0].color = 0xffffffff;
;    pVertices[2 * i + 0].tu = ( ( FLOAT )i ) / ( Sides - 1 );
;    pVertices[2 * i + 0].tv = 1.0f;

;    pVertices[2 * i + 1].position = D3DXVECTOR3( radius*sinf( theta ), ofstY+height, radius*cosf( theta ) );
;    pVertices[2 * i + 1].color = 0xff808080;
;    pVertices[2 * i + 1].tu = ( ( FLOAT )i ) / ( Sides - 1 );
;    pVertices[2 * i + 1].tv = 0.0f; } 

;edi=params.  eax=out buffer for mesh cylinder
gen@@Cylinder: 
        mov edx,[edi+12]        ;get sides
        movss xmm6,[edi+4]      ;get ofsetY
        cvtsi2ss xmm7,edx
        
        xor ecx,ecx
       
        pushFirstVrtxNul eax,myVrtx_Stride
        mgen@UVs eax
.up1:   cvtsi2ss xmm0,ecx
        mulss xmm0,[double_PI]

        divss xmm0,xmm7

        msseSin   p@@theta
        movss xmm2,[edi+8]      ;get radius
        movss xmm3,xmm2
        mulss xmm2,[Sin1234]  ;[angl@@sin]

        mulss xmm3,[Sin1234+4];[angl@@cos]
        push2Bufer eax,myVrtx_Stride,xmm3,xmm6,xmm2
        mgen@UVs eax

        inc ecx
        cmp ecx,[edi+12]        ;get sides
        jb .up1

;gen indxs for Cap top and Cap bottom
        movd xmm3,esi            ;as push
        movd xmm4,ebp

        mov ebp,[edi+12]        ;get sides
        dec ebp
        xor esi,esi
        mov edx,[gen@@Cylinder.indxsBufr] ;mymymyIndxxss
        mov ecx,[gen@@Cylinder.f1]
        mov ebx,[gen@@Cylinder.f2]
.upp:   inc ecx
        inc ebx
        inc esi
        movss xmm0,[gen@@Cylinder.f3]
        movss dword [edx],xmm0
        mov dword [edx+4],ecx
        mov dword [edx+8],ebx
        add edx,12
        cmp esi,ebp
        jb  .upp
        movss xmm0,[gen@@Cylinder.f3]
        movss dword [edx],xmm0
        mov dword [edx+4],ebx
        mov esi,[gen@@Cylinder.f3]
        inc esi
        mov dword [edx+8],esi
        add edx,12
        add ecx,2
        add ebx,2
        mov [gen@@Cylinder.f1],ecx
        mov [gen@@Cylinder.f2],ebx
        mov ebp,[edi+12]
        inc ebp
        mov [gen@@Cylinder.f3],ebp
        mov [gen@@Cylinder.indxsBufr],edx
        movd esi,xmm3
        movd ebp,xmm4
        ret

        gen@@Cylinder.indxsBufr  dd myIndxs
        gen@@Cylinder.f1         dd 0
        gen@@Cylinder.f2         dd 1
        gen@@Cylinder.f3         dd 0

        double_PI dd 6.28318530718
        pf@@@05   dd 0.5

        Scal@TubeNiz    dd 1.0
        
        pfl0@@_5  dd 1.5708      ;cos
        p@@theta  dd 0          

sse@Sin:
movaps      xmm0,dqword [FourRadians]
    mulps       xmm0,dqword [OneDivPi]      ; 1/pi to get a 1pi range
    cvtps2dq    xmm3,xmm0                   ; (4 packed spfp to 4 packed int32) lose the fractional parts and keep it in xmm3 to save the signs 
    cvtdq2ps    xmm1,xmm3                   ; (4 packed int32 to 4 packed spfp) save the  integral parts 
    subps       xmm0,xmm1                   ; now it's inside the range, results are values between -0.5 to 0.4999999 
    pslld       xmm3,31                     ; put sign-bits in position, to place values in the right hemispheres 
    xorps       xmm0,xmm3                   ; set sign-bits 
    mulps       xmm0,dqword [Pi]            ; restore ranges between -1/2 pi to +1/2 pi

; Now do the Chebyshev approximation of a 9th degree polynomial 
; With 4 optimized constants for a maximum error of about 3.3381e-9 over -1/2 pi to +1/2 pi 

    movaps      xmm2,xmm0 
    mulps       xmm2,xmm2 

    movaps      xmm1,dqword [ChebyChf43]
    mulps       xmm1,xmm2 
    addps       xmm1,dqword [ChebyChf42]
    mulps       xmm1,xmm2 
    addps       xmm1,dqword [ChebyChf41]
    mulps       xmm1,xmm2 
    addps       xmm1,dqword [ChebyChf40]
    mulps       xmm2,xmm0 
    mulps       xmm1,xmm2 
    addps       xmm0,xmm1
    movaps      dqword [Sin1234],xmm0
    ret

     align 16
     OneDivPi    dd 4 dup (0.3183098861837)
     Pi          dd 4 dup (3.1415926535897)
     ChebyChf40  dd 4 dup (-0.1666665709650) 
     ChebyChf41  dd 4 dup (0.0083330172915) 
     ChebyChf42  dd 4 dup (-0.0001980661520)
     ChebyChf43  dd 4 dup (0.0000026000547) 
     FourRadians dd  0.174532925,1.570796325,0.0174532925,1.570796325 ;four numbers radian
     Sin1234 dd 0,0,0,0 ;result four sinus

macro mtubeNorm {
        movss xmm0,[Sin1234]
        movss [eax-4],xmm0
        movss xmm0,[Sin1234+4]
        movss [eax-12],xmm0
}

Gen@@Tube:      movd xmm4,eax
        mov edx,[edi+12]        ;get sides
        movss xmm6,[edi+4]      ;get ofsetY
        cvtsi2ss xmm7,edx
        xor ecx,ecx
.up1:   cvtsi2ss xmm0,ecx
        mulss xmm0,[double_PI]

        ;mulss xmm0,xmm7        ;s rcpss
        divss xmm0,xmm7

        ;movss [p@@theta],xmm0
        ;fpu@SinCos  p@@theta
        msseSin
        movss xmm2,[edi+8]      ;get radius
        movss xmm3,xmm2
        mulss xmm2,[Sin1234]  ;[angl@@sin]
        ;mulss xmm2,[minflt@@1]              ;++
        ;mulss xmm3,[minflt@@1]              ;++
        mulss xmm3,[Sin1234+4];[angl@@cos]
        push2Bufer eax,myVrtx_Stride,xmm3,xmm6,xmm2    ;vrtxTop
        mgen@XYUVs eax
        mtubeNorm
mulss xmm2,[Scal@TubeNiz]
mulss xmm3,[Scal@TubeNiz]
        xorps xmm5,xmm5
        subss xmm5,xmm6
        push2Bufer eax,myVrtx_Stride,xmm3,xmm5,xmm2    ;vrtxNiz
        mgen@XYUVs eax
        mtubeNorm

        inc ecx
        cmp ecx,[edi+12]        ;get sides
        jb .up1

;copy 64 bytes vrtx to last
movd edx,xmm4
rept 4 {
movups xmm0,xword [edx]
movups xword [eax],xmm0
add edx,16
add eax,16
}


;gen tube indxs
        mov edx,[gen@@Cylinder.indxsBufr]  ;get position in indxData
        mov ecx,[edi+12]
        dec ecx
        add ecx,ecx
        mov  ebx,[gen@@Cylinder.f3]
        add  ebx,ebx
        

.up2:   mov [edx],ebx
        inc ebx
        mov   [edx+4],ebx
        inc ebx
        mov   [edx+8],ebx
        mov  ebp,ebx
        dec ebp
        mov [edx+12],ebp
        mov   [edx+16],ebx
        inc ebx
        mov   [edx+20],ebx
        ;inc ebx
        add edx,12*2

.up2b:
        mov  ebp,ebx
        dec ebp
        mov [edx],ebp
        mov   [edx+4],ebx
        inc ebx
        mov   [edx+8],ebx
        ;inc ebx
        add edx,12

        dec ecx
        jnz .up2b
        shr ebx,1
        inc ebx
        mov  [gen@@Cylinder.f3],ebx
        mov [gen@@Cylinder.indxsBufr],edx
        ret

              

    


Last edited by Roman on 02 Aug 2026, 15:59; edited 13 times in total
Post 30 Jul 2026, 17:35
View user's profile Send private message Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 2079
Roman 30 Jul 2026, 17:39
Using
Code:
zzCylindrSize   dd 2.0,1.0,2.0,6  ;height,ofstY,radius,sides int
myVrtxs         dd 200 dup(0)     ;vertx buffer

;myIndxs dd 0,1,2, 0,2,3, 0,3,4,  0,4,5, 0,5,6 , 0,6,1  ;cap top 6 triangles. Not gen. i am writed
 ;       dd 7,8,9, 7,9,10, 7,10,11,  7,11,12, 7,12,13 , 7,13,8  ;cap bottom 6 triangles

myIndxs dd 800 dup(0)

        mov eax,myVrtxs         ;out vertices to eax
        mov edi,zzCylindrSize
        call gen@@Cylinder      ;gen top cap. All normals = 0,1f,0
                                ;my vertex stride 32 bytes Pos.xyz,UV.xy,Normal.xyz
        movss xmm0,[edi]        ;get Height
        addss xmm0,[edi+4]      ;Height+ofstY
        movss [edi+4],xmm0
;if want change radius bottom cap and get cone !
rept 1 { mov ecx,0.4
movd xmm0,ecx
mulss xmm0,[edi+8]
movss [edi+8],xmm0  ;radius*0.4  
}
        call gen@@Cylinder      ;generated bottom cap. All normals = 0,-1f,0
        call Gen@@Tube           ;if we want cylinder

;get num vertices
sub eax,myVrtxs
shr eax,5  ;/32 my stride 32

;get bytes idices
sub edx,myIndxs

;get num idices
shr edx,2     ;because one indx=4bytes

;if sides=4 we get boxe ! gen@@Cylinder can get 5 type meshes(boxe,pyramid,cone,cylinder, one cap as flat circle)

;We can generated one cap top and set central point +0,10.0,0 and get cone or pyramid(sides=4) !
    


I created two caps as cone and get mushroom.
Image
Image
Image


Last edited by Roman on 01 Aug 2026, 13:57; edited 3 times in total
Post 30 Jul 2026, 17:39
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2026, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.