Cyberjaya, Malaysia ยท open to remote
I build AI systems
and the 3D worlds
they run in.
AI full stack developer with years of visual craft behind it. I ship the whole thing โ the model calls, the database, the browser, and the geometry on screen.
Cadastral lots mapped
Python ETL over PLANMalaysia + OpenStreetMap, rendered in one browser tab.
Projects on this page
Web apps, developer tools, games, 3D work and one handheld console โ built, not tutorialed.
Sports simulated
Badminton, tennis, table tennis, sepak takraw and both volleyballs โ one physics spine, in Referee For Fun.
npm dependencies
Claude Chat runs on Node's built-in modules alone. No framework, nothing to patch.
Work
Thirty-seven projects across code, games, 3D and hardware. Filter by what you came for.

bengkel
CodingA bengkel is a workshop — the room where the tools are kept and the work is done. This one is the front door to seven of them, and the rail down its side is a pipeline in the order the work happens: find it, make it, clean it up, dress it, check it, move it, ship it. It carries no engine of its own — the bundle holds a studio page, a tool list and one Swift file, and runs each tool from where that tool already lives on disk, so a change to any of them is live the next time it starts. pasar searches Sketchfab, Poly Haven and Texturelabs from one box, reimplementing none of them: the three command-line tools already on the machine are loaded as modules and their functions called, so there is one description of how to talk to Sketchfab rather than two that drift. The licence is on every card before the download, anything that cannot be sold is flagged, and every file arrives with a note of its source, author and licence beside it — six months later that note is the only thing that still knows. jaring asks the one question every other remesher gets wrong: not “how many faces do you want”, which nobody knows, but how wide one quad should be in centimetres, which is a thing you can picture. The face count follows from the model’s own surface area and is shown as the slider moves; one press then welds, remeshes, unwraps, bakes a normal map off the original and builds LODs through a headless Blender, and a downloaded paladin came back from 12,332 to 2,632 triangles — same size, same place, still recognisably a paladin. It refuses four failures that raise nothing. A glTF has no shared vertices, so a model that has been through one arrives as loose triangles that merely touch and is never closed — a sphere exported and re-imported comes back with 32,512 non-manifold edges — and without welding first, the quad remesher is never once given a surface it can work on. Blender’s Quadriflow then lies twice: it cancels rather than raising, and on a mesh it could not handle it reports success and hands back shards at a different size, which every other check passes. So the result is measured against what went in — a remesh of a thing is the same size as the thing — and anything else is done again another way. A bake is never wired to read the image it is writing; each LOD gets its own file, because three inside one are not alternatives but three copies standing inside one another; and when a result comes out heavier than it went in, it says so rather than reporting “−2% lighter”. periksa is the last look before a model goes into a game, and it reads the file rather than opening it — a .glb carries its own table of contents, so the size, the origin, the weight and the UVs are all answerable in milliseconds instead of the thirty seconds a Blender launch costs, which is the difference between a thing you run on every model and a thing you run when you already suspect something. It refuses to grade: a 400,000 triangle model is right for a cinematic and hopeless for a crowd, so it asks what the thing is for and the same model passes as a hero and fails as scenery, with every finding carrying what it found, why it matters and what to do. hantar is the last mile into one of the twelve game projects, and the only tool that writes outside the workshop — so it writes nowhere else, and the guard is in the server rather than the page. It invents no layout: for each game it finds where that project already keeps its models and how those files are already spelled, so the same typed name becomes walker_walk.glb in one project and walker-walk.glb in another, because a tool that imposes its own convention on twelve existing projects makes work rather than saving it. It stands the model on the floor, scales it to a real height, and exports for Godot or for Unreal, which counts in centimetres. The three were checked against each other rather than one at a time: periksa said a model’s origin was not on the ground, hantar moved it and sized it, and periksa then passed it. A tool’s server starts the first time you open that tool and stops when the window closes; not at launch, because one of them keeps a headless Blender running. The servers never speak to each other: a window.bengkel object is injected into every page and everything crosses through the native side, and because each tool checks whether that object exists and carries on exactly as before when it does not, all seven still run perfectly well alone. What the tools share — the token and origin guards, the model library, the way to call Blender, the look — lives in one place, so a fifth tool is a page and about a hundred lines.

Siti Sihat
CodingSix habits that usually mean six apps, in one page on a phone: a water tracker, a sugar budget, three guided exercise routines and a menstrual calendar. Nothing leaves the device — one localStorage key, no account, no server, no analytics, and a check in the test suite that fails if any request goes anywhere but the two font hosts. The three routines share one player: a countdown ring, spoken cues through the browser’s own speech engine, beeps synthesised on the fly rather than shipped as files, rest steps between moves, and a wake lock so the screen stays on mid-plank. The cycle tracker predicts from the user’s own history rather than a textbook 28 days — it averages the last six gaps, throws out anything outside 15–60 days as a mis-log, and counts ovulation backwards from the predicted start, because the luteal phase is the stable half of a cycle and the follicular half is what varies. The part that took the most thought was what not to promise: a thigh gap is pelvis width and bone position, and no adductor work creates one; belly fat cannot be spot-reduced, because crunches build the muscle under the fat rather than removing the fat above it. Both routines are still there and still worth doing — each one just says so on its own screen, above the Start button. Plain HTML, CSS and ES modules: no framework, no build step, no dependencies, installable to the home screen and working offline. Verified by a self-driving harness that starts a server, drives headless Chrome over the DevTools protocol and fails on any console error — 23 checks green, though the three defects that actually mattered were caught by looking at the screenshots it takes, not by the checks.

gerak
CodingA Mac app for animating the 3D models already on one machine — its own window, its own menu bar, a Dock icon, and a server it starts and stops itself. It scans the machine and finds 3,442 of them — reading each .glb’s JSON header rather than the whole file, so a full sweep takes 1.2 seconds — and reports that only 312 carry a skeleton. Open one of those, click any joint, turn it, and press a key; a timeline works out every frame in between. The other 3,130 get a skeleton first: drop a ready-made one on the model — human, four-legged animal, bird, fish, or a plain chain for a snake or a rope — written in the model’s own bounding-box coordinates so the same numbers fit a chess piece and a two-metre character, nudge the joints, and headless Blender weights the skin to them and counts whatever no bone reached rather than hiding it. Each arm and leg switches between FK, turning one joint at a time, and IK, dragging a handle and letting the shoulder and elbow be worked out — solved exactly rather than iteratively, by the law of cosines, so a hand lands 1×10−7 from where it was put and a pinned foot slips 1×10−8 while the body tilts above it. The IK is only a way of posing: what gets keyed and exported is plain bone rotations, because a .glb carrying constraints is quietly stripped of them by Godot and by Unreal. Out come .glb, .fbx, .blend and a rendered video. The application around all of it is one Swift file and a shell script — no Xcode project, because an app bundle is a folder with an Info.plist in it and swiftc comes with the command line tools. Drop a model on the window or open one from Finder; the path is caught in AppKit, because JavaScript is handed a dropped file’s contents but never its path. Nothing is installed and nothing is hosted: the Python that ships with macOS, a copy of three.js in the folder, and the Blender already there. And because animating from memory is how a walk comes out looking like somebody wading, there is a reference panel: it searches Wikimedia Commons and puts Eadweard Muybridge’s motion studies first — people and animals photographed frame by frame in the 1880s to settle what a galloping horse really does with its legs, long out of copyright, and many already assembled into animated GIFs. A GIF is a sequence already, so pinning one pulls it apart into frames and the timeline steps it proportionally: a twelve-frame Muybridge walk against a forty-eight-frame clip advances one reference frame every four, so frame 24 sits beside reference frame 6 whatever length either is. The picture floats over the viewport, draggable and fadeable, and is copied to disk and saved with the clip — a reference that lives at a URL is gone when the link rots. The page never talks to Commons: the server fetches the picture and serves it, so nothing on screen breaks the origin rule and Commons never learns what is being animated. A character is rarely one animation, so the app holds them all: a footballer in one of the games carries fifty-three in a single file and an athlete in another carries twelve, each played by name from the game’s own scripts, and any of them can be opened on the timeline, re-posed and put down again with its edits intact. Two that ought to be the same thing — two runs for two different occasions — can be merged into one, keeping whichever motion is chosen; before it deletes the other name it searches the game’s scripts and scenes for it and lists every line that says it, because a Godot script asking an AnimationPlayer for a name that has stopped existing is a runtime error in a game that worked an hour ago. Then one button puts the result back into the file the game actually loads. It does that by editing the .glb’s own glTF JSON and binary buffer in place rather than re-exporting it through Blender, because a round trip rebuilds the materials and can move the vertex order — a great deal of collateral change to a live game asset for the sake of one animation. Only the animations that were edited are rewritten; the rest are never even decoded, so they keep their original curves down to their interpolation, and the mesh, the skin, the materials and the node tree come out byte for byte. The suite proves that accessor by accessor after eleven consecutive rewrites, with the file the same size every time — the orphaned accessors are collected and the buffer repacked, or a file pushed to ten times would be mostly the animations it no longer has. The keys are thinned against a linear sampler at about a ninth of a degree on the way out, taking one athlete from 1,509 keys to 314 without changing the motion, and a copy of the file as it was goes into a backups folder first, every single time.

boneka
CodingType “a tall blue knight with a sword” and watch Blender build it in the browser, part by part, as it is being made — then press one button for a skeleton and type “walk slowly” to make it move. A knight is not a blue person: each kind of character has a kit of named pieces — breastplate, pauldrons, gauntlets, belt, tassets, greaves, boots, helmet, crest — and they go on one at a time, in that order, each fitted to the body underneath and tied to the bone it moves with, so the pauldron turns with the shoulder without anything extra. Three more things keep it from looking like stacked boxes. Every part is a lofted stack of cross-sections rather than a primitive — a torso wide at the shoulders, narrowing at the waist and widening again at the hips; an arm as a shoulder ring, a bicep swell, an elbow and a wrist — because a box with its corners filed off is still a box. Those sections are measured: the eight-head canon for the vertical landmarks, anthropometry for the widths (biacromial breadth is 0.234 of height, so the skeletal shoulder is narrower than the finished figure and the deltoids make up the difference), breed standards for the dog, real dimensions for the chicken. And the app pulls photographs of whatever you asked for alongside the viewport so you can judge one against the other. Then a sculpt pass voxel-remeshes the soft parts into one continuous skin, so the seam where an arm meets a shoulder stops being a seam, while crates and machines stay crisp on purpose. Every part is then given a surface by what it is made of — metal on armour, wood on a crate, cloth on a robe — multiplied over its colour rather than replacing it, from a free texture library read through its own licence first. Name a palette — one of ten built-in moods, or any of the thousands on Lospec — and the whole model is snapped onto it in Oklab, by an ordered assignment that keeps every colour distinct and the shading the right way up. The one-press rig survives that: vertex weights are painted on before the remesh and transferred back after, so the skeleton is still placed from the recipe rather than guessed at a cloud of triangles. Nineteen moves, each written separately for people, four-legged animals, birds and objects; motion capture clips can be dropped in and retargeted. System Python driving one long-running headless Blender, three.js in the page, 779 checks against the real thing.

Auxetic Chess
CodingA chess variant where the board is a mechanism. After every move all sixteen 2×2 blocks turn a quarter and carry the pieces round with them — a1→a2→b2→b1, and because it is a permutation of four squares it can never capture. Everything is carried, pawns included — a pawn on a4 turns to b4 — but a pawn’s own moves stay forward only, never sideways or backwards, wherever the board puts it. The rule is deterministic, so the twist runs inside the engine’s own make/unmake and the search plays the variant properly instead of playing normal chess into a scrambling board. It stands down on any turn that would expose your own king, which is what keeps the game from deadlocking rather than drawing on move three. Each side also gets three stops: press one and the board holds still for your move and the reply. A stop is part of the move itself, so the engine plans with them too, pricing an unused stop at a pawn. The engine underneath matches all 26 published perft reference counts, including 4,865,609 nodes at depth 5. Play it against that engine at four strengths, each with its own leaderboard of wins kept in the browser — a game where Undo was used is not ranked — or two-up at one keyboard.

Peta Lot Tanah
CodingEvery cadastral land lot within 5 km of a point in Klang, Selangor โ 64,770 of them. A Python pipeline pulls lots from PLANMalaysia iPLAN and buildings from OpenStreetMap, joins them and bakes one data file. Colours lots by built-vs-empty, by size, and by JUPEM area code.

Print Quote
CodingDrag an STL into the browser and get a printing price. The page parses the triangle mesh itself โ no server, no upload โ works out solid volume, shell and infill, converts that to grams and hours, then prices it against filament cost, machine rate and margin.

Claude Chat
CodingA WhatsApp-style web app that drives an AI coding agent running on my Mac at home. Each chat on the phone is a real terminal session over a private Tailscale network. Node with built-in modules only โ no dependencies, no framework.
Pipeline
CodingA Blender add-on that batch-exports a scene to Unreal with the naming, unit scale, pivots and collision meshes Unreal expects. Four export modes, FBX and glTF. Its tests run Blender headless and re-import the FBX to measure that the pivot, rotation and scale survived the round trip.

Cerdik โ tuition platform
CodingA learning platform for a tuition centre: students open materials and track progress, parents see attendance and fees, the centre sees enrolment and revenue. Built as a working demo to answer a client brief rather than claim past work.
Siti โ voice assistant
CodingA hands-free AI assistant for the drive to work. Open a page on the phone, tap once, and it listens, answers aloud and listens again. It knows my project notes, can save new facts to a vector store, and searches the web.
Line Call
The shuttle lands. You have a second and a half to decide. No call counts against you โ same as the real thing.
Line Call
PlayableA one-rule slice of Referee For Fun: the engine knows exactly where the shuttle touched down, to the millimetre, and you don't. In the full game you can bend the call in a team's favour and see how long the crowd tolerates it. Here, just get it right.

Referee For Fun
Game DevA first-person game where you are the umpire, not the athlete. The match is physically simulated in front of you and the engine always knows the truth โ so you can bend every close call, limited only by how much suspicion the crowd tolerates. Six sports share one official and one reputation, and two TV commentators who remember your whole career. In badminton the night is shot like a broadcast: the umpire leads the players on and tosses the coin, the players shake hands at the end, and a removed umpire is walked off court. Every sport's on-screen score is laid out like its own television broadcast โ BWF, FIVB, the tennis tours, WTT โ and every venue is dressed like a real Malaysian event, from an indoor Kuala Lumpur tennis stadium to a beach volleyball court at Pantai Cenang, with sponsor boards, TV cameras, courtside crew and flags in the crowd. Sepak takraw is refereed to ISTAF’s 2024 rules, down to the tekong’s standing foot in the service circle.

Red Card
Game DevA first-person football game where you are the referee, on foot, for a full 11-a-side match the engine simulates for real. Look down and see your own boots; decide with a whistle and your pointing arm; show the card to the player you are looking at. Every tackle, offside position and ball over the line is recorded as it happens and judged against the IFAB Laws of the Game, and an assessor marks you out of ten with replays from your own eyes. Both captains meet you for the toss before a ball is kicked; players who disagree come and tell you so, and waving them away is marked as carefully as the decision itself. A career climbs from a village rec with club linesmen to a floodlit final with VAR, and the report ends with a map of the pitch showing where you were standing for every call you made, and what you could see from there. Every training drill is checked both ways โ the right call must pass, doing nothing must fail.

Bluff Show
Game DevA Fibbage-style bluffing party game for 3–10 players, dressed as a 1970s television quiz show. Each round shows a strange-but-true fact with the key word blanked out; everyone writes a convincing fake, the fakes are shuffled in with the truth, and you score for finding the real answer and for how many people your lie caught. Two ways to play: pass one device around the room, or put the board on a TV and let phones join with a four-letter code. A Phaser effects layer sits over the HTML — TRUTH and LIE stamps, score rings, a drum roll and a sax sting on the reveal — while the writing and picking stay ordinary DOM, because a text box is the one thing a game engine does worse than a browser.

Out Loud
CodingA Japanese class that runs in a browser tab and refuses to move on until you have said the phrase out loud. The teacher speaks first through a Japanese voice already installed in macOS, then the microphone opens, Chrome turns what you said into Japanese text, and the app marks it against what it asked for. Every lesson drills its phrases and then makes you use them in a scene where the teacher plays the other person. Built because Luqman wanted to learn by speaking rather than by tapping — and built to cost nothing: no API key, no account, no server, 47 passing checks on the marking alone.

Codebot
Game DevA Roblox game where you learn Luau by writing it. There is no joystick — your code is the controller, and typing move() walks the robot one tile. Eight rooms are ordered so each introduces exactly one new idea, other players solve the same room beside you with their robots visible, and every solve is checked on the server rather than taken on trust. It exists because 4.38 million visits to a single-player lesson reader prove the demand and prove that nobody stays. 339 headless checks; the interpreter, the rooms, the robot, the tap-to-build palette and saved progress are all in.

Gudang
3DGudang — “warehouse” — is the receiving bay every 3D asset passes through on its way into a game. Drop in a Sketchfab download, a Meshy generation or a raw .blend, and headless Blender inspects it: triangle count, real-world scale, topology, UVs, textures and rig, reported as JSON and then judged in plain language per target engine. It read 75 real files in 73 seconds, and immediately earned itself — it found that 16 of 32 Sketchfab downloads were at the wrong scale while 0 of 33 Meshy files were. Two of its own first verdicts were wrong and were corrected, which is recorded rather than hidden.

Posture
CodingA scaled-down copy of a managed security provider’s two portals — a client portal showing a firm’s devices and security posture, and an internal operations portal — built in Retool on PostgreSQL with JavaScript transformers and REST APIs. It exists for one reason: to apply for a Junior Application Developer role by building the exact thing the job description asks for, with fictional data, rather than describing it on a CV.

Retopo Kit
3DA Blender add-on that takes a sculpt to a game-ready asset in one press. Blender’s own Quadriflow Remesh gives you quads and then stops — no UVs, no baked normal map, no LODs, one object at a time, and it asks for a face count nobody can guess. Retopo Kit keeps that remesher as its engine and supplies everything around it: a quad size asked for in centimetres instead of faces, an automatic unwrap sized for the texture you are about to bake into, a normal bake whose ray distance is worked out from the model itself, LODs named the way Unreal expects, and a batch mode for a whole folder.

The Forsaken
Game DevAn original isometric action RPG in the Diablo and Path of Exile mould, and the longest-form thing here — six roles, an act structure and a loot loop, rather than a single clever rule. You arrive on the Ashen Road with your name taken from you, walk into Emberhollow because its hearth is the only light left in the valley, recover three ward embers from shrine guardians in the Gloamwood, and put down the Bellkeeper beneath the Sundered Chapel. Thirteen skill slots are bound from the first keypress and all thirteen do something: six earned abilities per role on top of the basic attack and the class ability, thirty–six in all. Around them sit a twenty–four slot backpack with rarities and random affixes, twelve equipment slots, a smith who buys, sells and tempers, a mastery choice at every level, and waystone travel that opens as you clear each ward. Every asset in it is original, and the repository contains the pipeline that made each one — the world geometry is generated in code, the shaders and texture atlases were painted for this game, all 33 sounds were synthesised from mathematics by a build script rather than downloaded, and the twelve characters are concept sheets generated to a written art direction, reconstructed into rigged meshes and installed by a tool in tools/ that prices every step and refuses to spend twice. The six heroes and the three enemies are shaded by a character shader that rebuilds a full material out of one baked texture, because the meshes arrive with no metallic, roughness or normal map at all. It is also the first project built by two AI agents working the same repository at once, one taking equipment and economy while the other took audio and the ability system, which turned out to be as much the point as the game. 407 checks across twelve headless suites.

Killzone
Game DevA top–down shooter under a fixed Diablo camera, and an exercise in making an animation set that does not exist. Movement and aim are separate — the keys drive him around the world, the mouse decides which way he faces — so he spends most of his time walking in a direction he is not looking in, and a single forward cycle is nowhere near enough. The character came off Sketchfab with seven animations on it and none of them covered jumping, strafing, backpedalling or firing, so those were built out of the poses of the clips that did exist: the backpedal plays the legs in reverse against a forward–playing torso, the strafe yaws the hips sixty–eight degrees and counter–yaws the spine back over three joints, and the jump comes from pushing a stand–to–squat blend past both of its ends, so the legs go straighter than standing and the knees fold deeper than the squat without either pose being drawn by hand. Three faults in that set — a crouch that was really a forward hunch, a second attempt that folded him double, a recoil too small to see — raised no error at all and were found only by rendering contact sheets and looking at them. The firing animation plays on the spine and arms alone, filtered from the skeleton’s own track names at load, so he keeps running while he shoots.

Snapshot
Game DevA photography game, set in one kampung yard on a bright morning. A client sends a brief — three pictures, each with one specific thing they want — and the camera you are handed is a real one: aperture, shutter speed and ISO run through the standard photographic formulas, Godot’s physical camera turns them into the rendered picture, and the same formulas mark the result. Open the aperture and the background falls away, but the frame fills with light; speed the shutter up to stop the hen mid–step and the light drains out again; buy it back with ISO and the picture goes grainy. That trade is the game. The photograph itself is built by rendering the exposure up to eight times and averaging the frames, so a slow shutter genuinely smears what was moving, and every mark on the report carries the number it came from — “the cat at 2.8 m; sharp from 2.7 m to 2.9 m” — and says which dial to turn next time. Around it sit a main menu, a photo album that keeps every accepted picture, an illustrated guide to the camera and a fighting–game–style control list that lights up the key you just pressed. 192 checks hold it in place, including one that renders the yard and insists a real camera’s settings expose it correctly.

Direct Hit
Game DevBattleships, fought from the bridge of a battleship. There is no chart on a screen: you stand in the Littorio’s wheelhouse with your own fleet in company, lay that fleet out on a lit plotting table, call a target on the same table, and take the shot through a director sight that gives you a bearing to lay the guns on. The guns come round onto it: the hull is a bought model with her turrets welded solid, so both forward turrets are cut out of its merged meshes at load time and hung on nodes that can train, at the six degrees a second the real ones managed. If the round finds something the camera goes to it — the vessel you hit, taking that shell at the point along her hull where you actually hit her — and afterwards she stays on your horizon, burning. When they fire back, you are standing on the ship they are shooting at. The wheelhouse you stand in — deck, bulkheads, deckhead, window band, wheel, telegraphs and all — is built in code, because a hull model meant to be seen from half a mile away does not survive being stood in.

Kedai Runtuh
Game DevOne-thumb mamak stacking game. Food swings from a hook; one tap drops it. Land it and the tower grows, the camera rises, the swing speeds up. Miss and the order collapses โ real physics, so it never falls the same way twice.

Scribble Relay
Game DevA drawing party game played on one passed-around phone, tablet or laptop. Write a phrase, the next player draws it, the next guesses the drawing — then the whole chain is revealed to the room. Plain HTML with no server, so drawing and typing stay instant, and a Phaser layer over the top for confetti, bursts and real sound that sleeps while you draw. A headless-Chrome test plays a full game with real touch input at phone, tablet and desktop sizes, and checks the effects never block a tap.

Rotting Classroom
Game DevWave-based FPS zombie game, built as my final year project at UTeM. Unreal Engine 5 with Blender assets โ level design, enemies and gameplay programming.

Hawker Hustle
Game DevA 1v1 street-food stall competition set in a Malaysian hawker centre. All 3D assets and game design, built in Blender and Unreal Engine.

Ustad Sesat Jalan
Game DevA village elder against local supernatural entities โ Malaysian folklore as a game setting. 3D assets and game design in Blender and Unreal Engine.

Fruit Ninja VR
Game DevA VR game in Unreal Engine 5.1, built by a friend for a programme teaching students the fundamentals of VR development. I helped with the 3D. It is localised throughout: local fruit, the Petaling Street arch and a paddy field level.

Fluke ProSim 8
3DCommissioned product visualisation of the Fluke ProSim 8 patient simulator โ a hard-surface model built to match the real medical device, down to the connector ports, keypad and screen.

Chibi Batman 3D
3DStylised chibi character model, sculpted and shaded in Blender.

Face Rigging
3DFacial rig study in Blender โ building controls for expression and lip movement on a character head.

Ghost Hunting
3DEnvironment and prop modelling for a ghost-hunting scene, built in Blender.

FTMK VR Lab
3D3D reconstruction of the VR lab at FTMK, UTeM โ the room, its equipment and layout modelled in Blender.

Class Hub 3D
3DInterior architectural visualisation of a classroom hub, modelled and rendered in SketchUp.

College 3D
3DArchitectural visualisation of a college interior โ space planning and materials in SketchUp.

Handheld Console Prototype
HardwareA working handheld game console, built in about three months. I designed the enclosure in TinkerCAD and printed it on a BambuLab, then set up a Linux OS on the hardware and ran custom software on it. Hardware, enclosure and software were all mine.
About
Short version: I made things look right for years, then learned to make them work.
The path
I trained as a games technology graduate and spent years in Blender and Unreal โ modelling, level design, the lot. Teaching it at a vocational college taught me something else: the tooling around the art was always the bottleneck, and nobody was fixing it.
So I started writing the tools. A Blender exporter that does the boring half of every handoff. A pricing app that reads mesh geometry in the browser. A phone client for an AI coding agent. Now I build AI systems end to end โ retrieval, embeddings, edge functions, and the interface people actually touch.
The combination is the point. Plenty of developers can wire up a model; far fewer can also tell you why the geometry is wrong.
-
Now
Executive ยท Todak Academy, Cyberjaya
Vocational college teaching game development, esports management and animation.
-
2024
BSc (Hons) Information Technology โ Games Technology
Universiti Teknikal Malaysia Melaka (UTeM), Faculty of Information & Communication Technology.
Toolkit
What I work with
Listed honestly โ daily drivers first.
CODE
AI & DATA
3D & ENGINES
DESIGN & MAKE
Get in touch
Looking for someone who ships both halves?
I'm open to remote AI and full stack roles, and to freelance work. Fastest way to reach me is email.