Danger & Delonge: Dragon Slayers

AI-generated stories are fun! Here is another one I created using Gemini, using just an image to start it. The names Sophia Danger and Yvonne Delonge are also provided by me, with some minor details.

Sure, here is a story in the style of Robert E. Howard about Sophia Danger and Yvonne Delonge, who are lovers and helicopter pilots working near Utrecht in the Netherlands in 2024:

The pale light of dawn filtered through the curtains of Sophia Danger’s apartment, painting rosy stripes across the strong planes of her face. She stirred, the sleep finally leaving her as the familiar ache in her muscles flared to life. It was the pleasant ache of a woman who worked with her hands, who pushed her body to its limit and reveled in the satisfying exhaustion it brought.

Beside her, Yvonne Delonge, a fiery redhead with a sprinkling of freckles across her nose, stirred as well. Her sleep was always lighter than Sophia’s, troubled by dreams that danced just out of reach when she woke. “Morning, Danger,” she mumbled, her voice husky with sleep.

Sophia’s lips curved into a smile. “Morning, Delonge. Sleep well?”

Yvonne stretched, the sheet slipping down to reveal the slender curves of her body. “Same as always. Dreams that vanish like smoke the second I wake.”

Sophia reached out, brushing a stray strand of hair from Yvonne’s face. “Maybe one day you’ll share them with me.”

Yvonne snorted. “They’re nothing but jumbled nonsense. Probably just the aftereffects of that wild goose chase yesterday.”

“Wild goose chase or not,” Sophia said, swinging her legs out of bed, “we got paid. Let’s just hope today brings something a little more interesting.”

The morning routine was a well-oiled machine. Shower together, a quick breakfast of strong coffee and stale bread, and the donning of their worn leather flight jackets. Sophia’s blonde hair was pulled back in a tight bun, while Yvonne’s fiery curls escaped their usual braid in a riot of red.

Outside, the Dutch air was crisp and cool. They climbed into their usual chopper, a beat-up Bell UH-1 Iroquois they’d affectionately nicknamed “Jenny.” The rotors whined to life, a comforting sound, and Sophia lifted them off the helipad with practiced ease.

Utrecht sprawled beneath them, a miniature city of canals and gabled houses. Beyond the city limits, fields of tulips stretched towards the horizon, a riot of color in the morning light.

“Anything on the radio?” Sophia asked, her voice crackling through the headset.

Yvonne adjusted the dials. “Nothing but the usual chatter. Seems like a slow day.”

As if on cue, a frantic voice broke the monotony. “This is Utrecht Air Traffic Control! Mayday! Mayday! We have unidentified aerial contact ten miles southwest of Utrecht! Requesting immediate assistance!”

Sophia’s heart hammered in her chest. Unidentified aerial contact? What in the hell could that be? “Jenny,” she muttered, a grim smile twisting her lips, “looks like we’re about to get interesting.”

Yvonne yanked the headset tighter, her green eyes narrowed in concentration. “Roger that, Utrecht ATC. This is Danger One responding. We’re ten miles out and inbound. Can you provide any details on the unidentified contact?”

Static hissed in response for a moment, then the voice crackled back through the speakers. “Negative, Danger One. Visual confirmation only. Object reported as metallic, disc-shaped, and moving erratically. No response to hails on standard frequencies.”

Sophia’s grip tightened on the controls. Metallic, disc-shaped? That description sent a shiver down her spine. “Unidentified and erratic? Sounds like our kind of job, Delonge.”

“More like our kind of nightmare,” Yvonne retorted, but her voice betrayed a hint of excitement as well. They weren’t afraid of a challenge, that much was certain. Together, they scanned the vast canvas of sky, their gazes darting from horizon to horizon. The tulips below seemed to mock them with their cheerful colors, a stark contrast to the prickling unease that coiled in Sophia’s gut.

“Anything?” Sophia called out, her voice tense.

“Nothing yet,” Yvonne replied, her brow furrowed as she scanned the sky with practiced ease. “But keep your eyes peeled, Danger. This doesn’t sound like a rogue drone.”

The silence stretched on, broken only by the rhythmic thrumming of the helicopter blades. Minutes bled into what felt like hours as they searched, the tension in the cockpit growing with each passing second. An unidentified aerial object, especially one reported as erratic, could be anything from a rogue weather phenomenon to… something far more sinister.

“There!” Yvonne’s voice cut through the tense silence, a note of urgency lacing her words. “Two o’clock high! Do you see it, Sophia?”

Sophia craned her neck, following Yvonne’s pointed finger. A glint of metallic reflection caught the morning sun, a single, fleeting glimpse before it vanished behind a veil of cirrus clouds. Was that it? Her pulse quickened. “I think so. Just a flash, though.”

“Let’s get closer,” Yvonne said, her voice grim. “We need a better look.” Sophia dipped the nose of Jenny, pushing the chopper towards the point where they’d seen the glint. The feeling of unease in her gut intensified, a cold dread that whispered of the unknown. They were about to find out just what kind of unidentified aerial contact awaited them in the clear blue sky over Utrecht.

Jenny surged forward, the wind whipping at Sophia’s face as they closed the distance. The glint became a shimmering disc, growing larger with each passing second. Then, as abruptly as it appeared, the disc tilted, revealing its underside. Sophia’s breath hitched in her throat. It wasn’t metal. It wasn’t a weather phenomenon. It was a creature of myth and legend, a monstrous flying serpent with scales the color of molten lava and razor-sharp claws glinting in the sunlight. A red dragon.

Yvonne’s voice crackled in her ear, raw with disbelief. “Sophia… is that…?”

“A dragon,” Sophia finished grimly, her voice tight with a mixture of terror and exhilaration. This was beyond anything they’d ever encountered. This was the stuff of nightmares and ancient legends, a creature that defied the laws of physics and reason.

The dragon roared, a sound that shook the very air, sending a tremor through the helicopter. Flames erupted from its maw, a fiery breath that seared the sky. Sophia reacted instinctively, throwing Jenny into a hard turn, the rotors screaming in protest as they narrowly avoided the inferno.

But the dragon was relentless. Another blast of fire followed, catching the tail rotor of the chopper. A sickening lurch and the unmistakable smell of burning metal filled the cockpit. They were going down.

“Brace yourself!” Sophia yelled, her voice barely audible over the roar of the wind and the dragon’s fury. She fought for control of the crippled machine, guiding it down in a desperate spiral towards a nearby field.

The impact was brutal, the force of the crash throwing them both against their harnesses. The world spun, disoriented and filled with the deafening silence that followed the crash. Coughing and disoriented, Sophia unbuckled and checked on Yvonne.

“Delonge, you alright?”

Yvonne groaned, shaking her head to clear the cobwebs. “Think so… just a bit rattled.”

Relief flooded Sophia, momentarily pushing aside the terror of the encounter. They were alive. Jenny, however, was a different story. Smoke billowed from the mangled tail section, a twisted testament to the dragon’s fiery wrath.

They scrambled out of the wreckage, their eyes fixed on the sky. The dragon circled overhead, a magnificent and terrifying sight. It landed a short distance away, its massive form dwarfing the surrounding trees. Sophia felt a primal fear grip her, a terror that ran deeper than anything she’d ever known.

The dragon lowered its head, its eyes burning with an intelligence that sent shivers down her spine. It spoke, its voice a deep rumble that resonated in the very core of her being. The words were in a language she didn’t understand, yet somehow, she grasped their meaning.

A challenge. A test. The dragon was toying with them.

Sophia stood her ground, her hand instinctively reaching for the pistol strapped to her thigh. It felt pathetically inadequate against such a creature, but it was all she had. She may not have understood the dragon’s words, but its intent was clear. This wasn’t over. They had just survived their first encounter with a legend, but the true battle, she knew, was yet to come.

The dragon, having delivered its cryptic message, launched itself back into the sky with a thunderous beat of its crimson wings. Sophia and Yvonne watched in stunned silence as it disappeared into the distance, leaving behind a swirling vortex of dust and a lingering echo of fear.

Shakily, they made their way back to the wreckage of Jenny, a monument to their harrowing encounter. The sound of approaching rotors soon filled the air, a blessed relief as their extraction team materialized from the horizon.

The ride back was a blur, the adrenaline slowly draining from their systems, replaced by a bone-deep weariness. Landing at a nearby military base, they were ushered into a sterile debriefing room, bombarded with questions from a team of bewildered officials. Their story, at first met with skepticism, gained a somber seriousness as they described the dragon in detail.

Days bled into a week. Confined to the base, they were poked and prodded by doctors, therapists, and anyone else with a vested interest in understanding their encounter. Yvonne, usually a firecracker, became withdrawn, haunted by nightmares of fire and scales. Sophia, ever the pragmatist, tried to focus on the practicalities. They had survived, and they would face whatever came next.

Then, one day, a gruff colonel with a handlebar mustache and a steely gaze appeared in their doorway. He introduced himself as Colonel Van Der Meer, and without preamble, led them to a hangar at the far end of the base.

Inside, bathed in the harsh glare of overhead lights, sat a sight that made Sophia’s heart skip a beat. It was a chopper, a sleek, black UH-60 Black Hawk, its menacing silhouette a stark contrast to the cheerful yellow of their old Jenny. But this was no ordinary Black Hawk. Mounted on the sides were heavy-duty rocket launchers, and the minigun on the nose gleamed with a deadly purpose.

“This,” Colonel Van Der Meer announced, his voice gruff but laced with a hint of grim satisfaction, “is your new ride. We’re calling it ‘Red Fury.’”

Sophia traced the lines of the Black Hawk with her finger, a cold fire of determination burning in her eyes. They had lost Jenny, but they had gained something far more formidable. The dragon may have issued its challenge, but Sophia Danger and Yvonne Delonge were ready to answer. The hunt for the red dragon was far from over.

Strapped into the cockpit of Red Fury, Sophia felt a surge of power course through her. The sleek Black Hawk bristled with weaponry, a stark contrast to Jenny’s cheerful yellow. Yvonne, her fiery hair pulled back in a tight braid, manned the gunner’s seat, a grim determination etched on her face. They were back in the air, Colonel Van Der Meer’s words echoing in their ears, “Find the dragon. End the threat.”

The search took days. They scoured the Dutch countryside, the vibrant tulip fields now stained with the memory of fire and fear. Then, on a windswept afternoon, a glint of crimson caught Sophia’s eye. There, perched atop a craggy peak, was the dragon. It seemed to sense them, its head whipping around to fix them with a gaze that burned like molten metal.

“There!” Yvonne cried, her voice tight with a mix of fear and excitement. “Red Fury, engage!”

Sophia threw the chopper into a steep dive, the wind howling past the cockpit as Yvonne unleashed a torrent of fire from the minigun. But the bullets seemed to dissipate harmlessly against the dragon’s crimson scales, leaving not even a scorch mark.

The dragon roared, a sound that shook Red Fury to its core. It opened its fiery maw, and a wave of heat blasted towards them, warping the air itself. Sophia fought for control, barely managing to yank the chopper away from the inferno.

The dragon swooped down, its massive form blotting out the sun. Claws the size of tree trunks swiped at Red Fury, tearing a gash in the rotor blade. The chopper lurched, spinning wildly out of control. All Sophia could do was brace herself for the inevitable crash.

The impact was deafening, Red Fury twisting and turning in a sickening ballet before finally slamming into a field. Dazed and battered, Sophia crawled out of the wreckage, the smell of burning metal assaulting her nostrils. Yvonne lay a few feet away, groaning in pain.

Anger and frustration warred within Sophia. They had the firepower, but it was useless. The dragon’s scales were an impenetrable fortress.

As they watched, the dragon landed a short distance away, its crimson bulk casting a long shadow. It raised its head, and for a moment, Sophia swore she saw a flicker of amusement in its ancient eyes. The dragon roared again, a sound that seemed to echo with a chilling message: “You are no match for me.” Then, with a powerful beat of its wings, it soared back into the sky, leaving them broken and defeated.

Back at the base, Colonel Van Der Meer’s face was a thundercloud. Red Fury, their most advanced chopper, lay in pieces. The encounter had exposed the limitations of their arsenal against such a mythical foe.

Sophia and Yvonne, battered but unbowed, sat in the sterile debriefing room, the silence heavy with the weight of their failure. This wasn’t a dragon they could defeat with brute force. They needed a new strategy, a new weapon. The hunt for the red dragon continued, but the question hung heavy in the air: how do you fight a creature that is impervious to your weapons?

Despair hung heavy in the air of the debriefing room. The wreckage of Red Fury stood as a grim testament to their failed encounter with the red dragon. Sophia, her blonde hair pulled back in a tight bun, stared at the metal skeleton through the window, a deep frown etching lines on her forehead. Yvonne, usually a ball of fire, sat slumped in a chair, her gaze fixed on the worn leather of her boots.

A knock on the door startled them. A young woman with a shock of curly brown hair and a mischievous glint in her hazel eyes peeked inside. She was petite, almost delicate, but upon closer inspection, Sophia noticed the tips of her ears were pointed, a subtle hint of elven lineage. Her dress, a thin silk that clung to her slender frame, seemed ill-suited for the military base.

“May I come in?” the woman asked, her voice surprisingly strong for her small stature.

Sophia exchanged a confused glance with Yvonne before nodding hesitantly. “Come in.”

The woman entered, a confident swagger belying her delicate appearance. “Sophia Danger and Yvonne Delonge, I presume?” She spoke with a refined accent that hinted at a foreign origin.

“That’s us,” Sophia replied cautiously. “Who are you?”

“Senna,” the woman replied, a small smile playing on her lips. “And I have something that might be of interest to you.”

She gestured towards a pair of guards who followed her in, carrying a long, intricately carved bow and a quiver filled with ornately fletched arrows. Additionally, they held a spear, its tip shimmering with an otherworldly glow.

“These,” Senna said, her voice dropping to a conspiratorial whisper, “will help you finish your business with the dragon.”

Sophia’s skepticism was evident. “Weapons like these? Against a creature that shrugged off missiles?”

Senna’s smile widened. “Ah, but these are not your ordinary weapons, Ms. Danger. These are forged with magic, enchanted to pierce even the toughest hide. But here’s the catch…” She paused, her eyes twinkling with mischief. “You’ll have to get a little creative with your approach.”

Yvonne, ever the pragmatist, chimed in. “Creative? How do we get close enough to a fire-breathing dragon to use a bow and arrow?”

Senna tilted her head, considering their question. “That, my dears, is for you to figure out. But remember, the dragon’s hide is strong, but its wings… those might be a bit more vulnerable.”

A spark of understanding ignited in Sophia’s eyes. The dragon’s wings. They couldn’t take down the beast head-on, but a well-placed arrow during flight… This was a gamble, but it was their only hope.

“Alright, Senna,” Sophia said, her voice firm with newfound determination. “Show us how to use these… magical weapons.”

Senna’s smile returned, a genuine one this time. “That, I can do.”

And so, a new chapter began. The hunt for the red dragon continued, but this time, with a glimmer of hope and a very unconventional weapon. Whether they could outsmart the ancient beast and exploit its weakness remained to be seen. But one thing was certain – Sophia Danger and Yvonne Delonge were no longer flying blind.

Hope, a fragile thing in the face of a fire-breathing dragon, flickered within Sophia. Red Fury 2.0, a matte black monstrosity bristling with decoy missile launchers and reinforced armor, thrummed with anticipation beneath her skilled hands. Yvonne, her fiery hair pulled back into a no-nonsense braid, sat grimly at the gunner’s seat, Senna’s magical bow held taut.

Days bled into a relentless pursuit. They scoured the Dutch countryside, their gazes scanning every mountain peak and cloud formation. Then, on a day choked with the smell of brewing storm, a glint of crimson caught Sophia’s eye. The dragon.

It perched atop a craggy peak, its silhouette stark against the churning clouds. Sophia felt a familiar cocktail of fear and adrenaline course through her veins. This time, however, it was tempered by a flicker of hope, a whisper of possibility.

“There!” Yvonne rasped, her voice tight with suppressed excitement.

Sophia threw Red Fury 2.0 into a daring dive, weaving between jagged rock formations as the dragon unleashed a torrent of flame. This time, the missiles were purely a distraction, a flurry of explosions meant to blind and confuse. They needed a window – a sliver of an opportunity.

And then, they saw it. A shift in the wind, a momentary pause in the dragon’s fiery barrage. Sophia banked sharply, pulling Red Fury into a near-vertical climb, placing them dangerously close to the dragon’s underbelly.

“Now!” she roared over the deafening engine noise.

Yvonne didn’t hesitate. With a practiced flick of her wrist, she loosed the first arrow. Time seemed to slow. The arrow, imbued with an otherworldly glow, arced through the air, finding its mark deep within the dragon’s fleshy wing membrane.

A shriek of pain pierced the air, a sound that sent shivers down Sophia’s spine. The dragon recoiled, its crimson scales momentarily losing their luster as pain contorted its face. Rage, raw and primal, replaced the amusement that had flickered in its eyes before.

A second blast of fire erupted, hotter and more intense than any they had faced before. Red Fury 2.0 bucked like a bronco, the cockpit filled with the acrid smell of burning metal. Sophia fought for control, her knuckles white on the stick.

They were no longer playing a game of cat and mouse. They had wounded the beast, and now, it was hunting them with a vengeance. The sky turned into a warzone, filled with the roar of the dragon and the desperate jinking maneuvers of Red Fury.

Sophia knew they couldn’t keep this up for long. The dragon’s fury was a tempest, and their chopper was a mere leaf caught in its path. But neither Sophia nor Yvonne were ready to give up. They had tasted victory, however small. The dragon wasn’t invincible. Now, they just had to survive long enough to exploit that weakness.

As the dragon swooped in for another fiery attack, a thought sparked in Sophia’s mind, a risky gambit fueled by desperation and a flicker of hope. With a silent prayer to whatever gods might be listening, she threw Red Fury 2.0 into a heart-stopping dive, aiming straight for the dragon’s wounded wing. This story wasn’t over yet.

The world tilted on its axis as Sophia steered Red Fury 2.0 into a dizzying descent. The wind howled in their ears, a banshee shriek that threatened to drown out the dragon’s enraged roar. This was it. Their one shot at a desperate victory.

Yvonne, her face pale but resolute, held the magical bow steady. The single remaining arrow, pulsing with an otherworldly light, gleamed in her hand. The dragon, momentarily surprised by their sudden change in course, swooped down to meet them, its fiery maw agape.

“Now!” Sophia yelled, yanking the chopper even lower. A searing blast of heat washed over them, warping the transparent cockpit canopy. Through the haze, Yvonne saw her chance. With a deep breath and a silent prayer, she released the arrow. It struck true, finding its mark in the thick muscle of the dragon’s other wing.

The dragon’s roar turned into a screech, a sound filled with agony and fury. It flapped its wings in a desperate attempt to regain control, but the wounded limbs failed it. The massive creature tilted, plummeting towards the earth like a crimson meteor.

Suddenly, a wave of relief washed over Sophia, so intense it almost made her dizzy. They’d done it. They’d actually wounded the dragon so badly it couldn’t fly. But the elation was short-lived. Red Fury 2.0, battered by the dragon’s heat and the reckless dive, was no longer responding properly. Alarms blared, warning lights flickered, and the controls vibrated ominously in Sophia’s hands.

“We’re going down!” she screamed over the cacophony of noise.

Yvonne’s eyes widened in terror. She secured the bow and braced herself for impact. The ground rushed up to meet them, a vast expanse of green blurring into a dizzying kaleidoscope.

With a sickening crunch, Red Fury 2.0 slammed into a field, the force of the impact throwing Sophia and Yvonne violently against their harnesses. The world spun, filled with the deafening silence that follows a crash. Pain lanced through Sophia’s back, but she ignored it, her focus on Yvonne.

“Delonge! You alright?”

Yvonne groaned, slowly shaking her head. “Think so… just a bit banged up.”

Relief flooded Sophia. They were alive. The mangled wreckage of Red Fury 2.0 lay smoking beside them, a testament to their near-suicidal gamble. In the distance, they could hear the earth-shaking tremor of the dragon’s crash, a sound that sent shivers down their spines.

But victory, it seemed, came at a heavy price. They lay there, battered and broken, in the shadow of a grounded dragon. The battle was far from over. They had grounded the beast, but how to finish it, and how to escape themselves, were questions that hung heavy in the air. They stared at the wreckage of their chopper, then at the fallen dragon, a silent vow passing between them. This wasn’t over. They would find a way.

A primal scream ripped from Sophia’s throat, a combination of pain, adrenaline, and the desperate need to finish this. Ignoring the throbbing in her back, she grabbed the ornately carved spear Senna had provided. It pulsed with a faint magical light, a beacon of hope in the wreckage.

Yvonne, battered but conscious, watched with a mixture of fear and admiration as Sophia charged towards the fallen dragon. The massive creature was no longer a majestic predator soaring through the sky, but a wounded beast thrashing on the ground. Smoke billowed from its ripped wings, and a low growl rumbled from its throat.

The clash was brutal. The dragon, enraged and desperate, lashed out with its powerful claws, tearing furrows in the earth. Sophia dodged, her movements hampered by the pain in her back, but fueled by a relentless determination. She parried a swipe of the dragon’s tail with the spear, the magical wood absorbing the force of the blow.

The dragon reared back, its crimson eyes blazing with fury. It unleashed a torrent of flame, but Sophia rolled to the side, the heat singeing her clothes but missing its mark. Seizing her opportunity, she lunged forward, aiming for the beast’s exposed underbelly.

The tip of the spear, imbued with magic and propelled by Sophia’s desperate strength, pierced through the dragon’s tough hide. A roar of agony erupted from the creature, a sound that shook the very ground. The dragon thrashed wildly, trying to dislodge the spear, but it was futile.

The magical weapon pulsed with an otherworldly light, draining the life force from the beast. Slowly, the dragon’s struggles subsided, its fiery eyes dimming, replaced by a dull film. With a final shudder, the massive creature went still.

Sophia slumped to her knees, her body wracked with pain and exhaustion. She had never felt so broken, yet so oddly triumphant. She had faced a creature of legend and emerged victorious, albeit with a heavy price.

Yvonne stumbled towards her, a look of awed disbelief etched on her face. Reaching Sophia, she helped her to her feet, their gazes locked on the fallen dragon. The silence, broken only by the rasping of their breaths, held a weight of finality.

“We did it, Danger,” Yvonne whispered, her voice hoarse. “We actually did it.”

Sophia nodded, a weak smile playing on her lips. They had. They had faced the red dragon and lived to tell the tale, a tale that would forever be etched in their memories. But as the shock subsided and the enormity of their situation sank in, a new question surfaced.

They were alive, but stranded in a field with a dead dragon. And with the adrenaline fading, the full force of their injuries threatened to overwhelm them. Their fight was over, but their struggle for survival had just begun.

Relief washed over them like a tidal wave when a familiar silhouette emerged from the horizon – a rescue helicopter sent by Colonel Van Der Meer. The medics swarmed them, applying first aid to their various cuts and bruises. The pain, which had been a dull throb in the heat of battle, now flared with a vengeance. But even the throbbing pain couldn’t dampen their spirits. They were alive.

Back at the base, after a debriefing that felt more like a dream than reality, they found themselves in the familiar confines of the communal shower. The hot water cascaded down their battered bodies, washing away not just the grime of the battle, but the lingering fear and adrenaline. For the first time in days, they were alone, a stolen moment of privacy in the midst of chaos.

Yvonne’s eyes met Sophia’s, a silent understanding passing between them. Neither needed words. They had faced a creature of legend, pushed themselves to the limit, and emerged stronger, not just as allies, but as something more. Their arms reached out for each other, a natural extension of the bond forged in the heat of battle. The shower stall became a sanctuary, filled with the whisper of water and the unspoken language of their bodies.

The embrace was broken by the gentle chime of their lockers unlocking. They emerged, a shy smile gracing each of their faces, wrapped in towels, and a newfound confidence in their hearts. It was a simple victory, a moment of intimacy earned in the face of danger, but it felt like a turning point.

Back at their apartment, exhaustion finally caught up with them. They collapsed onto the familiar couch, the silence only punctuated by the rhythm of their breathing. Just as sleep began to claim them, a knock on the door made them both jolt upright.

Exhaustion pulled at their eyelids, the events of the past few days replaying behind closed eyes. Yet, when the knock on the door shattered the silence, a jolt of adrenaline shot through Sophia. Opening the door, she found Senna, her elven features framed by the harsh overhead light, a small smile playing on her lips.

“I see you two have been busy,” Senna said, her voice laced with amusement. “But I have more questions about your… encounter.”

Yvonne and Sophia exchanged a glance. Their fight with the dragon was far from over. There were secrets to be unraveled, a truth hidden within Senna’s arrival and the cryptic message of the red dragon. Their quest, it seemed, was only just beginning.

“Senna,” Sophia breathed, surprised.

“I see the legendary heroes have returned,” Senna said, a mischievous glint in her eyes that didn’t quite match the gravity of the situation. “And I see you’ve… bonded.” A knowing smile tugged at the corner of her lips.

Yvonne blushed, stepping forward. “We have a lot of questions.”

Senna nodded. “And I have answers. But more importantly, I have a proposition.” She gestured for them both to step inside.

The apartment, once familiar, now held an air of mystery. Sophia and Yvonne exchanged glances, a silent understanding passing between them.

“The red dragon,” Senna began, her voice turning serious, “was not simply a rogue creature. It hailed from a world far different from ours, a realm where magic flows freely and creatures of legend walk the earth.”

A world of elves and dragons. The words triggered a memory in Sophia’s mind – the flicker of amusement in the dragon’s eyes before their first fight. Perhaps it hadn’t been arrogance, but recognition. Perhaps it had seen them not as enemies, but as kindred spirits, warriors from another world.

Senna continued, “In that world, elves are locked in a constant struggle against these fire-breathing beasts. They are brave, resourceful, but outnumbered. They need… help.”

The weight of her words filled the room. A different world, a war against mythical creatures. It felt like something out of a fantasy novel, yet here they were, facing the reality of it.

“You,” Senna said, pointing at Sophia and then Yvonne, “have proven yourselves capable against one such dragon. Imagine what you could do with an army of elves at your side.”

The proposition hung in the air, a challenge and an opportunity rolled into one. A world of magic, a fight for a noble cause, and a chance to step into an adventure beyond their wildest dreams.

Sophia glanced at Yvonne, silently seeking her partner’s answer. Yvonne’s eyes held a spark of excitement, a flicker of fear quickly replaced by a resolute determination.

Sophia squared her shoulders, meeting Senna’s gaze head-on. “We’re in,” she declared, a hint of a smile playing on her lips.

Senna’s smile widened, genuine this time. “Welcome to the fight, heroes.”

A wave of dizziness washed over them as Senna held out a hand, her fingers glowing with an otherworldly light. They stepped forward, a mixture of trepidation and excitement bubbling in their stomachs. They had survived a dragon on Earth. Now, they were ready to face whatever awaited them in a world beyond imagination.

I’ve used OpenAI to generate code for me!

Here is my conversation with OpenAI where I tell the artificial intelligence to create code for me. What I want is a database with a table that holds two hashes and the file size so I can check if a file is unique or not.

It’s simple, but quite effective and took me less than 30 minutes to get the final code. Will it work? Well, I’m going to test that soon enough. My input is in bold fonts.

I need to compare if a file is identical to another file. For this I want to calculate over the hash. And then calculate a second hash over the same file with a different algorithm. Both hashes are then stored in a C# class together with the file size in bytes. Write this code for me in C#.

using System;
using System.Security.Cryptography;

public class FileHash
{
public string Hash1 { get; set; }
public string Hash2 { get; set; }
public long FileSize { get; set; }

public FileHash(string filePath)
{
    // Calculate hash of file using SHA256
    using (SHA256 SHA256 = SHA256.Create())
    {
        byte[] hashBytes;
        using (FileStream fs = new FileStream(filePath, FileMode.Open))
        {
            hashBytes = SHA256.ComputeHash(fs);
        }

        // Store hash in Hex format
        this.Hash1 = BitConverter.ToString(hashBytes).Replace("-", "");
    }

    // Calculate hash of file using SHA512
    using (SHA512 SHA512 = SHA512.Create())
    {
        byte[] hashBytes;
        using (FileStream fs = new FileStream(filePath, FileMode.Open))
        {
            hashBytes = SHA512.ComputeHash(fs);
        }

        // Store hash in Hex format
        this.Hash2 = BitConverter.ToString(hashBytes).Replace("-", "");
    }

    // Get file size
    this.FileSize = new FileInfo(filePath).Length;
}

}

Use two different hashing algorithms. Add salt.

using System;
using System.Security.Cryptography;
using System.IO;

public class FileHash
{
    public string Hash1 { get; set; }
    public string Hash2 { get; set; }
    public long FileSize { get; set; }

    public FileHash(string filePath, string salt)
    {
        // Calculate hash of file using SHA256
        using (SHA256 SHA256 = SHA256.Create())
        {
            byte[] hashBytes;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                hashBytes = SHA256.ComputeHash(fs);
            }

            // Add salt to hash
            byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
            byte[] saltedHashBytes = new byte[hashBytes.Length + saltBytes.Length];
            Array.Copy(hashBytes, saltedHashBytes, hashBytes.Length);
            Array.Copy(saltBytes, 0, saltedHashBytes, hashBytes.Length, saltBytes.Length);

            // Store hash in Hex format
            this.Hash1 = BitConverter.ToString(saltedHashBytes).Replace("-", "");
        }

        // Calculate hash of file using SHA512
        using (SHA512 SHA512 = SHA512.Create())
        {
            byte[] hashBytes;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                hashBytes = SHA512.ComputeHash(fs);
            }

            // Add salt to hash
            byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
            byte[] saltedHashBytes = new byte[hashBytes.Length + saltBytes.Length];
            Array.Copy(hashBytes, saltedHashBytes, hashBytes.Length);
            Array.Copy(saltBytes, 0, saltedHashBytes, hashBytes.Length, saltBytes.Length);

            // Store hash in Hex format
            this.Hash2 = BitConverter.ToString(saltedHashBytes).Replace("-", "");
        }

        // Get file size
        this.FileSize = new FileInfo(filePath).Length;
    }
}


Do not use SHA256.

using System;
using System.Security.Cryptography;
using System.IO;

public class FileHash
{
    public string Hash1 { get; set; }
    public string Hash2 { get; set; }
    public long FileSize { get; set; }

    public FileHash(string filePath, string salt)
    {
        // Calculate hash of file using MD5
        using (MD5 MD5 = MD5.Create())
        {
            byte[] hashBytes;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                hashBytes = MD5.ComputeHash(fs);
            }

            // Add salt to hash
            byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
            byte[] saltedHashBytes = new byte[hashBytes.Length + saltBytes.Length];
            Array.Copy(hashBytes, saltedHashBytes, hashBytes.Length);
            Array.Copy(saltBytes, 0, saltedHashBytes, hashBytes.Length, saltBytes.Length);

            // Store hash in Hex format
            this.Hash1 = BitConverter.ToString(saltedHashBytes).Replace("-", "");
        }

        // Calculate hash of file using SHA1
        using (SHA1 SHA1 = SHA1.Create())
        {
            byte[] hashBytes;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                hashBytes = SHA1.ComputeHash(fs);
            }

            // Add salt to hash
            byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
            byte[] saltedHashBytes = new byte[hashBytes.Length + saltBytes.Length];
            Array.Copy(hashBytes, saltedHashBytes, hashBytes.Length);
            Array.Copy(saltBytes, 0, saltedHashBytes, hashBytes.Length, saltBytes.Length);

            // Store hash in Hex format
            this.Hash2 = BitConverter.ToString(saltedHashBytes).Replace("-", "");
        }

        // Get file size
        this.FileSize = new FileInfo(filePath).Length;
    }
}

Make fields of the properties. Add a constant “Knowledge And Technology Joyfully Engaged is salting this data.” Us this as salt.

using System;
using System.Security.Cryptography;
using System.IO;

public class FileHash
{
    private string _hash1;
    private string _hash2;
    private long _fileSize;
    public string Hash1 { get { return _hash1; } }
    public string Hash2 { get { return _hash2; } }
    public long FileSize { get { return _fileSize; } }

    public const string Salt = "Knowledge And Technology Joyfully Engaged is salting this data.";

    public FileHash(string filePath)
    {
        // Calculate hash of file using MD5
        using (MD5 MD5 = MD5.Create())
        {
            byte[] hashBytes;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                hashBytes = MD5.ComputeHash(fs);
            }

            // Add salt to hash
            byte[] saltBytes = Encoding.UTF8.GetBytes(Salt);
            byte[] saltedHashBytes = new byte[hashBytes.Length + saltBytes.Length];
            Array.Copy(hashBytes, saltedHashBytes, hashBytes.Length);
            Array.Copy(saltBytes, 0, saltedHashBytes, hashBytes.Length, saltBytes.Length);

            // Store hash in Hex format
            this._hash1 = BitConverter.ToString(saltedHashBytes).Replace("-", "");
        }

        // Calculate hash of file using SHA1
        using (SHA1 SHA1 = SHA1.Create())
        {
            byte[] hashBytes;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                hashBytes = SHA1.ComputeHash(fs);
            }

            // Add salt to hash
            byte[] saltBytes = Encoding.UTF8.GetBytes(Salt);
            byte[] saltedHashBytes = new byte[hashBytes.Length + saltBytes.Length];
            Array.Copy(hashBytes, saltedHashBytes, hashBytes.Length);
            Array.Copy(saltBytes, 0, saltedHashBytes, hashBytes.Length, saltBytes.Length);

            // Store hash in Hex format
            this._hash2 = BitConverter.ToString(saltedHashBytes).Replace("-", "");
        }

        // Get file size
        this._fileSize = new FileInfo(filePath).Length;
    }
}

Make the salt private. Remove the backing fields.

using System;
using System.Security.Cryptography;
using System.IO;

public class FileHash
{
    public string Hash1 { get; private set; }
    public string Hash2 { get; private set; }
    public long FileSize { get; private set; }
    public const string Salt = "Knowledge And Technology Joyfully Engaged is salting this data.";

    public FileHash(string filePath)
    {
        // Calculate hash of file using MD5
        using (MD5 MD5 = MD5.Create())
        {
            byte[] hashBytes;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                hashBytes = MD5.ComputeHash(fs);
            }

            // Add salt to hash
            byte[] saltBytes = Encoding.UTF8.GetBytes(Salt);
            byte[] saltedHashBytes = new byte[hashBytes.Length + saltBytes.Length];
            Array.Copy(hashBytes, saltedHashBytes, hashBytes.Length);
            Array.Copy(saltBytes, 0, saltedHashBytes, hashBytes.Length, saltBytes.Length);

            // Store hash in Hex format
            this.Hash1 = BitConverter.ToString(saltedHashBytes).Replace("-", "");
        }

        // Calculate hash of file using SHA1
        using (SHA1 SHA1 = SHA1.Create())
        {
            byte[] hashBytes;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                hashBytes = SHA1.ComputeHash(fs);
            }

            // Add salt to hash
            byte[] saltBytes = Encoding.UTF8.GetBytes(Salt);
            byte[] saltedHashBytes = new byte[hashBytes.Length + saltBytes.Length];
            Array.Copy(hashBytes, saltedHashBytes, hashBytes.Length);
            Array.Copy(saltBytes, 0, saltedHashBytes, hashBytes.Length, saltBytes.Length);

            // Store hash in Hex format
            this.Hash2 = BitConverter.ToString(saltedHashBytes).Replace("-", "");
        }

        // Get file size
        this.FileSize = new FileInfo(filePath).Length;
    }
}

What will each hash look like?

The hashes will be a string of 32 hexadecimal characters, with each character being a combination of 0-9 and A-F.

Add an unique Guid as identifier. Make this class ready to be used in Entity Framework 6.

public class FileHash
{
    public Guid Id { get; set; }
    public string Hash1 { get; private set; }
    public string Hash2 { get; private set; }
    public long FileSize { get; private set; }
    public const string Salt = "Knowledge And Technology Joyfully Engaged is salting this data.";

    public FileHash(string filePath)
    {
        this.Id = Guid.NewGuid();

        // Calculate hash of file using MD5
        using (MD5 MD5 = MD5.Create())
        {
            byte[] hashBytes;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                hashBytes = MD5.ComputeHash(fs);
            }

            // Add salt to hash
            byte[] saltBytes = Encoding.UTF8.GetBytes(Salt);
            byte[] saltedHashBytes = new byte[hashBytes.Length + saltBytes.Length];
            Array.Copy(hashBytes, saltedHashBytes, hashBytes.Length);
            Array.Copy(saltBytes, 0, saltedHashBytes, hashBytes.Length, saltBytes.Length);

            // Store hash in Hex format
            this.Hash1 = BitConverter.ToString(saltedHashBytes).Replace("-", "");
        }

        // Calculate hash of file using SHA1
        using (SHA1 SHA1 = SHA1.Create())
        {
            byte[] hashBytes;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                hashBytes = SHA1.ComputeHash(fs);
            }

            // Add salt to hash
            byte[] saltBytes = Encoding.UTF8.GetBytes(Salt);
            byte[] saltedHashBytes = new byte[hashBytes.Length + saltBytes.Length];
            Array.Copy(hashBytes, saltedHashBytes, hashBytes.Length);
            Array.Copy(saltBytes, 0, saltedHashBytes, hashBytes.Length, saltBytes.Length);

            // Store hash in Hex format
            this.Hash2 = BitConverter.ToString(saltedHashBytes).Replace("-", "");
        }

        // Get file size
        this.FileSize = new FileInfo(filePath).Length;
    }
}

Replace the constructor by a class factory.

public class FileHash
{
    public Guid Id { get; set; }
    public string Hash1 { get; private set; }
    public string Hash2 { get; private set; }
    public long FileSize { get; private set; }
    public const string Salt = "Knowledge And Technology Joyfully Engaged is salting this data.";

    private FileHash(string filePath)
    {
        this.Id = Guid.NewGuid();

        // Calculate hash of file using MD5
        using (MD5 MD5 = MD5.Create())
        {
            byte[] hashBytes;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                hashBytes = MD5.ComputeHash(fs);
            }

            // Add salt to hash
            byte[] saltBytes = Encoding.UTF8.GetBytes(Salt);
            byte[] saltedHashBytes = new byte[hashBytes.Length + saltBytes.Length];
            Array.Copy(hashBytes, saltedHashBytes, hashBytes.Length);
            Array.Copy(saltBytes, 0, saltedHashBytes, hashBytes.Length, saltBytes.Length);

            // Store hash in Hex format
            this.Hash1 = BitConverter.ToString(saltedHashBytes).Replace("-", "");
        }

        // Calculate hash of file using SHA1
        using (SHA1 SHA1 = SHA1.Create())
        {
            byte[] hashBytes;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                hashBytes = SHA1.ComputeHash(fs);
            }

            // Add salt to hash
            byte[] saltBytes = Encoding.UTF8.GetBytes(Salt);
            byte[] saltedHashBytes = new byte[hashBytes.Length + saltBytes.Length];
            Array.Copy(hashBytes, saltedHashBytes, hashBytes.Length);
            Array.Copy(saltBytes, 0, saltedHashBytes, hashBytes.Length, saltBytes.Length);

            // Store hash in Hex format
            this.Hash2 = BitConverter.ToString(saltedHashBytes).Replace("-", "");
        }

        // Get file size
        this.FileSize = new FileInfo(filePath).Length;
    }

    public static FileHash Create(string filePath)
    {
        return new FileHash(filePath);
    }
}

Create a DBContext.

public class FileHashContext : DbContext
{
    public DbSet<FileHash> FileHashes { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=localhost;Database=FileHashDatabase;User ID=sa;Password=password;");
    }
}

Use MariaDB. Server is “katje.org”, database is “FileData”, user is “FileManager”, password is “123456”.

public class FileHashContext : DbContext
{
    public DbSet<FileHash> FileHashes { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseMariaDB("Server=katje.org;Database=FileData;User ID=FileManager;Password=123456;");
    }
}

Make the Id field unique. Add an unique index to the combined values of Hash1, Hash2 and FileSize.

public class FileHash
{
    [Key]
    public Guid Id { get; set; }
    public string Hash1 { get; private set; }
    public string Hash2 { get; private set; }
    public long FileSize { get; private set; }
    public const string Salt = "Knowledge And Technology Joyfully Engaged is salting this data.";

    private FileHash(string filePath)
    {
        this.Id = Guid.NewGuid();

        // Calculate hash of file using MD5
        using (MD5 MD5 = MD5.Create())
        {
            byte[] hashBytes;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                hashBytes = MD5.ComputeHash(fs);
            }

            // Add salt to hash
            byte[] saltBytes = Encoding.UTF8.GetBytes(Salt);
            byte[] saltedHashBytes = new byte[hashBytes.Length + saltBytes.Length];
            Array.Copy(hashBytes, saltedHashBytes, hashBytes.Length);
            Array.Copy(saltBytes, 0, saltedHashBytes, hashBytes.Length, saltBytes.Length);

            // Store hash in Hex format
            this.Hash1 = BitConverter.ToString(saltedHashBytes).Replace("-", "");
        }

        // Calculate hash of file using SHA1
        using (SHA1 SHA1 = SHA1.Create())
        {
            byte[] hashBytes;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                hashBytes = SHA1.ComputeHash(fs);
            }

            // Add salt to hash
            byte[] saltBytes = Encoding.UTF8.GetBytes(Salt);
            byte[] saltedHashBytes = new byte[hashBytes.Length + saltBytes.Length];
            Array.Copy(hashBytes, saltedHashBytes, hashBytes.Length);
            Array.Copy(saltBytes, 0, saltedHashBytes, hashBytes.Length, saltBytes.Length);

            // Store hash in Hex format
            this.Hash2 = BitConverter.ToString(saltedHashBytes).Replace("-", "");
        }

        // Get file size
        this.FileSize = new FileInfo(filePath).Length;
    }

    public static FileHash Create(string filePath)
    {
        return new FileHash(filePath);
    }
}

public class FileHashContext : DbContext
{
    public DbSet<FileHash> FileHashes { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<FileHash>().HasIndex(x => new { x.Hash1, x.Hash2, x.FileSize }).IsUnique();
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseMariaDB("Server=katje.org;Database=FileData;User ID=FileManager;Password=123456;");
    }
}

What does the table look like? Give me the CREATE SQL code.

CREATE TABLE FileHash (
    Id BINARY(16) NOT NULL PRIMARY KEY,
    Hash1 VARCHAR(128) NOT NULL,
    Hash2 VARCHAR(128) NOT NULL,
    FileSize BIGINT NOT NULL,
    UNIQUE INDEX (Hash1, Hash2, FileSize)
);

Summarize the code.

FileHash is a class that stores the hashes and file size of a file. It uses the MD5 and SHA1 algorithms to generate the hashes, and also adds salt to the hashes for increased security. The FileHashContext class is a database context that uses MariaDB to store the FileHash objects. The database contains a table with columns for the Id, Hash1, Hash2, and FileSize, and an index that ensures that each combination of hashes and file sizes is unique.

It amazes me with how little instructions I managed to get all this code. And it looks okay to me. Thing is, I’m going to make some manual changes to this code to make it more my style, but having OpenAI create most of this code for me is definitely going to save me a lot of time in the future!

Will OpenAI and other AI replace developers? That is unlikely, as developers still have to evaluate the resulting code and someone has to actually tell the AI to what it needs to make. And while telling the AI to create it all, I also had to check the code over and over again and have the AI replace code I did not like.

Print your own cases, part 10 of 10

In the previous post and the post before I showed how I repair my models before they’re ready to print. The final step is actually uploading the model to Shapeways. This happens to be the most exciting part since it will tell you if there are any flaws in the final model.

I already had a lot of problems repairing the model and had to remove a small piece of it to make it manifold. But there are other problems that might occur when uploading a model to Shapeways. One of the more annoying things are loose parts that are too small to notice immediately. However, those very small parts might prevent the model from being printed because they’re smaller than the minimum bounding box. And you have to pay extra for multiple parts so you just don’t want those small, loose parts!

2016-04-20

And as I said, it has some very small, loose parts! These are actually caused by the chosen hair style, which seems to have strands of hair flying around her head. 

It would have been nice if Shapeways had a feature to remove these loose parts but all it does is tell me how large they are. One main part of 12.4×7.6×25/5 cm and three parts that are smaller than a tenth of a cubic millimeter. Those are the ones that prevent this model from being printed successfully!

So at this point I should actually fix this by choosing a different hair style. But I will use the MeshMixer trick again of separating all shells and then just remove all parts that seem too small to use. All small parts would already be too small to really get noticed so removing them won’t have much effects. Well, except in Shapeways, where the removal of the small pieces will hopefully result in a printable model.

2016-04-20 (1)

Uploading to Shapeways is a slow process which can take minutes before it is done. And even after the file is uploaded, it could still take some time before it is completely ready to be printed. But it is needed so Shapeways will show me where the loose parts are that need to be removed. To do so, I need give Shapeways to render the image for me that will display them for me. And one part is on her left front and the other two on her left back side of her head.

But it is easier to remember that I should not use this hairstyle for 3D models in the future. But for now, I will just try to fix this model without going back to Poser.

So, how do I fix this? Simple. I will go back to OpenSCAD and adjust the floor panel. I then import it again in Poser and give it the exact size and position as the old version. I will then change Anarani’s hair to a better hairstyle and go through the whole process again. And while it sounds like a lot of works,once you’ve done these steps over and over again, it becomes about half an hour work, including the time needed to wait for the system to render or calculate things. I won’t create a new artistic rendering, though. But the new model will be uploaded to Shapeways.

And once the upload was successful, I started noticing that the strings of her bikini top weren’t very visible in Shapeways. So, as the last fix for this model, I removed her top. The result was finally printable!

2016-04-20 (2).png

But the wall thickness is still a reason for the model to be rejected. Fortunately you can specify that you wanted it printed anyways when you order it, thus it will be printed. Problem is that it has some risky areas that might not print well. In this case, the skirt, the scarf and the hair will cause trouble.

A price has also been calculated. Including taxes, this model will cost me $101.86 if I want it. Right now, my budget prevents me from buying it, though.When 3D printing is a hobby, make sure you have a budget set aside for the amount that you can spend on these prints, else you’ll end up broke before you know it!

The price is reasonable for such a large figurine. Do keep in mind that it’s over 25 cm tall! I did save on the price by having the other two dimensions as short as possible, thus conserving machine space. I also made it hollow, which also reduces the costs. But the container for my device is still very large.

2016-04-20 (3)

Machine space is one important factor when printing in white plastic. The system is calculating a small, extra area around the model that would be off-limits for other printed items. When the model gets printed together with other objects, this space is important to make sure no two models get fused together! But the price of the model is based on the volume of the model and the machine space needed.

Now, the objects with the smallest machine space would be a sphere. Thus, the round shape of the box is saving me some space, even though it is big. It is actually the back panel that adds extra machine space, since the area between the panel and the model is added into the math.

Fortunately, they do calculate it very precise and at one point, the space between back panel and model is wide enough to allow a hole, else it would have been a bit more expensive. But Shapeways will tell you how much space it actually needs.

2016-04-20 (5)

Because I made a hollow mode, the material volume is quite low! White plastic costs $0.28 per cm³, thus this is only $18.44.

But the space costs $0.21 per cm³ and that adds up to $64.24. Add $1.50 for the start price for a single part print and I have a total of $84.18 excluding taxes. Taxes are 21% so the total price according to my calculations is $101.86.

So, what makes the 3D print so expensive? Mostly machine space, although that can be reduced by avoiding space-wasting areas in your model. Here, removal of the back panel should have saved me a bit of space. The space between her arms and legs are also added so because she’s standing on a plateau and holding an object, two ‘rings’ of print material are created and the space inside that ring is added to the material volume.

Put the legs wider apart could have saved some machine space, if it would be wide enough to allow a hole through the leg-ring. The same applies to her arms.

This model would actually cost $63.38 if I would print it in sandstone since you only pay for the material volume in sandstone. Sandstone does cost $0.75 per cm³ but because the model is hollow, that would basically be that 65 cm³. So it would be great to have it printed in sandstone, except for one major problem… Sandstone requires thicker materials. Supporting walls must be at least 2 mm and unsupported walls have to be even thicker!

2016-04-20 (6)

The heatmap of wall thickness shows how much of the model is at risk of failing when printed in sandstone. In this case, almost the whole Anarani part. The box itself also has areas that are too thin. Only the back panel seems to be strong enough!

Would other materials be an option? Considering the large size of the model, most materials would not qualify because the model is too big for the printers to handle. Metallic plastic would be an option but then you still pay for material volume and this plastic is more expensive than white plastic. $164.87 is quite a lot.

Frosted Ultra Detail is another option but even more expensive at $284.11 so I won’t even consider that as an option.

Stainless steel is an option but like sandstone, it has too many thin areas so it won’t print in the end. And for the other materials, the model is just too big…

I have created Poser models in colored sandstone, though. But these models are solid and I had to be real careful to avoid any thin parts. Especially hair and fingers turn out to be vulnerable. And the model needs to be strong enough to carry it’s own weight and is extremely vulnerable when it is just printed since the sandstone is still soft. Like the wet sand that’s used to make sandcastles.

Print your own cases, part 9 of 10

In the previous post I used NetFabb to repair my model. I will also show an alternative option here.

Since the repair in NetFabb went wrong in the previous step, I will do a repair using MeshLab instead. So I open MeshLab and import the hollow model. I also use the menu options ‘Render/Show non manif edges’ and ‘Render/Show non manif vertices’ to show the non manifold parts of my model.

If the geometry is non-manifold then that means that it cannot exist in the real world. In general, it means there are pieces that are disconnected or don’t fit perfectly. Those need to be fixed. And as the image shows, my model seems to have a lot of those, especially in the floor plane.

2016-04-19 (19)

I first start to fix the non-manifold edges. I use ‘Filters/Cleaning and Repairing/Select non-manifold edges’ to select them all and then I delete the current selection of faces and vertices. And when I do that, this happens:

2016-04-19 (20)

It removed a large piece of the floor plane!

So, I start over again with MeshLab and use ‘Filters/Cleaning and Repairing/Select non-manifold vertices’ and ‘Delete selected vertices’ instead. This needs to be repeated several times but it does the trick. The floor plane stay solid while the model is repaired. But it still isn’t enough. So I have to try to repair it with NetFabb again and this time I do an automatic repair but before accepting the repair, I select the triangles that cover the floor plane and remove them. That way, the floor plane gets its border back. Since it will have repaired most other issues, this will be the version I use for further attempts to repair it.

So, one solution would be to redo the whole model from the beginning. I would need to fix the floor plane, import it in Poser again, set it to the proper size, export all from Poser, remove the textures and merge all parts, rescale, cut and then try to repair it again. But as it turns out, there is another solution to remove that floor plane.

MeshMixer has an option ‘Edit/Separate shells’ which can be used to split the whole thing up in loose parts. I can then join all the parts again minus the floor plan. The floor plane is just cut away while keeping her foot intact. This is then exported again and repaired. And since the whole model was already manifold except for the floor plan, there isn’t much to be repaired to begin with.

This is what the model looks like now:

2016-04-19 (21)

The floor plane would have given her a better look and a way to stand on her own, but this is why I added the back plane with magnets anyway. The connections will be weaker, though.

The last part is printing the 3D object.

Print your own cases, part 8 of 10

In the previous post, I scaled my Poser model and removed the ruler. It is now time to do an automated fix.

2016-04-19 (17)

Once a model leaves MeshMixer, it is almost ready to be printed. However, when using the services of Shapeways it is always a good idea to check the model for any potential errors. This is where I use NetFabb Basic. 

In NetFabb I get my last view before I accept the model as something that would print well. As you can see, this is the hollowed model with two holes on her butt. They are large enough so any excess plastic can be removed from the model. But once you receive the 3D print, there can still be some excess material inside so you will still have to check if it is clean inside.

Hollow models have a challenge, since they increase the amount of polygons considerably. Where you just had only an outside, you now also have an inside. Sure, it is less material but Shapeways has a limitation in the number of polygons that are allowed. Fortunately, this model doesn’t go above that maximum.

It can also happen that the file size is larger than 64 MB. Shapeways can’t upload files bigger than that. That can also be solved easily by adding the file to a compressed .zip file and upload the .zip file. (Unless the .zip file is also larger than 64 MB, in which case your model is too complex to print.)

Repair is quite simple. I click on the red cross in the toolbar to initialize the repair options. I select ‘Automatic repair’ and then ‘Default repair’ and then just wait until it is done. Once done, click ‘Apply repair’ and have the old part removed. Then you should have a fine result.

However, in my case, something went wrong and the floor panel with its border became a solid block. This happened:

2016-04-19 (18)

And this is why you should repair it first in NetFabb, because Shapeways would do the repair in almost exactly the same way! In most cases things will go well but here I prefer to use MeshLab instead to repair the model manually.

I did try some manual repairs in NetFabb but they keep filling this floor plane so NetFabb doesn’t work as well as I hoped for this model.

Is there a way to fix this problem in NetFabb? I don’t know and might have to buy the professional version to find out. However, NetFabb happens to be too expensive for the rare times that I need it.

Still, one way to fix it is by redoing the OpenSCAD model and then start all over again from Poser until this post. I would need to remove the old back panel from the Poser model and put the new one in place at the proper size. I would then have to do all steps over again which is a bit annoying. So I will try again with MeshLab and if that fails, I’ll try some other solution.

In the next post I will show an alternative solution to repair models using MeshLab.

Print your own cases, part 7 of 10

In the previous post I cleaned the Poser model and made it a single object. Now comes the part where I start to scale and cut, and occasionally hollow my object.

2016-04-19 (13)

To start, open the .stl file from the earlier post in MeshMixer. And it will probably look like this:

Now, that is a minor annoyance. I will need to rotate and resize it first. I choose ‘Edit/Transform’ and do a ‘Rotate X’ for 90 degrees and put ‘Size Z’ to 600 mm which is the exact length of the ruler. Once it has the proper scale, I export the file to the folder 4 and import it again, replacing the current object in MeshMixer. I need to do this because MeshMixer gets a bit confused after resizing and the model looks ugly in the view. There’s nothing wrong with the model, though. It’s just MeshMixer having a bad render engine.

2016-04-19 (15)

Next, we will cut the ruler away. Using ‘Edit/Plane cut’ I rotate the cutting plane vertically and move it to somewhere between the model and the ruler. It will look something like this:

And once I click ‘Accept’, the ruler is gone! It is that simple. And now I will also be able to tell the exact sizes of my model. It is 124x255x76 mm in size. Slightly larger than expected.

So I’m going to add a simple trick to cut the amount of material in my model! I’m going to make her hollow! Using ‘Edit/Hollow’ I will get several options to make a hollow model. This will save materials and thus make the print less expensive. But it will require a few holes in the model.

2016-04-19 (16)

I set ‘Offset Distance’ to 1 mm since that’s thick enough. ‘Solid accuracy’ and ‘Mesh Density’ are set to 512 to get the best details and ‘Hole Radius’ will be 3 mm to allow good holes for excess materials to be removed from the hollow inside. And this also shows why you should remove the teeth, inner mouth, tongue and gums if the model has her mouth closed! Those parts would fill the inside of her head if they were still there. By removing them, there’s a slightly bigger hollow space.

I put two hollow openings on her butt, since her skirt is already covering that area. If she was wearing panties or a bikini bottom, those holes might not work out as well because the clothing adds an extra layer which the hole won’t go through. MeshMixer makes good hollow objects but they aren’t always perfect.

I don’t have to make the box or back panel hollow since they are already thin enough.

So now the model is almost ready to be printed. However, there can be some hidden flaws that need to be repaired. In the next post I will apply some automated repairs before the model is ready to be printed.

Print your own cases, part 6 of 10

In the previous post I created an artistic rendering of my model. I will now use 3D converter to remove the textures and unwanted parts and to turn it into one solid part for further processing.

Now, we will export the Poser model to a Wavefront .obj file. I generally use a numbered file structure where the first folder (1) will contain all the Poser models that I want to print. The next folder is the export folder where the exported Poser models go to. I have even more folders with the 8th folder being used for all models that are ready to upload to Shapeways. And the 9th folder has everything that I have uploaded as backup. So when I upload a model, that uploaded file will also be stored in this folder.

Only folders 1 and 9 are permanent. Once a model is successfully uploaded, I remove the related files from the in-between folders. They’re not needed anymore.

So I start to export my model to folder 2: export. The .obj file will have references to any textures used but I’m generally not interested in textures. Still, if you want a print in colored sandstone then you should do a second export to the Collada .dae file format. Then you will have a sub folder with all textures used in your model. Put those textures together with the .obj file and the .mtl file into a compressed .zip file and upload that compressed file to Shapeways for printing in colored sandstone. However, tools like NetFabb, MeshMixer en Meshlab tend to remove textures if you’re not careful. This makes scaling a bit difficult.

So, why not export to just Collada? Well, the problem is that Poser has a bad implementation of the Collada file format. While it is supposed to export things correctly, it has flaws preventing you to import the model in some other tool. Much of the parts of your model will be missing if you try. Which is why I only use it to get all textures together and not for further processing of the model.

2016-04-19 (9)

But this time I only want a white, plastic print so textures can be removed.

That’s what the model looks like in 3D converter. The OpenSCAD objects had no texture so they have random colors. But the cane, shoes and bikini have textures that 3D converter can’t find.

The first step is ‘Layers/Make All Opaque’ which I use to change all transparent areas. You can’t 3D print transparent areas anyways so make them opaque. And once you do that, you will notice the eyes losing their textures too. Why? Because Poser has two transparent objects in front of the iris and eye, which are meant to be used to add reflections. These are the Cornea and eye surface and once removed, you will see a normal eye again.

Next, use ‘Tools_2/Set White As Color For Textures’. to make all parts nice and white beneath the textures. Then, use ‘Tools_2/Erase Textures on All layers’ to remove all the textures and you should have a nice, white model. Or, if you forgot to give all parts a white color, you get this:

Anarani for blogpost
2016-04-19 (12)

This is not a big problem anyways and we will fix this once all parts are merged.

At this point, I start to select the parts that I want to merge. All other parts will be removed. So, deselect all parts and then select only those parts that you clearly need, like the face, body and the OpenSCAD objects. Keep in mind that the cornea and eye surface need to be removed to have a more detailed eye. And if the model has her mouth shut, you can also remove the gums, inner mouth, tongue and teeth.

Eyelashes can be selected and look good on large models, but will hide the eyes on smaller models. I decided to hide them in this model. But make sure you select the ruler since you will still need it!

Her shoes have small flowers and petals, which could become loose shells in Shapeway so those are also removed. Then choose “Merge Select” from the bottom buttons to merge all parts that you have selected. This makes one part from all of those parts. And at this point you can save the file as a StereoLithography .stl file in binary to continue processing in the next step. This export file will be in my 3rd folder.

In the next post I will scale the model to its proper size and remove the ruler.

Print your own cases, part 5 of 10

In the previous post I created a Poser model and a few OpenSCAD models and joined them into one. But before I continue to manipulate them to make them ready for 3D printing, I wanted to do an artistic rendering of the model, just to show off! This means that I want a complete background with water, trees and other stuff and the model in the middle of it all, well-lit and looking cool.

While it might seem a waste of time, it does give one extra view on your model before you continue processing. It will look okay but the OpenSCAD objects will not have any color. Problem is that painting those object cannot be done in Poser or OpenSCAD so if you want a specific coloring of those objects, you will need a special tool to do so.

2016-04-19 (4)

Modeling in Vue is quite easy. You just import the Poser model and then you put it where you want it to be. But once imported, you should turn down the highlights of the Poser model, else it starts to shine, which isn’t pretty. So, select the complete Poser model in Vue and click “Edit all materials” to change the highlights. 

Vue now has a value of 50% for my model. This is actually the highlight of one part of your model and not all parts! But if you change this value, it will change it for all.

2016-04-19 (6)

Since it has the value of 50%, I can simply overwrite it with 0. If it had been 0, I would have chosen the value of 1 instead.

I have already removed the ruler from the list of parts in Vue and I can easily find the other pieces that I’ve created because of their names. Unfortunately, Poser tends to name all figures “body” while all properties keep their old name. And that’s a bit annoying.

Often I will rename those parts but this will just be a quick render so, skip it.

Since I lack the tools to paint the OpenSCAD models, I will just pick a few from the materials that Vue already has. I decide to pick grass for the back panel because it always looks good to have a model walking on grass. And I pick dark smoked glass for the box. The cane will be gold, making it shine.

Next, I check the materials that are provided by Poser. The dress, for example, has a zipper which uses a reflection map. I hate those, because Vue does a full 360-degree view of everything if I want to. Reflection maps are a poor alternative for real reflections.

2016-04-19 (7)

I also decided to change the color of her bra. This won’t replace the texture but just the color. And I decide to pick an orange trim and green cloth, both pastel-tints.

2016-04-19 (8)

I also decide to put the sun in the background to create a kind of ‘eye in the sky’ so I also need a second light, which I put at the location of the camera. To get it there, I just select the camera, which will put it in the center of the views. When you add lights or objects, they will be put at the same place. Thus, the light is at the location of the camera!

And a quick preview of the image shows me that it will look good. So let the rendering start!

Now, one reason I use Vue to create an artistic image is because it allows me to use a transparent material for some of the more complex objects. In this case, that would be the box with its round shape. With the image rendered at a large resolution I can check the box for possible flaws, if I want to use it again with another model.

In my next post I will show how I clean the model using Accutrans 3D. In the mean time, this is what the rendered artwork looks like:

Anarani for blogpost

Print your own cases, part 4 of 10

In my previous post I created a round container for my electronic thermometer and now I need to add it to my Poser model. But I also need a special stand for Anarani to stand upon, with a back panel for a couple of magnets. Lets immediately start with the OpenSCAD script:

$fn=250;
difference(){
  union(){
    cube([60, 60, 6]); 
    translate([28, 0, 0]) cube([4, 3, 160]);
    translate([20, 1, 10]) cube([20, 2, 20]);
    translate([10, 1, 140]) cube([40, 2, 20]);
    translate([30, 1, 20]) rotate([90, 0, 0]) cylinder(d=12, h=1);
    translate([20, 1, 151]) rotate([90, 0, 0]) cylinder(d=12, h=1);
    translate([40, 1, 151]) rotate([90, 0, 0]) cylinder(d=12, h=1);
  }
  union(){
    translate([3, 3, 2]) cube([54, 54, 5]);
    translate([30, 1, 20]) rotate([90, 0, 0]) cylinder(d=10, h=2);
    translate([20, 1, 151]) rotate([90, 0, 0]) cylinder(d=10, h=2);
    translate([40, 1, 151]) rotate([90, 0, 0]) cylinder(d=10, h=2);
    translate([30, 2, 150])
    rotate([270, 180, 0]) height = 2) {
      text("Anarani", 
      size = 7, 
      font = "Harlow Solid Italic", 
      halign = "center", 
      valign = "center"
      );
    }
  }
}

This isn’t very special. A floor plate with an edge and a pole with two plates which will hold the magnets. As you may notice, there is no connection to the box that I created in the earlier post. That connector will be something from Poser. All you have to do now is to convert these models to WaveFront .obj files and you can import them in Poser. So, let’s combine them with Anarani! And this will show a few issues with importing in Poser.

2016-04-19
Anarani for blogpost II_0001

When you do import models in Poser, prefer to enable “Percent of standard figure size”. The reason for this is that the standard figure size is extremely small, compared to the imported objects. I will scale them anyways once they are imported and because their size is relative to Anarani, I can use integer values between 1 and 100 to scale them. Otherwise, I would need to scale them to very small numbers with fractions.

Now, to do a proper scaling, I will use the ruler to measure the height of the opening in the temperature holder, which should be 46 mm. I will then use the ruler to scale the back panel to the proper size, thus having it synchronized with the size of the box.

You could wonder why I don’t combine all three parts into one .obj file and import that one, but when I do that, it becomes just a single part. And I need to move them around, so that isn’t very practical.

So I end up with my model looking like the image on the right. The temperature box is too big and the ruler is extremely small. The back panel seems to be okay, though. But first I will have to put Anarani in a nice pose. And reconsider the clothing she’s wearing, since not all clothes will print well on Shapeways. (Hint: if a piece of clothing is transparent when you look at it from a specific angle in Poser then it will not print very well!)

The next step is trying to make everything fit. Since the box is quite large, I decide that Anarani will hold it above her head, thus making the model even taller. I don’t want it to go in all three directions because that would require more machine space, thus making it more costly. The final height will be about 22 cm and it’s 75 mm wide and about 60 mm deep. (The sizes are from the bottom panel and the box.) The ruler is set up vertically so I can use that to scale it to the proper length, which would be 60 cm. I will then cut away the ruler from the model and thus have the exact height, although I don’t think the width and depth will change much from my prediction.

Anarani for blogpost III_0001

Anarani will look like this image. One foot on the floor panel and a second one against the back panel. Both feet touch these panels so they should be connected, although the support will be tricky.

The ruler has moved towards the back and will be used in one of the next steps to set the proper scale of the model, before I will remove it.

The box itself is held up by her arms. Here, the hands will need to touch the box to make sure that connection is strong too. But they can’t connect too well, else the fingers will disappear.

To get things at the proper size, I started with matching the ruler to the length of the back panel, which was 16 cm. I then used this to scale the box so the vertical height of the opening is 46 mm. If I did the math well, my device should fit just nicely.

Anarani for blogpost IV_0001

I have given Anarani high heels to wear and replaced her top with a bikini. This bikini top has a clothing thickness property allowing me to set the thickness of it, thus making sure it prints better.

The skirt she’s wearing is also special, since it is one of the few skirt models I have that has both an inside and an outside. Most clothing props for Poser tend to just cover one side and the render engine is smart enough to come up with the other side, if it needs to be rendered. But when you want to print those props, then the thickness is unknown and the repair function of Shapeways will actually fill it all up, thus turning the inside of a skirt into a massive block. With this skirt, I still have a skirt that you can look under.

I won’t tell if she’s wearing a bikini bottom!

As an extra support for the box I used a cane prop from Poser and put it to the proper scale and thickness. It should add stability to the whole thing. making sure the bottom plate doesn’t bend over due to the weight of it all. Since there will be magnets on the back side, that bottom plate would not be supported and thus bend. This cane also required me to make Anarani bend slightly. After I put the hands in placed and locked their place, I moved her hip to the side and started to bend back her abdomen and chest to go near the cane again. Next, her neck was bent away from the cane and her head back to the cane so her neck and head (and hair, ear) would not touch the cane.

To make sure it is well-balanced, the whole box is in the center of the floor panel so it doesn’t matter that Anarani is leaning on her left foot. Gravity works downwards so the model won’t tilt to the left or right. Also, the border on top of the floor plane was added to make it stronger without making it much thicker.

I used a cane because the box is higher than the back panel. The cane adds a few more cm to this height. Add to this the height of the box (50 mm) and you get close to my estimation of 22 cm in total.

In my next post I will render the model in Vue, with some interesting textures, just to show what it will look like.

Print your own cases, part 3 of 10

In the earlier post I created a ruler so I can make sure that my box will have the exact size that I have specified. As I said, Poser loses this information, forcing me to fix the scale of the export file once I’m done with the model in Poser.

Temperature-Sensor
Mini Digital LCD Indoor Convenient Temperature Sensor Humidity Meter Thermometer Hygrometer Gauge

The device I will use is this thermometer that’s also shown on the left. (Image from AliExpress.) And the first thing I will have to do is measure it to get the exact dimensions. This is tricky because if you get the dimensions wrong, it either won’t fit or will be too loose to fit.

AliExpress does mention the size (3 cm x 4.8 cm x 1.6 cm) but these turn out to be incorrect! So, never assume the site will have exact measurements! Worse, this device has a small border that’s slightly bigger than the case itself, allowing a nice fit, but I need the size of the box, not the border. So, I take my ruler and start measuring the box. I end up with 45.75 mm x 25.9 mm x 13.5 mm. So, that’s the shape I need in OpenSCAD, which I will subtract from the real container.

The container itself needs to be hollow and must have enough space to contain the device. And for this one, I want a container that is round. That adds more complexity but it will look better. And I want my name on it, so people know it’s mine!

Making this shape isn’t difficult but you need to play around a bit. I did create the clock as a block to subtract from my shape and I did this to make sure that it fits. Especially the back should not have any holes from the corners of the device, otherwise, it won’t fit.

However, to create these oval shapes in OpenSCAD you need to create a round cylinder and a round sphere and then resize the width, height and depth to the required dimensions before subtracting the box. This slows down the rendering slightly, especially if you use high details.

And in the top of my script I use ‘$fn=250;’ which sets the detail level to a reasonable level. Simply put, OpenSCAD can’t create round shapes but can make a close estimate by using triangles and squares in a curve. With a value of 6, my shape would actually be a six-sided model. With 250, the round shape is actually made of 250 small, flat panels. Since I’ve set it to be 75 mm wide, those panels will be barely noticeable. Do keep in mind that the 3D printer won’t be able to make round shapes either so the value of 250 will be small enough to match the print resolution of Shapeways. But if you polish it, the shape will become more round.

Now, the script:

$fn=250;
module Box(){
  translate([-23, -13, 0]) union(){
    difference(){
      union(){
        translate([0, 0, 0]) cube([46, 26, 14]);
        translate([-2, -2, -2]) cube([50, 30, 2]);
      }
      union(){
        translate([23, 13, -0.1]) rotate([180, 0, 0]) linear_extrude(height = 2) {
          text("12:30", 
          size = 10, 
          font = "Lucida Console Regular", 
          halign = "center", 
          valign = "center"
        );
        } // text
      } // union
    } // difference
    difference(){
      translate([-2, -2, -3]) cube([50, 30, 2]);
      translate([0, 0, -3]) cube([46, 26, 14]);
    } // difference
  } // union
}

difference(){
  resize(newsize=[75, 50, 27.5]) union(){
    cylinder(d=75, h=2);
    difference(){
      sphere(d=75);
      union(){
        sphere(d=72);
        translate([0, 0, 2-75/2]) cube(75, center=true);
      } // union
    } // difference
  } // union
  union(){
    Box();
    translate([0, -19, 1]) rotate([180, 0, 0]) linear_extrude(height = 1) {
      text("W.A. ten Brink", 
      size = 4, 
      font = "Lucida Console Regular", 
      halign = "center", 
      valign = "center"
    );
    } // text
  } // union
}

This time I did not create a separate method for the texts simply because I use only two texts of different sizes. Creating a module for that would require an additional parameter and the text function isn’t that complex.

I first create the box including a border and make it look a bit pretty. I make sure that the box-part that needs to be subtracted aligns to the center of the X-Y plane and lies against the zero Z plane. The border will stick out anyways but it allows me an easier way to put it in the proper place. Because of this, I don’t need to translate the position of the box.

Please, do notice that the text on the box is offset at 1/10th of a millimeter because else a thin piece of those numbers will become part of the rendering! Those would become loose parts so I need to add an offset. This is something you have to do when you do into the negative parts. I should actually do the same for the border but actually like the small line that it adds. It won’t be really noticeable when printed, though. But in the 3D software it will be visible as a thin line.

The dimensions of this box are 75x50x27.5 mm which is a bit large. Then again, the device itself isn’t that small either.

Like the ruler, I uploaded this model to Shapeways to get an estimate of the price and looks. It has slightly more volume as my ruler but the price is more than double of my ruler! The reason for this is because the price for plastic is determined by the volume of the model and the machine space that it takes. And although my ruler was long, it was also thin and not so high, thus it did not need as much space as this model.

In my next post I will combine this model with my model Anarani. In that post, I will also create the platform for Anarani to stand upon, although that won’t be very special.